From 00433a512c1482fcf54afa920f2bbd30fc3cd532 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Thu, 24 Apr 2014 12:14:32 +0000 Subject: [PATCH] [OLE32_WINETEST] * Sync with Wine 1.7.17. CORE-8080 svn path=/trunk/; revision=62939 --- rostests/winetests/ole32/compobj.c | 278 +++++++++--- rostests/winetests/ole32/defaulthandler.c | 18 +- rostests/winetests/ole32/dragdrop.c | 191 +++++++- rostests/winetests/ole32/marshal.c | 528 +++++++++++++++++----- rostests/winetests/ole32/ole2.c | 401 +++++++++++++++- rostests/winetests/ole32/ole_server.c | 39 +- rostests/winetests/ole32/propvariant.c | 117 ++++- rostests/winetests/ole32/stg_prop.c | 1 + rostests/winetests/ole32/storage32.c | 69 ++- rostests/winetests/ole32/usrmarshal.c | 8 +- 10 files changed, 1398 insertions(+), 252 deletions(-) diff --git a/rostests/winetests/ole32/compobj.c b/rostests/winetests/ole32/compobj.c index b6fda82d765..fb68b347f32 100644 --- a/rostests/winetests/ole32/compobj.c +++ b/rostests/winetests/ole32/compobj.c @@ -37,7 +37,7 @@ //#include "objbase.h" //#include "shlguid.h" #include -//#include "urlmon.h" /* for CLSID_FileProtocol */ +#include /* for CLSID_FileProtocol */ #include @@ -68,32 +68,26 @@ static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; +static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; +static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } }; -static WCHAR stdfont[] = {'S','t','d','F','o','n','t',0}; +DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); + +static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0}; static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0}; -static WCHAR wszCLSID_StdFont[] = +static const WCHAR wszCLSID_StdFont[] = { '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-', '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0 }; static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0}; +static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-', + 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0}; DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd); DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd); -static const char *debugstr_guid(REFIID riid) -{ - static char buf[50]; - - sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], - riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4], - riid->Data4[5], riid->Data4[6], riid->Data4[7]); - - return buf; -} - static LONG cLocks; static void LockModule(void) @@ -207,7 +201,13 @@ static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie) actctx.lpSource = path; handle = pCreateActCtxW(&actctx); - ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */, + "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError()); + if (handle == INVALID_HANDLE_VALUE) + { + win_skip("activation context generation failed, some tests will be skipped\n"); + handle = NULL; + } ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize); ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags); @@ -221,8 +221,11 @@ static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie) DeleteFileA("file.manifest"); - ret = pActivateActCtx(handle, cookie); - ok(ret, "ActivateActCtx failed: %u\n", GetLastError()); + if (handle) + { + ret = pActivateActCtx(handle, cookie); + ok(ret, "ActivateActCtx failed: %u\n", GetLastError()); + } return handle; } @@ -232,6 +235,14 @@ static const char actctx_manifest[] = "" "" +" " +" " " " +" " +" ProgId.ProgId.1" +" " " " +" " +" clrprogid.1" +" " ""; DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0); @@ -297,22 +317,24 @@ static void test_ProgIDFromCLSID(void) static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0}; hr = ProgIDFromCLSID(&CLSID_non_existent, &progid); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); - if (hr == S_OK) - { - ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid)); - CoTaskMemFree(progid); - } + ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid)); + CoTaskMemFree(progid); /* try something registered and redirected */ progid = NULL; hr = ProgIDFromCLSID(&CLSID_StdFont, &progid); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid)); CoTaskMemFree(progid); + /* classes without default progid, progid list is not used */ + hr = ProgIDFromCLSID(&IID_Testiface5, &progid); + ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr); + + hr = ProgIDFromCLSID(&IID_Testiface6, &progid); + ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr); + pDeactivateActCtx(0, cookie); pReleaseActCtx(handle); } @@ -354,14 +376,20 @@ static void test_CLSIDFromProgID(void) { GUID clsid1; + memset(&clsid, 0xcc, sizeof(clsid)); + hr = CLSIDFromProgID(wszNonExistent, &clsid); + ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n"); + + /* CLSIDFromString() doesn't check activation context */ + hr = CLSIDFromString(progidW, &clsid); + ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr); + clsid = CLSID_NULL; hr = CLSIDFromProgID(progidW, &clsid); -todo_wine - ok(hr == S_OK, "got 0x%08x\n", hr); - if (hr == S_OK) - /* it returns generated CLSID here */ - ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL), - "got wrong clsid %s\n", debugstr_guid(&clsid)); + /* it returns generated CLSID here */ + ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL), + "got wrong clsid %s\n", wine_dbgstr_guid(&clsid)); /* duplicate progid present in context - returns generated guid here too */ clsid = CLSID_NULL; @@ -370,9 +398,8 @@ todo_wine clsid1 = CLSID_StdFont; /* that's where it differs from StdFont */ clsid1.Data4[7] = 0x52; -todo_wine ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1), - "got %s\n", debugstr_guid(&clsid)); + "got %s\n", wine_dbgstr_guid(&clsid)); pDeactivateActCtx(0, cookie); pReleaseActCtx(handle); @@ -389,10 +416,17 @@ static void test_CLSIDFromString(void) ok_ole_success(hr, "CLSIDFromString"); ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); + memset(&clsid, 0xab, sizeof(clsid)); hr = CLSIDFromString(NULL, &clsid); - ok_ole_success(hr, "CLSIDFromString"); + ok(hr == S_OK, "got 0x%08x\n", hr); ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n"); + /* string is longer, but starts with a valid CLSID */ + memset(&clsid, 0, sizeof(clsid)); + hr = CLSIDFromString(cf_brokenW, &clsid); + ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr); + ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid)); + lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont); for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++) wszCLSID_Broken[i] = 'A'; @@ -448,6 +482,68 @@ static void test_CLSIDFromString(void) ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2); } +static void test_IIDFromString(void) +{ + static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-', + 'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0}; + static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-', + 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0}; + static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-', + 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0}; + static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-', + 'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0}; + HRESULT hr; + IID iid; + + hr = IIDFromString(wszCLSID_StdFont, &iid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid)); + + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(NULL, &iid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid)); + + hr = IIDFromString(cfW, &iid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid)); + + /* string starts with a valid IID but is longer */ + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(cf_brokenW, &iid); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1); + + /* invalid IID in a valid format */ + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(brokenW, &iid); + ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr); + ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1); + + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(broken2W, &iid); + ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr); + ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1); + + /* format is broken, but string length is okay */ + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(broken3W, &iid); + ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr); + ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1); + + /* invalid string */ + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(wszNonExistent, &iid); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1); + + /* valid ProgID */ + memset(&iid, 0xab, sizeof(iid)); + hr = IIDFromString(stdfont, &iid); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1); +} + static void test_StringFromGUID2(void) { WCHAR str[50]; @@ -539,10 +635,10 @@ static void test_CoCreateInstance(void) /* show that COM doesn't have to be initialized for multi-threaded apartments if another thread has already done so */ - info.wait = CreateEvent(NULL, TRUE, FALSE, NULL); + info.wait = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError()); - info.stop = CreateEvent(NULL, TRUE, FALSE, NULL); + info.stop = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError()); thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid); @@ -570,8 +666,9 @@ static void test_CoCreateInstance(void) static void test_CoGetClassObject(void) { HRESULT hr; - HANDLE thread; + HANDLE thread, handle; DWORD tid, exitcode; + ULONG_PTR cookie; IUnknown *pUnk; struct info info; REFCLSID rclsid = &CLSID_InternetZoneManager; @@ -590,10 +687,10 @@ static void test_CoGetClassObject(void) /* show that COM doesn't have to be initialized for multi-threaded apartments if another thread has already done so */ - info.wait = CreateEvent(NULL, TRUE, FALSE, NULL); + info.wait = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError()); - info.stop = CreateEvent(NULL, TRUE, FALSE, NULL); + info.stop = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError()); thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid); @@ -635,7 +732,7 @@ static void test_CoGetClassObject(void) { IUnknown_Release(pUnk); - res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0, + res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); ok(!res, "RegCreateKeyEx returned %d\n", res); @@ -651,26 +748,42 @@ static void test_CoGetClassObject(void) if (hr == S_OK) IUnknown_Release(pUnk); RegCloseKey(hkey); } + + hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk); + ok(hr == S_OK, "got 0x%08x\n", hr); + IUnknown_Release(pUnk); + + /* context redefines FreeMarshaler CLSID */ + if ((handle = activate_context(actctx_manifest, &cookie))) + { + hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk); + ok(hr == S_OK, "got 0x%08x\n", hr); + IUnknown_Release(pUnk); + + pDeactivateActCtx(0, cookie); + pReleaseActCtx(handle); + } + CoUninitialize(); } static ATOM register_dummy_class(void) { - WNDCLASS wc = + WNDCLASSA wc = { 0, - DefWindowProc, + DefWindowProcA, 0, 0, - GetModuleHandle(NULL), + GetModuleHandleA(NULL), NULL, - LoadCursor(NULL, IDC_ARROW), + LoadCursorA(NULL, (LPSTR)IDC_ARROW), (HBRUSH)(COLOR_BTNFACE+1), NULL, - TEXT("WineOleTestClass"), + "WineOleTestClass", }; - return RegisterClass(&wc); + return RegisterClassA(&wc); } static void test_ole_menu(void) @@ -678,7 +791,7 @@ static void test_ole_menu(void) HWND hwndFrame; HRESULT hr; - hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); + hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL); todo_wine ok_ole_success(hr, "OleSetMenuDescriptor"); @@ -974,8 +1087,8 @@ static void test_CoGetPSClsid(void) hr = CoGetPSClsid(&IID_IClassFactory, &clsid); ok_ole_success(hr, "CoGetPSClsid"); - res = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &hkey, NULL); + res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0, + KEY_ALL_ACCESS, NULL, &hkey, NULL); ok(!res, "RegCreateKeyEx returned %d\n", res); res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey); @@ -995,27 +1108,34 @@ static void test_CoGetPSClsid(void) if ((handle = activate_context(actctx_manifest, &cookie))) { -todo_wine { memset(&clsid, 0, sizeof(clsid)); hr = CoGetPSClsid(&IID_Testiface, &clsid); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", debugstr_guid(&clsid)); + ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid)); memset(&clsid, 0, sizeof(clsid)); hr = CoGetPSClsid(&IID_Testiface2, &clsid); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", debugstr_guid(&clsid)); + ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid)); memset(&clsid, 0, sizeof(clsid)); hr = CoGetPSClsid(&IID_Testiface3, &clsid); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", debugstr_guid(&clsid)); + ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid)); memset(&clsid, 0xaa, sizeof(clsid)); hr = CoGetPSClsid(&IID_Testiface4, &clsid); ok(hr == S_OK, "got 0x%08x\n", hr); - ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", debugstr_guid(&clsid)); -} + ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid)); + + /* register same interface and try to get CLSID back */ + hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4); + ok(hr == S_OK, "got 0x%08x\n", hr); + memset(&clsid, 0, sizeof(clsid)); + hr = CoGetPSClsid(&IID_Testiface, &clsid); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid)); + pDeactivateActCtx(0, cookie); pReleaseActCtx(handle); } @@ -1138,6 +1258,8 @@ static void test_CoMarshalInterThreadInterfaceInStream(void) static void test_CoRegisterClassObject(void) { + ULONG_PTR ctxcookie; + HANDLE handle; DWORD cookie; HRESULT hr; IClassFactory *pcf; @@ -1213,6 +1335,33 @@ static void test_CoRegisterClassObject(void) if (0) CoRevokeClassObject(cookie); + /* test that object is accessible */ + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER, + REGCLS_MULTIPLEUSE, &cookie); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); + ok(hr == S_OK, "got 0x%08x\n", hr); + IClassFactory_Release(pcf); + + /* context now contains CLSID_WineOOPTest, test if registered one could still be used */ + if ((handle = activate_context(actctx_manifest, &ctxcookie))) + { + hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); +todo_wine + ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr); + + pDeactivateActCtx(0, ctxcookie); + pReleaseActCtx(handle); + } + + hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf); + ok(hr == S_OK, "got 0x%08x\n", hr); + IClassFactory_Release(pcf); + + hr = CoRevokeClassObject(cookie); + ok(hr == S_OK, "got 0x%08x\n", hr); + CoUninitialize(); } @@ -1394,7 +1543,7 @@ static DWORD CALLBACK free_libraries_thread(LPVOID p) static inline BOOL is_module_loaded(const char *module) { - return GetModuleHandle(module) != 0; + return GetModuleHandleA(module) != 0; } static void test_CoFreeUnusedLibraries(void) @@ -1466,10 +1615,10 @@ static void test_CoGetObjectContext(void) /* show that COM doesn't have to be initialized for multi-threaded apartments if another thread has already done so */ - info.wait = CreateEvent(NULL, TRUE, FALSE, NULL); + info.wait = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError()); - info.stop = CreateEvent(NULL, TRUE, FALSE, NULL); + info.stop = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError()); thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid); @@ -1685,10 +1834,10 @@ static void test_CoGetContextToken(void) /* show that COM doesn't have to be initialized for multi-threaded apartments if another thread has already done so */ - info.wait = CreateEvent(NULL, TRUE, FALSE, NULL); + info.wait = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError()); - info.stop = CreateEvent(NULL, TRUE, FALSE, NULL); + info.stop = CreateEventA(NULL, TRUE, FALSE, NULL); ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError()); thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid); @@ -1817,21 +1966,18 @@ static void test_OleRegGetMiscStatus(void) { status = 0; hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status); -todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status); -} + /* context data takes precedence over registration info */ status = 0; hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status); /* there's no such attribute in context */ status = -1; hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); ok(status == 0, "got 0x%08x\n", status); @@ -1869,9 +2015,13 @@ START_TEST(compobj) return; } + if (!pCreateActCtxW) + win_skip("Activation contexts are not supported, some tests will be skipped.\n"); + test_ProgIDFromCLSID(); test_CLSIDFromProgID(); test_CLSIDFromString(); + test_IIDFromString(); test_StringFromGUID2(); test_CoCreateInstance(); test_ole_menu(); diff --git a/rostests/winetests/ole32/defaulthandler.c b/rostests/winetests/ole32/defaulthandler.c index 619393f0baf..d8119b1b67f 100644 --- a/rostests/winetests/ole32/defaulthandler.c +++ b/rostests/winetests/ole32/defaulthandler.c @@ -69,18 +69,6 @@ DEFINE_EXPECT(CF_QueryInterface_ClassFactory); DEFINE_EXPECT(CF_CreateInstance); DEFINE_EXPECT(CF_QueryInterface_IMarshal); -static const char *debugstr_guid(REFIID riid) -{ - static char buf[50]; - - sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], - riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4], - riid->Data4[5], riid->Data4[6], riid->Data4[7]); - - return buf; -} - static HRESULT create_storage(IStorage **stg) { HRESULT hr; @@ -199,7 +187,7 @@ static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID r return S_OK; } - ok(0, "unexpected interface: %s\n", debugstr_guid(riid)); + ok(0, "unexpected interface: %s\n", wine_dbgstr_guid(riid)); *ppv = NULL; return E_NOINTERFACE; } @@ -220,7 +208,7 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, CHECK_EXPECT(CF_CreateInstance); ok(pUnkOuter == NULL, "pUnkOuter != NULL\n"); - todo_wine ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", debugstr_guid(riid)); + todo_wine ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", wine_dbgstr_guid(riid)); if(IsEqualGUID(riid, &IID_IOleObject)) { *ppv = NULL; return E_NOINTERFACE; @@ -257,7 +245,7 @@ static void test_default_handler_run(void) DWORD class_reg; HRESULT hres; - if(!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx")) { + if(!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) { win_skip("skipping OleCreateDefaultHandler tests\n"); return; } diff --git a/rostests/winetests/ole32/dragdrop.c b/rostests/winetests/ole32/dragdrop.c index 83a7872b609..20ed8646385 100644 --- a/rostests/winetests/ole32/dragdrop.c +++ b/rostests/winetests/ole32/dragdrop.c @@ -36,6 +36,40 @@ #include +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(DataObject_EnumFormatEtc); +DEFINE_EXPECT(EnumFORMATETC_Next); +DEFINE_EXPECT(EnumFORMATETC_Reset); +DEFINE_EXPECT(DataObject_QueryGetData); +DEFINE_EXPECT(DropSource_QueryContinueDrag); +DEFINE_EXPECT(DropTarget_DragEnter); +DEFINE_EXPECT(DropSource_GiveFeedback); +DEFINE_EXPECT(DropTarget_Drop); +DEFINE_EXPECT(DropTarget_DragLeave); + static int droptarget_refs; /* helper macros to make tests a bit leaner */ @@ -73,7 +107,9 @@ static HRESULT WINAPI DropTarget_DragEnter(IDropTarget* iface, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { - return E_NOTIMPL; + CHECK_EXPECT(DropTarget_DragEnter); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; } static HRESULT WINAPI DropTarget_DragOver(IDropTarget* iface, @@ -81,11 +117,14 @@ static HRESULT WINAPI DropTarget_DragOver(IDropTarget* iface, POINTL pt, DWORD* pdwEffect) { - return E_NOTIMPL; + ok(0, "unexpected call\n"); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; } static HRESULT WINAPI DropTarget_DragLeave(IDropTarget* iface) { + CHECK_EXPECT(DropTarget_DragLeave); return E_NOTIMPL; } @@ -93,7 +132,8 @@ static HRESULT WINAPI DropTarget_Drop(IDropTarget* iface, IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { - return E_NOTIMPL; + CHECK_EXPECT(DropTarget_Drop); + return 0xbeefbeef; } static const IDropTargetVtbl DropTarget_VTbl = @@ -109,7 +149,6 @@ static const IDropTargetVtbl DropTarget_VTbl = static IDropTarget DropTarget = { &DropTarget_VTbl }; -/** stub IDropSource **/ static HRESULT WINAPI DropSource_QueryInterface(IDropSource *iface, REFIID riid, void **ppObj) { if (IsEqualIID(riid, &IID_IUnknown) || @@ -137,7 +176,7 @@ static HRESULT WINAPI DropSource_QueryContinueDrag( BOOL fEscapePressed, DWORD grfKeyState) { - /* always drop */ + CHECK_EXPECT(DropSource_QueryContinueDrag); return DRAGDROP_S_DROP; } @@ -145,6 +184,7 @@ static HRESULT WINAPI DropSource_GiveFeedback( IDropSource *iface, DWORD dwEffect) { + CHECK_EXPECT(DropSource_GiveFeedback); return DRAGDROP_S_USEDEFAULTCURSORS; } @@ -158,7 +198,75 @@ static const IDropSourceVtbl dropsource_vtbl = { static IDropSource DropSource = { &dropsource_vtbl }; -/** IDataObject stub **/ +static HRESULT WINAPI EnumFORMATETC_QueryInterface(IEnumFORMATETC *iface, + REFIID riid, void **ppvObj) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static ULONG WINAPI EnumFORMATETC_AddRef(IEnumFORMATETC *iface) +{ + return 2; +} + +static ULONG WINAPI EnumFORMATETC_Release(IEnumFORMATETC *iface) +{ + return 1; +} + +static BOOL formats_enumerated; +static HRESULT WINAPI EnumFORMATETC_Next(IEnumFORMATETC *iface, + ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) +{ + static FORMATETC format = { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + CHECK_EXPECT2(EnumFORMATETC_Next); + + ok(celt == 1, "celt = %d\n", celt); + ok(rgelt != NULL, "rgelt == NULL\n"); + ok(pceltFetched == NULL, "pceltFetched != NULL\n"); + + if(formats_enumerated) + return S_FALSE; + + *rgelt = format; + formats_enumerated = TRUE; + return S_OK; +} + +static HRESULT WINAPI EnumFORMATETC_Skip(IEnumFORMATETC *iface, ULONG celt) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumFORMATETC_Reset(IEnumFORMATETC *iface) +{ + CHECK_EXPECT(EnumFORMATETC_Reset); + formats_enumerated = FALSE; + return S_OK; +} + +static HRESULT WINAPI EnumFORMATETC_Clone(IEnumFORMATETC *iface, + IEnumFORMATETC **ppenum) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static const IEnumFORMATETCVtbl enumformatetc_vtbl = { + EnumFORMATETC_QueryInterface, + EnumFORMATETC_AddRef, + EnumFORMATETC_Release, + EnumFORMATETC_Next, + EnumFORMATETC_Skip, + EnumFORMATETC_Reset, + EnumFORMATETC_Clone +}; + +static IEnumFORMATETC EnumFORMATETC = { &enumformatetc_vtbl }; + static HRESULT WINAPI DataObject_QueryInterface( IDataObject *iface, REFIID riid, @@ -171,6 +279,8 @@ static HRESULT WINAPI DataObject_QueryInterface( IDataObject_AddRef(iface); return S_OK; } + + trace("DataObject_QueryInterface: %s\n", wine_dbgstr_guid(riid)); return E_NOINTERFACE; } @@ -189,6 +299,7 @@ static HRESULT WINAPI DataObject_GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -197,6 +308,7 @@ static HRESULT WINAPI DataObject_GetDataHere( FORMATETC *pformatetc, STGMEDIUM *pmedium) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -204,6 +316,7 @@ static HRESULT WINAPI DataObject_QueryGetData( IDataObject *iface, FORMATETC *pformatetc) { + CHECK_EXPECT(DataObject_QueryGetData); return S_OK; } @@ -212,6 +325,7 @@ static HRESULT WINAPI DataObject_GetCanonicalFormatEtc( FORMATETC *pformatectIn, FORMATETC *pformatetcOut) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -221,6 +335,7 @@ static HRESULT WINAPI DataObject_SetData( STGMEDIUM *pmedium, BOOL fRelease) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -229,6 +344,9 @@ static HRESULT WINAPI DataObject_EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) { + CHECK_EXPECT(DataObject_EnumFormatEtc); + *ppenumFormatEtc = &EnumFORMATETC; + formats_enumerated = FALSE; return S_OK; } @@ -239,6 +357,7 @@ static HRESULT WINAPI DataObject_DAdvise( IAdviseSink *pAdvSink, DWORD *pdwConnection) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -246,6 +365,7 @@ static HRESULT WINAPI DataObject_DUnadvise( IDataObject *iface, DWORD dwConnection) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -253,6 +373,7 @@ static HRESULT WINAPI DataObject_EnumDAdvise( IDataObject *iface, IEnumSTATDATA **ppenumAdvise) { + ok(0, "unexpected call\n"); return E_NOTIMPL; } @@ -275,21 +396,21 @@ static IDataObject DataObject = { &dataobject_vtbl }; static ATOM register_dummy_class(void) { - WNDCLASS wc = + WNDCLASSA wc = { 0, - DefWindowProc, + DefWindowProcA, 0, 0, - GetModuleHandle(NULL), + GetModuleHandleA(NULL), NULL, - LoadCursor(NULL, IDC_ARROW), + LoadCursorA(NULL, (LPSTR)IDC_ARROW), (HBRUSH)(COLOR_BTNFACE+1), NULL, - TEXT("WineOleTestClass"), + "WineOleTestClass", }; - return RegisterClass(&wc); + return RegisterClassA(&wc); } static void test_Register_Revoke(void) @@ -367,9 +488,10 @@ static void test_DoDragDrop(void) DWORD effect; HRESULT hr; HWND hwnd; + RECT rect; - hwnd = CreateWindowA("WineOleTestClass", "Test", 0, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, + hwnd = CreateWindowExA(WS_EX_TOPMOST, "WineOleTestClass", "Test", 0, + CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, NULL, NULL); ok(IsWindow(hwnd), "failed to create window\n"); @@ -401,6 +523,47 @@ static void test_DoDragDrop(void) hr = DoDragDrop(&DataObject, NULL, 0, &effect); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + ShowWindow(hwnd, SW_SHOW); + GetWindowRect(hwnd, &rect); + ok(SetCursorPos(rect.left+50, rect.top+50), "SetCursorPos failed\n"); + SET_EXPECT(DataObject_EnumFormatEtc); + SET_EXPECT(EnumFORMATETC_Next); + SET_EXPECT(EnumFORMATETC_Reset); + SET_EXPECT(DataObject_QueryGetData); + SET_EXPECT(DropSource_QueryContinueDrag); + SET_EXPECT(DropTarget_DragEnter); + SET_EXPECT(DropSource_GiveFeedback); + SET_EXPECT(DropTarget_Drop); + hr = DoDragDrop(&DataObject, &DropSource, DROPEFFECT_COPY, &effect); + ok(hr == 0xbeefbeef, "got 0x%08x\n", hr); + todo_wine CHECK_CALLED(DataObject_EnumFormatEtc); + todo_wine CHECK_CALLED(EnumFORMATETC_Next); + todo_wine CHECK_CALLED(EnumFORMATETC_Reset); + todo_wine CHECK_CALLED(DataObject_QueryGetData); + CHECK_CALLED(DropSource_QueryContinueDrag); + CHECK_CALLED(DropTarget_DragEnter); + CHECK_CALLED(DropSource_GiveFeedback); + CHECK_CALLED(DropTarget_Drop); + + SET_EXPECT(DataObject_EnumFormatEtc); + SET_EXPECT(EnumFORMATETC_Next); + SET_EXPECT(EnumFORMATETC_Reset); + SET_EXPECT(DataObject_QueryGetData); + SET_EXPECT(DropSource_QueryContinueDrag); + SET_EXPECT(DropTarget_DragEnter); + SET_EXPECT(DropSource_GiveFeedback); + SET_EXPECT(DropTarget_DragLeave); + hr = DoDragDrop(&DataObject, &DropSource, 0, &effect); + ok(hr == DRAGDROP_S_DROP, "got 0x%08x\n", hr); + todo_wine CHECK_CALLED(DataObject_EnumFormatEtc); + todo_wine CHECK_CALLED(EnumFORMATETC_Next); + todo_wine CHECK_CALLED(EnumFORMATETC_Reset); + todo_wine CHECK_CALLED(DataObject_QueryGetData); + CHECK_CALLED(DropSource_QueryContinueDrag); + CHECK_CALLED(DropTarget_DragEnter); + CHECK_CALLED(DropSource_GiveFeedback); + CHECK_CALLED(DropTarget_DragLeave); + OleUninitialize(); DestroyWindow(hwnd); diff --git a/rostests/winetests/ole32/marshal.c b/rostests/winetests/ole32/marshal.c index 9430ff9022e..fd1ddc02465 100644 --- a/rostests/winetests/ole32/marshal.c +++ b/rostests/winetests/ole32/marshal.c @@ -53,6 +53,9 @@ static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID); #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks) #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks) #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) +#define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0); +#define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0); +#define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0); static const IID IID_IWineTest = { @@ -113,6 +116,52 @@ static void UnlockModule(void) InterlockedDecrement(&cLocks); } +static BOOL with_external_conn; +static DWORD external_connections; +static BOOL last_release_closes; + +static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv) +{ + ok(0, "unxpected call\n"); + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface) +{ + return 2; +} + +static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface) +{ + return 1; +} + +static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved) +{ + trace("add connection\n"); + return ++external_connections; +} + + +static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn, + DWORD reserved, BOOL fLastReleaseCloses) +{ + trace("release connection %d\n", fLastReleaseCloses); + last_release_closes = fLastReleaseCloses; + return --external_connections; +} + +static const IExternalConnectionVtbl ExternalConnectionVtbl = { + ExternalConnection_QueryInterface, + ExternalConnection_AddRef, + ExternalConnection_Release, + ExternalConnection_AddConnection, + ExternalConnection_ReleaseConnection +}; + +static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl }; + static HRESULT WINAPI Test_IUnknown_QueryInterface( LPUNKNOWN iface, @@ -171,6 +220,12 @@ static HRESULT WINAPI Test_IClassFactory_QueryInterface( return S_OK; } + if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection)) + { + *ppvObj = &ExternalConnection; + return S_OK; + } + *ppvObj = NULL; return E_NOINTERFACE; } @@ -247,11 +302,11 @@ static DWORD CALLBACK host_object_proc(LPVOID p) ok_ole_success(hr, CoMarshalInterface); /* force the message queue to be created before signaling parent thread */ - PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); SetEvent(data->marshal_event); - while (GetMessage(&msg, NULL, 0, 0)) + while (GetMessageA(&msg, NULL, 0, 0)) { if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) { @@ -259,7 +314,7 @@ static DWORD CALLBACK host_object_proc(LPVOID p) SetEvent((HANDLE)msg.lParam); } else - DispatchMessage(&msg); + DispatchMessageA(&msg); } HeapFree(GetProcessHeap(), 0, data); @@ -272,7 +327,7 @@ static DWORD CALLBACK host_object_proc(LPVOID p) static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread) { DWORD tid = 0; - HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL); + HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL); struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)); data->stream = stream; @@ -298,17 +353,17 @@ static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, M /* asks thread to release the marshal data because it has to be done by the * same thread that marshaled the interface in the first place. */ -static void release_host_object(DWORD tid) +static void release_host_object(DWORD tid, WPARAM wp) { - HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL); - PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event); + HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL); + PostThreadMessageA(tid, RELEASEMARSHALDATA, wp, (LPARAM)event); ok( !WaitForSingleObject(event, 10000), "wait timed out\n" ); CloseHandle(event); } static void end_host_object(DWORD tid, HANDLE thread) { - BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0); + BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0); ok(ret, "PostThreadMessage failed with error %d\n", GetLastError()); /* be careful of races - don't return until hosting thread has terminated */ ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); @@ -337,6 +392,7 @@ static void test_normal_marshal_and_release(void) IStream *pStream = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -344,6 +400,7 @@ static void test_normal_marshal_and_release(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -351,6 +408,8 @@ static void test_normal_marshal_and_release(void) IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); } /* tests success case of a same-thread marshal and unmarshal */ @@ -361,6 +420,7 @@ static void test_normal_marshal_and_unmarshal(void) IUnknown *pProxy = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -368,6 +428,7 @@ static void test_normal_marshal_and_unmarshal(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -375,6 +436,8 @@ static void test_normal_marshal_and_unmarshal(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_zero_external_conn(); + ok_last_release_closes(FALSE); IUnknown_Release(pProxy); @@ -392,18 +455,22 @@ static void test_marshal_and_unmarshal_invalid(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); - + ok_non_zero_external_conn(); + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); ok_ole_success(hr, CoReleaseMarshalData); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -432,6 +499,7 @@ static void test_same_apartment_unmarshal_failure(void) static const LARGE_INTEGER llZero; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -440,6 +508,7 @@ static void test_same_apartment_unmarshal_failure(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); ok_ole_success(hr, IStream_Seek); @@ -448,6 +517,8 @@ static void test_same_apartment_unmarshal_failure(void) ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(FALSE); IStream_Release(pStream); } @@ -462,12 +533,14 @@ static void test_interthread_marshal_and_unmarshal(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -475,10 +548,13 @@ static void test_interthread_marshal_and_unmarshal(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -499,12 +575,14 @@ static void test_proxy_marshal_and_unmarshal(void) int i; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -537,6 +615,7 @@ static void test_proxy_marshal_and_unmarshal(void) ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); @@ -550,6 +629,8 @@ static void test_proxy_marshal_and_unmarshal(void) } ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Release(pStream); @@ -568,12 +649,14 @@ static void test_proxy_marshal_and_unmarshal2(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); @@ -608,10 +691,13 @@ static void test_proxy_marshal_and_unmarshal2(void) IUnknown_Release(pProxy); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -627,18 +713,21 @@ static void test_proxy_marshal_and_unmarshal_weak(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); /* marshal the proxy */ @@ -646,6 +735,7 @@ static void test_proxy_marshal_and_unmarshal_weak(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the original proxy to test that we successfully keep the * original object alive */ @@ -657,6 +747,8 @@ static void test_proxy_marshal_and_unmarshal_weak(void) ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Release(pStream); @@ -674,18 +766,21 @@ static void test_proxy_marshal_and_unmarshal_strong(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); /* marshal the proxy */ @@ -699,6 +794,7 @@ static void test_proxy_marshal_and_unmarshal_strong(void) } ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the original proxy to test that we successfully keep the * original object alive */ @@ -709,10 +805,12 @@ static void test_proxy_marshal_and_unmarshal_strong(void) ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); ok_more_than_one_lock(); + ok_non_zero_external_conn(); end: IStream_Release(pStream); @@ -720,6 +818,10 @@ end: end_host_object(tid, thread); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} } /* tests that stubs are released when the containing apartment is destroyed */ @@ -732,12 +834,14 @@ static void test_marshal_stub_apartment_shutdown(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -745,10 +849,15 @@ static void test_marshal_stub_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); end_host_object(tid, thread); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} IUnknown_Release(pProxy); @@ -765,12 +874,14 @@ static void test_marshal_proxy_apartment_shutdown(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -778,10 +889,13 @@ static void test_marshal_proxy_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoUninitialize(); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IUnknown_Release(pProxy); @@ -805,12 +919,14 @@ static void test_marshal_proxy_mta_apartment_shutdown(void) pCoInitializeEx(NULL, COINIT_MULTITHREADED); cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -818,10 +934,13 @@ static void test_marshal_proxy_mta_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoUninitialize(); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IUnknown_Release(pProxy); @@ -871,9 +990,10 @@ static void test_no_couninitialize_server(void) struct ncu_params ncu_params; cLocks = 0; + external_connections = 0; - ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL); - ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL); + ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); + ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -883,6 +1003,7 @@ static void test_no_couninitialize_server(void) ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" ); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -890,11 +1011,16 @@ static void test_no_couninitialize_server(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); SetEvent(ncu_params.unmarshal_event); ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} CloseHandle(thread); CloseHandle(ncu_params.marshal_event); @@ -937,6 +1063,7 @@ static void test_no_couninitialize_client(void) struct ncu_params ncu_params; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -948,6 +1075,7 @@ static void test_no_couninitialize_client(void) IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); ok_more_than_one_lock(); + ok_non_zero_external_conn(); thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid); @@ -955,6 +1083,8 @@ static void test_no_couninitialize_client(void) CloseHandle(thread); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(host_tid, host_thread); } @@ -970,34 +1100,48 @@ static void test_tableweak_marshal_and_unmarshal_twice(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); - IStream_Release(pStream); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); IUnknown_Release(pProxy1); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); - /* this line is shows the difference between weak and strong table marshaling: - * weak has cLocks == 0 - * strong has cLocks > 0 */ + /* When IExternalConnection is present COM's lifetime management + * behaviour is altered; the remaining weak ref prevents stub shutdown. */ + if (with_external_conn) + { + ok_more_than_one_lock(); + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 0); + } + + /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling + * weak has cLocks == 0, strong has cLocks > 0. */ ok_no_locks(); + IStream_Release(pStream); end_host_object(tid, thread); } @@ -1012,25 +1156,29 @@ static void test_tableweak_marshal_releasedata1(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the remaining reference on the object by calling * CoReleaseMarshalData in the hosting thread */ IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); - release_host_object(tid); + release_host_object(tid, 0); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); @@ -1038,15 +1186,22 @@ static void test_tableweak_marshal_releasedata1(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy1); + if (pProxy2) + { + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); + } /* this line is shows the difference between weak and strong table marshaling: * weak has cLocks == 0 * strong has cLocks > 0 */ ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -1061,17 +1216,19 @@ static void test_tableweak_marshal_releasedata2(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); /* release the remaining reference on the object by calling * CoReleaseMarshalData in the hosting thread */ IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); - release_host_object(tid); + release_host_object(tid, 0); ok_no_locks(); @@ -1086,42 +1243,51 @@ static void test_tableweak_marshal_releasedata2(void) IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); end_host_object(tid, thread); } -struct weak_and_normal_marshal_data +struct duo_marshal_data { - IStream *pStreamWeak; - IStream *pStreamNormal; + MSHLFLAGS marshal_flags1, marshal_flags2; + IStream *pStream1, *pStream2; HANDLE hReadyEvent; HANDLE hQuitEvent; }; -static DWORD CALLBACK weak_and_normal_marshal_thread_proc(void *p) +static DWORD CALLBACK duo_marshal_thread_proc(void *p) { HRESULT hr; - struct weak_and_normal_marshal_data *data = p; + struct duo_marshal_data *data = p; HANDLE hQuitEvent = data->hQuitEvent; MSG msg; pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - hr = CoMarshalInterface(data->pStreamWeak, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK); + hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1); ok_ole_success(hr, "CoMarshalInterface"); - hr = CoMarshalInterface(data->pStreamNormal, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); + hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2); ok_ole_success(hr, "CoMarshalInterface"); /* force the message queue to be created before signaling parent thread */ - PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); SetEvent(data->hReadyEvent); while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT)) { - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - DispatchMessage(&msg); + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) + { + CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2); + SetEvent((HANDLE)msg.lParam); + } + else + DispatchMessageA(&msg); + } } CloseHandle(hQuitEvent); @@ -1138,31 +1304,37 @@ static void test_tableweak_and_normal_marshal_and_unmarshal(void) IUnknown *pProxyNormal = NULL; DWORD tid; HANDLE thread; - struct weak_and_normal_marshal_data data; + struct duo_marshal_data data; cLocks = 0; + external_connections = 0; - data.hReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data.hQuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamWeak); + data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; + data.marshal_flags2 = MSHLFLAGS_NORMAL; + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); ok_ole_success(hr, CreateStreamOnHGlobal); - hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStreamNormal); + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); ok_ole_success(hr, CreateStreamOnHGlobal); - thread = CreateThread(NULL, 0, weak_and_normal_marshal_thread_proc, &data, 0, &tid); + thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); CloseHandle(data.hReadyEvent); ok_more_than_one_lock(); + ok_non_zero_external_conn(); - IStream_Seek(data.pStreamWeak, ullZero, STREAM_SEEK_SET, NULL); - hr = CoUnmarshalInterface(data.pStreamWeak, &IID_IClassFactory, (void **)&pProxyWeak); + /* weak */ + IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); - IStream_Seek(data.pStreamNormal, ullZero, STREAM_SEEK_SET, NULL); - hr = CoUnmarshalInterface(data.pStreamNormal, &IID_IClassFactory, (void **)&pProxyNormal); + /* normal */ + IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); @@ -1170,13 +1342,120 @@ static void test_tableweak_and_normal_marshal_and_unmarshal(void) IUnknown_Release(pProxyNormal); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxyWeak); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); + + /* When IExternalConnection is present COM's lifetime management + * behaviour is altered; the remaining weak ref prevents stub shutdown. */ + if (with_external_conn) + { + ok_more_than_one_lock(); + IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 1); + } ok_no_locks(); - IStream_Release(data.pStreamWeak); - IStream_Release(data.pStreamNormal); + IStream_Release(data.pStream1); + IStream_Release(data.pStream2); + + SetEvent(data.hQuitEvent); + ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); + CloseHandle(thread); +} + +static void test_tableweak_and_normal_marshal_and_releasedata(void) +{ + HRESULT hr; + DWORD tid; + HANDLE thread; + struct duo_marshal_data data; + + cLocks = 0; + external_connections = 0; + + data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; + data.marshal_flags2 = MSHLFLAGS_NORMAL; + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); + ok_ole_success(hr, CreateStreamOnHGlobal); + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); + ok_ole_success(hr, CreateStreamOnHGlobal); + + thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); + ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); + CloseHandle(data.hReadyEvent); + + ok_more_than_one_lock(); + ok_non_zero_external_conn(); + + /* release normal - which in the non-external conn case will free the object despite the weak ref. */ + IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 2); + + ok_zero_external_conn(); + ok_last_release_closes(TRUE); + + if (with_external_conn) + { + ok_more_than_one_lock(); + IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 1); + } + + ok_no_locks(); + + IStream_Release(data.pStream1); + IStream_Release(data.pStream2); + + SetEvent(data.hQuitEvent); + ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); + CloseHandle(thread); +} + +static void test_two_tableweak_marshal_and_releasedata(void) +{ + HRESULT hr; + DWORD tid; + HANDLE thread; + struct duo_marshal_data data; + + cLocks = 0; + external_connections = 0; + + data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); + data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; + data.marshal_flags2 = MSHLFLAGS_TABLEWEAK; + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); + ok_ole_success(hr, CreateStreamOnHGlobal); + hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); + ok_ole_success(hr, CreateStreamOnHGlobal); + + thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); + ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); + CloseHandle(data.hReadyEvent); + + ok_more_than_one_lock(); + ok_zero_external_conn(); + + /* release one weak ref - the remaining weak ref will keep the obj alive */ + IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 1); + + ok_more_than_one_lock(); + + IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid, 2); + + ok_no_locks(); + + IStream_Release(data.pStream1); + IStream_Release(data.pStream2); SetEvent(data.hQuitEvent); ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); @@ -1194,12 +1473,14 @@ static void test_tablestrong_marshal_and_unmarshal_twice(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); @@ -1224,10 +1505,12 @@ static void test_tablestrong_marshal_and_unmarshal_twice(void) /* release the remaining reference on the object by calling * CoReleaseMarshalData in the hosting thread */ IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); - release_host_object(tid); + release_host_object(tid, 0); IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -1239,16 +1522,20 @@ static void test_lock_object_external(void) IStream *pStream = NULL; cLocks = 0; + external_connections = 0; /* test the stub manager creation aspect of CoLockObjectExternal when the * object hasn't been marshaled yet */ CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); ok_no_locks(); + ok_non_zero_external_conn(); + external_connections = 0; /* test our empty stub manager being handled correctly in * CoMarshalInterface */ @@ -1262,6 +1549,7 @@ static void test_lock_object_external(void) CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -1269,14 +1557,20 @@ static void test_lock_object_external(void) IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); ok_more_than_one_lock(); + ok_non_zero_external_conn(); + ok_last_release_closes(TRUE); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); + ok_last_release_closes(TRUE); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); /* test CoLockObjectExternal releases reference to object with * fLastUnlockReleases as TRUE and there are only strong references on @@ -1284,10 +1578,13 @@ static void test_lock_object_external(void) CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(FALSE); /* test CoLockObjectExternal doesn't release the last reference to an * object with fLastUnlockReleases as TRUE and there is a weak reference @@ -1296,14 +1593,18 @@ static void test_lock_object_external(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); ok_more_than_one_lock(); + ok_zero_external_conn(); + ok_last_release_closes(FALSE); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); @@ -1319,15 +1620,19 @@ static void test_disconnect_stub(void) IStream *pStream = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); ok_ole_success(hr, CoMarshalInterface); + ok_non_zero_external_conn(); + CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -1335,10 +1640,12 @@ static void test_disconnect_stub(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); ok_no_locks(); + ok_non_zero_external_conn(); hr = CoDisconnectObject(NULL, 0); ok( hr == E_INVALIDARG, "wrong status %x\n", hr ); @@ -1353,6 +1660,7 @@ static void test_normal_marshal_and_unmarshal_twice(void) IUnknown *pProxy2 = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -1360,12 +1668,15 @@ static void test_normal_marshal_and_unmarshal_twice(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_zero_external_conn(); + ok_last_release_closes(FALSE); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); @@ -1492,7 +1803,7 @@ static void test_proxy_used_in_wrong_thread(void) CloseHandle(thread); /* do release statement on Win9x that we should have done above */ - if (!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx")) + if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) IUnknown_Release(pProxy); ok_no_locks(); @@ -1832,7 +2143,7 @@ static HRESULT WINAPI TestRE_IClassFactory_CreateInstance( DWORD_PTR res; if (IsEqualIID(riid, &IID_IWineTest)) { - BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res); + BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res); ok(ret, "Timed out sending a message to originating window during RPC call\n"); } *ppvObj = NULL; @@ -1889,7 +2200,7 @@ static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l end_host_object(tid, thread); - PostMessage(hwnd, WM_QUIT, 0, 0); + PostMessageA(hwnd, WM_QUIT, 0, 0); return 0; } @@ -1919,7 +2230,7 @@ static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l /* post quit message before a doing a COM call to show that a pending * WM_QUIT message doesn't stop the call from succeeding */ - PostMessage(hwnd, WM_QUIT, 0, 0); + PostMessageA(hwnd, WM_QUIT, 0, 0); hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr); @@ -1964,34 +2275,34 @@ static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l return 0; } default: - return DefWindowProc(hwnd, msg, wparam, lparam); + return DefWindowProcA(hwnd, msg, wparam, lparam); } } static void register_test_window(void) { - WNDCLASS wndclass; + WNDCLASSA wndclass; memset(&wndclass, 0, sizeof(wndclass)); wndclass.lpfnWndProc = window_proc; wndclass.lpszClassName = "WineCOMTest"; - RegisterClass(&wndclass); + RegisterClassA(&wndclass); } static void test_message_reentrancy(void) { MSG msg; - hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); + hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); ok(hwnd_app != NULL, "Window creation failed\n"); /* start message re-entrancy test */ - PostMessage(hwnd_app, WM_USER, 0, 0); + PostMessageA(hwnd_app, WM_USER, 0, 0); - while (GetMessage(&msg, NULL, 0, 0)) + while (GetMessageA(&msg, NULL, 0, 0)) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageA(&msg); } DestroyWindow(hwnd_app); } @@ -2003,7 +2314,7 @@ static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance( LPVOID *ppvObj) { *ppvObj = NULL; - SendMessage(hwnd_app, WM_USER+2, 0, 0); + SendMessageA(hwnd_app, WM_USER+2, 0, 0); return S_OK; } @@ -2028,7 +2339,7 @@ static void test_call_from_message(void) HANDLE thread; IUnknown *object; - hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); + hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); ok(hwnd_app != NULL, "Window creation failed\n"); hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); @@ -2054,10 +2365,10 @@ static void test_call_from_message(void) end_host_object(tid, thread); - while (GetMessage(&msg, NULL, 0, 0)) + while (GetMessageA(&msg, NULL, 0, 0)) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageA(&msg); } DestroyWindow(hwnd_app); } @@ -2066,16 +2377,16 @@ static void test_WM_QUIT_handling(void) { MSG msg; - hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); + hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); ok(hwnd_app != NULL, "Window creation failed\n"); /* start WM_QUIT handling test */ - PostMessage(hwnd_app, WM_USER+1, 0, 0); + PostMessageA(hwnd_app, WM_USER+1, 0, 0); - while (GetMessage(&msg, NULL, 0, 0)) + while (GetMessageA(&msg, NULL, 0, 0)) { TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageA(&msg); } } @@ -2124,10 +2435,7 @@ static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void * } if (size >= 3*sizeof(DWORD) + sizeof(GUID)) { - trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n", - ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3, - ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3], - ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]); + trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data)); } } else @@ -2296,7 +2604,7 @@ static HRESULT reg_unreg_wine_test_class(BOOL Register) strcat(buffer, "\\InprocHandler32"); if (Register) { - error = RegCreateKeyEx(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); + error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); if (error == ERROR_ACCESS_DENIED) { skip("Not authorized to modify the Classes key\n"); @@ -2304,16 +2612,16 @@ static HRESULT reg_unreg_wine_test_class(BOOL Register) } ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error); if (error != ERROR_SUCCESS) hr = E_FAIL; - error = RegSetValueEx(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1); + error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1); ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error); if (error != ERROR_SUCCESS) hr = E_FAIL; RegCloseKey(hkey); } else { - RegDeleteKey(HKEY_CLASSES_ROOT, buffer); + RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); *strrchr(buffer, '\\') = '\0'; - RegDeleteKey(HKEY_CLASSES_ROOT, buffer); + RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); } return hr; } @@ -2623,16 +2931,16 @@ static void test_register_local_server(void) HANDLE quit_event; DWORD wait; - heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL); + heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); ok_ole_success(hr, CoRegisterClassObject); - ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); + ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); SetEvent(ready_event); - quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); + quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); do { @@ -2640,12 +2948,12 @@ static void test_register_local_server(void) if (wait == WAIT_OBJECT_0+1) { MSG msg; - BOOL ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); - if (ret) + + if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { trace("Message 0x%x\n", msg.message); TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessageA(&msg); } } } @@ -2662,14 +2970,14 @@ static HANDLE create_target_process(const char *arg) char cmdline[MAX_PATH]; BOOL ret; PROCESS_INFORMATION pi; - STARTUPINFO si = { 0 }; + STARTUPINFOA si = { 0 }; si.cb = sizeof(si); pi.hThread = NULL; pi.hProcess = NULL; winetest_get_mainargs( &argv ); sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg); - ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); ok(ret, "CreateProcess failed with error: %u\n", GetLastError()); if (pi.hThread) CloseHandle(pi.hThread); return pi.hProcess; @@ -2686,7 +2994,7 @@ static void test_local_server(void) HANDLE quit_event; HANDLE ready_event; - heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL); + heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); cLocks = 0; @@ -2749,7 +3057,7 @@ static void test_local_server(void) process = create_target_process("-Embedding"); ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError()); - ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); + ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); CloseHandle(ready_event); @@ -2761,7 +3069,7 @@ static void test_local_server(void) hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf); ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n"); - quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); + quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); SetEvent(quit_event); winetest_wait_child_process( process ); @@ -2854,8 +3162,8 @@ static void test_globalinterfacetable(void) while (ret == WAIT_OBJECT_0 + 1) { MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - DispatchMessage(&msg); + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessageA(&msg); ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT); } @@ -2963,12 +3271,12 @@ static const char *debugstr_iid(REFIID riid) LONG name_size = sizeof(name); StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL); - if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS) + if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS) { memcpy(name, buffer, sizeof(buffer)); goto done; } - if (RegQueryValue(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS) + if (RegQueryValueA(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS) { memcpy(name, buffer, sizeof(buffer)); goto done; @@ -3167,7 +3475,7 @@ static void test_channel_hook(void) START_TEST(marshal) { - HMODULE hOle32 = GetModuleHandle("ole32"); + HMODULE hOle32 = GetModuleHandleA("ole32"); int argc; char **argv; @@ -3198,29 +3506,37 @@ START_TEST(marshal) /* FIXME: test CoCreateInstanceEx */ /* lifecycle management and marshaling tests */ - test_no_marshaler(); - test_normal_marshal_and_release(); - test_normal_marshal_and_unmarshal(); - test_marshal_and_unmarshal_invalid(); - test_same_apartment_unmarshal_failure(); - test_interthread_marshal_and_unmarshal(); - test_proxy_marshal_and_unmarshal(); - test_proxy_marshal_and_unmarshal2(); - test_proxy_marshal_and_unmarshal_weak(); - test_proxy_marshal_and_unmarshal_strong(); - test_marshal_stub_apartment_shutdown(); - test_marshal_proxy_apartment_shutdown(); - test_marshal_proxy_mta_apartment_shutdown(); - test_no_couninitialize_server(); - test_no_couninitialize_client(); - test_tableweak_marshal_and_unmarshal_twice(); - test_tableweak_marshal_releasedata1(); - test_tableweak_marshal_releasedata2(); - test_tableweak_and_normal_marshal_and_unmarshal(); - test_tablestrong_marshal_and_unmarshal_twice(); - test_lock_object_external(); - test_disconnect_stub(); - test_normal_marshal_and_unmarshal_twice(); + do + { + test_no_marshaler(); + test_normal_marshal_and_release(); + test_normal_marshal_and_unmarshal(); + test_marshal_and_unmarshal_invalid(); + test_same_apartment_unmarshal_failure(); + test_interthread_marshal_and_unmarshal(); + test_proxy_marshal_and_unmarshal(); + test_proxy_marshal_and_unmarshal2(); + test_proxy_marshal_and_unmarshal_weak(); + test_proxy_marshal_and_unmarshal_strong(); + test_marshal_stub_apartment_shutdown(); + test_marshal_proxy_apartment_shutdown(); + test_marshal_proxy_mta_apartment_shutdown(); + test_no_couninitialize_server(); + test_no_couninitialize_client(); + test_tableweak_marshal_and_unmarshal_twice(); + test_tableweak_marshal_releasedata1(); + test_tableweak_marshal_releasedata2(); + test_tableweak_and_normal_marshal_and_unmarshal(); + test_tableweak_and_normal_marshal_and_releasedata(); + test_two_tableweak_marshal_and_releasedata(); + test_tablestrong_marshal_and_unmarshal_twice(); + test_lock_object_external(); + test_disconnect_stub(); + test_normal_marshal_and_unmarshal_twice(); + + with_external_conn = !with_external_conn; + } while (with_external_conn); + test_hresult_marshaling(); test_proxy_used_in_wrong_thread(); test_message_filter(); diff --git a/rostests/winetests/ole32/ole2.c b/rostests/winetests/ole32/ole2.c index 6b9ed142f72..a03e923b19e 100644 --- a/rostests/winetests/ole32/ole2.c +++ b/rostests/winetests/ole32/ole2.c @@ -32,6 +32,7 @@ #include #include #include +#include #include //#include "objbase.h" //#include "shlguid.h" @@ -40,10 +41,48 @@ #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr) +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(Storage_Stat); +DEFINE_EXPECT(Storage_OpenStream_CompObj); +DEFINE_EXPECT(Storage_SetClass); +DEFINE_EXPECT(Storage_CreateStream_CompObj); +DEFINE_EXPECT(Storage_OpenStream_Ole); + static IPersistStorage OleObjectPersistStg; static IOleCache *cache; static IRunnableObject *runnable; +static const CLSID CLSID_WineTestOld = +{ /* 9474ba1a-258b-490b-bc13-516e9239acd0 */ + 0x9474ba1a, + 0x258b, + 0x490b, + {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xd0} +}; + static const CLSID CLSID_WineTest = { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */ 0x9474ba1a, @@ -1346,7 +1385,7 @@ static void test_data_cache(void) { NULL, 0 } }; - GetSystemDirectory(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])); + GetSystemDirectoryA(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])); expected_method_list = methods_cacheinitnew; @@ -1449,7 +1488,7 @@ static void test_data_cache(void) fmtetc.cfFormat = CF_METAFILEPICT; stgmedium.tymed = TYMED_MFPICT; U(stgmedium).hMetaFilePict = OleMetafilePictFromIconAndLabel( - LoadIcon(NULL, IDI_APPLICATION), wszPath, wszPath, 0); + LoadIconA(NULL, (LPSTR)IDI_APPLICATION), wszPath, wszPath, 0); stgmedium.pUnkForRelease = NULL; fmtetc.dwAspect = DVASPECT_CONTENT; @@ -1964,6 +2003,363 @@ static void test_OleDraw(void) ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); } +static const WCHAR comp_objW[] = {1,'C','o','m','p','O','b','j',0}; +static IStream *comp_obj_stream; +static IStream *ole_stream; + +static HRESULT WINAPI Storage_QueryInterface(IStorage *iface, REFIID riid, void **ppvObject) +{ + ok(0, "unexpected call to QueryInterface\n"); + return E_NOTIMPL; +} + +static ULONG WINAPI Storage_AddRef(IStorage *iface) +{ + ok(0, "unexpected call to AddRef\n"); + return 2; +} + +static ULONG WINAPI Storage_Release(IStorage *iface) +{ + ok(0, "unexpected call to Release\n"); + return 1; +} + +static HRESULT WINAPI Storage_CreateStream(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm) +{ + ULARGE_INTEGER size = {{0}}; + LARGE_INTEGER pos = {{0}}; + HRESULT hr; + + CHECK_EXPECT(Storage_CreateStream_CompObj); + ok(!lstrcmpW(pwcsName, comp_objW), "pwcsName = %s\n", wine_dbgstr_w(pwcsName)); + todo_wine ok(grfMode == (STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode); + ok(!reserved1, "reserved1 = %x\n", reserved1); + ok(!reserved2, "reserved2 = %x\n", reserved2); + ok(!!ppstm, "ppstm = NULL\n"); + + *ppstm = comp_obj_stream; + IStream_AddRef(comp_obj_stream); + hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek returned %x\n", hr); + hr = IStream_SetSize(comp_obj_stream, size); + ok(hr == S_OK, "IStream_SetSize returned %x\n", hr); + return S_OK; +} + +static HRESULT WINAPI Storage_OpenStream(IStorage *iface, LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm) +{ + static const WCHAR ole1W[] = {1,'O','l','e',0}; + + LARGE_INTEGER pos = {{0}}; + HRESULT hr; + + ok(!reserved1, "reserved1 = %p\n", reserved1); + ok(!reserved2, "reserved2 = %x\n", reserved2); + ok(!!ppstm, "ppstm = NULL\n"); + + if(!lstrcmpW(pwcsName, comp_objW)) { + CHECK_EXPECT2(Storage_OpenStream_CompObj); + ok(grfMode == STGM_SHARE_EXCLUSIVE, "grfMode = %x\n", grfMode); + + *ppstm = comp_obj_stream; + IStream_AddRef(comp_obj_stream); + hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek returned %x\n", hr); + return S_OK; + }else if(!lstrcmpW(pwcsName, ole1W)) { + CHECK_EXPECT(Storage_OpenStream_Ole); + ok(grfMode == (STGM_SHARE_EXCLUSIVE|STGM_READWRITE), "grfMode = %x\n", grfMode); + + *ppstm = ole_stream; + IStream_AddRef(ole_stream); + hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek returned %x\n", hr); + return S_OK; + } + + ok(0, "unexpected call to OpenStream: %s\n", wine_dbgstr_w(pwcsName)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_CreateStorage(IStorage *iface, LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg) +{ + ok(0, "unexpected call to CreateStorage\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_OpenStorage(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg) +{ + ok(0, "unexpected call to OpenStorage\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_CopyTo(IStorage *iface, DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest) +{ + ok(0, "unexpected call to CopyTo\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_MoveElementTo(IStorage *iface, LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags) +{ + ok(0, "unexpected call to MoveElementTo\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_Commit(IStorage *iface, DWORD grfCommitFlags) +{ + ok(0, "unexpected call to Commit\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_Revert(IStorage *iface) +{ + ok(0, "unexpected call to Revert\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_EnumElements(IStorage *iface, DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum) +{ + ok(0, "unexpected call to EnumElements\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_DestroyElement(IStorage *iface, LPCOLESTR pwcsName) +{ + ok(0, "unexpected call to DestroyElement\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_RenameElement(IStorage *iface, LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName) +{ + ok(0, "unexpected call to RenameElement\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_SetElementTimes(IStorage *iface, LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime) +{ + ok(0, "unexpected call to SetElementTimes\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_SetClass(IStorage *iface, REFCLSID clsid) +{ + CHECK_EXPECT(Storage_SetClass); + ok(IsEqualIID(clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(clsid)); + return S_OK; +} + +static HRESULT WINAPI Storage_SetStateBits(IStorage *iface, DWORD grfStateBits, DWORD grfMask) +{ + ok(0, "unexpected call to SetStateBits\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Storage_Stat(IStorage *iface, STATSTG *pstatstg, DWORD grfStatFlag) +{ + CHECK_EXPECT2(Storage_Stat); + ok(pstatstg != NULL, "pstatstg = NULL\n"); + ok(grfStatFlag == STATFLAG_NONAME, "grfStatFlag = %x\n", grfStatFlag); + + memset(pstatstg, 0, sizeof(STATSTG)); + pstatstg->type = STGTY_STORAGE; + pstatstg->clsid = CLSID_WineTestOld; + return S_OK; +} + +static IStorageVtbl StorageVtbl = +{ + Storage_QueryInterface, + Storage_AddRef, + Storage_Release, + Storage_CreateStream, + Storage_OpenStream, + Storage_CreateStorage, + Storage_OpenStorage, + Storage_CopyTo, + Storage_MoveElementTo, + Storage_Commit, + Storage_Revert, + Storage_EnumElements, + Storage_DestroyElement, + Storage_RenameElement, + Storage_SetElementTimes, + Storage_SetClass, + Storage_SetStateBits, + Storage_Stat +}; + +static IStorage Storage = { &StorageVtbl }; + +static void test_OleDoAutoConvert(void) +{ + static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0}; + static struct { + DWORD reserved1; + DWORD version; + DWORD reserved2[5]; + DWORD ansi_user_type_len; + DWORD ansi_clipboard_format_len; + DWORD reserved3; + DWORD unicode_marker; + DWORD unicode_user_type_len; + DWORD unicode_clipboard_format_len; + DWORD reserved4; + } comp_obj_data; + static struct { + DWORD version; + DWORD flags; + DWORD link_update_option; + DWORD reserved1; + DWORD reserved_moniker_stream_size; + DWORD relative_source_moniker_stream_size; + DWORD absolute_source_moniker_stream_size; + DWORD clsid_indicator; + CLSID clsid; + DWORD reserved_display_name; + DWORD reserved2; + DWORD local_update_time; + DWORD local_check_update_time; + DWORD remote_update_time; + } ole_data; + + LARGE_INTEGER pos = {{0}}; + WCHAR buf[39+6]; + DWORD i, ret; + HKEY root; + CLSID clsid; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &comp_obj_stream); + ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr); + hr = IStream_Write(comp_obj_stream, (char*)&comp_obj_data, sizeof(comp_obj_data), NULL); + ok(hr == S_OK, "IStream_Write returned %x\n", hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &ole_stream); + ok(hr == S_OK, "CreateStreamOnHGlobal returned %x\n", hr); + hr = IStream_Write(ole_stream, (char*)&ole_data, sizeof(ole_data), NULL); + ok(hr == S_OK, "IStream_Write returned %x\n", hr); + + clsid = IID_WineTest; + hr = OleDoAutoConvert(NULL, &clsid); + ok(hr == E_INVALIDARG, "OleDoAutoConvert returned %x\n", hr); + ok(IsEqualIID(&clsid, &IID_NULL), "clsid = %s\n", wine_dbgstr_guid(&clsid)); + + if(0) /* crashes on Win7 */ + OleDoAutoConvert(&Storage, NULL); + + clsid = IID_WineTest; + SET_EXPECT(Storage_Stat); + hr = OleDoAutoConvert(&Storage, &clsid); + ok(hr == REGDB_E_CLASSNOTREG, "OleDoAutoConvert returned %x\n", hr); + CHECK_CALLED(Storage_Stat); + ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid)); + + lstrcpyW(buf, clsidW); + StringFromGUID2(&CLSID_WineTestOld, buf+6, 39); + + ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL); + if(ret != ERROR_SUCCESS) { + win_skip("not enough permissions to create CLSID key (%u)\n", ret); + return; + } + + clsid = IID_WineTest; + SET_EXPECT(Storage_Stat); + hr = OleDoAutoConvert(&Storage, &clsid); + ok(hr == REGDB_E_KEYMISSING, "OleDoAutoConvert returned %x\n", hr); + CHECK_CALLED(Storage_Stat); + ok(IsEqualIID(&clsid, &CLSID_WineTestOld), "clsid = %s\n", wine_dbgstr_guid(&clsid)); + + hr = OleSetAutoConvert(&CLSID_WineTestOld, &CLSID_WineTest); + ok_ole_success(hr, "OleSetAutoConvert"); + + hr = OleGetAutoConvert(&CLSID_WineTestOld, &clsid); + ok_ole_success(hr, "OleGetAutoConvert"); + ok(IsEqualIID(&clsid, &CLSID_WineTest), "incorrect clsid: %s\n", wine_dbgstr_guid(&clsid)); + + clsid = IID_WineTest; + SET_EXPECT(Storage_Stat); + SET_EXPECT(Storage_OpenStream_CompObj); + SET_EXPECT(Storage_SetClass); + SET_EXPECT(Storage_CreateStream_CompObj); + SET_EXPECT(Storage_OpenStream_Ole); + hr = OleDoAutoConvert(&Storage, &clsid); + ok(hr == S_OK, "OleDoAutoConvert returned %x\n", hr); + CHECK_CALLED(Storage_Stat); + CHECK_CALLED(Storage_OpenStream_CompObj); + CHECK_CALLED(Storage_SetClass); + CHECK_CALLED(Storage_CreateStream_CompObj); + CHECK_CALLED(Storage_OpenStream_Ole); + ok(IsEqualIID(&clsid, &CLSID_WineTest), "clsid = %s\n", wine_dbgstr_guid(&clsid)); + + hr = IStream_Seek(comp_obj_stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek returned %x\n", hr); + hr = IStream_Read(comp_obj_stream, &comp_obj_data, sizeof(comp_obj_data), NULL); + ok(hr == S_OK, "IStream_Read returned %x\n", hr); + ok(comp_obj_data.reserved1 == 0xfffe0001, "reserved1 = %x\n", comp_obj_data.reserved1); + ok(comp_obj_data.version == 0xa03, "version = %x\n", comp_obj_data.version); + ok(comp_obj_data.reserved2[0] == -1, "reserved2[0] = %x\n", comp_obj_data.reserved2[0]); + ok(IsEqualIID(comp_obj_data.reserved2+1, &CLSID_WineTestOld), "reserved2 = %s\n", wine_dbgstr_guid((CLSID*)(comp_obj_data.reserved2+1))); + ok(!comp_obj_data.ansi_user_type_len, "ansi_user_type_len = %d\n", comp_obj_data.ansi_user_type_len); + ok(!comp_obj_data.ansi_clipboard_format_len, "ansi_clipboard_format_len = %d\n", comp_obj_data.ansi_clipboard_format_len); + ok(!comp_obj_data.reserved3, "reserved3 = %x\n", comp_obj_data.reserved3); + ok(comp_obj_data.unicode_marker == 0x71b239f4, "unicode_marker = %x\n", comp_obj_data.unicode_marker); + ok(!comp_obj_data.unicode_user_type_len, "unicode_user_type_len = %d\n", comp_obj_data.unicode_user_type_len); + ok(!comp_obj_data.unicode_clipboard_format_len, "unicode_clipboard_format_len = %d\n", comp_obj_data.unicode_clipboard_format_len); + ok(!comp_obj_data.reserved4, "reserved4 %d\n", comp_obj_data.reserved4); + + hr = IStream_Seek(ole_stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "IStream_Seek returned %x\n", hr); + hr = IStream_Read(ole_stream, &ole_data, sizeof(ole_data), NULL); + ok(hr == S_OK, "IStream_Read returned %x\n", hr); + ok(ole_data.version == 0, "version = %x\n", ole_data.version); + ok(ole_data.flags == 4, "flags = %x\n", ole_data.flags); + for(i=2; iData1, guid->Data2, guid->Data3, guid->Data4[0], - guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], - guid->Data4[5], guid->Data4[6], guid->Data4[7]); - return buf; + return wine_dbgstr_guid(guid); } /******************************* OLE server *******************************/ @@ -258,9 +253,9 @@ static void ole_server(void) { HANDLE done_event, init_done_event; - done_event = OpenEvent(SYNCHRONIZE, FALSE, "ole_server_done_event"); + done_event = OpenEventA(SYNCHRONIZE, FALSE, "ole_server_done_event"); ok(done_event != 0, "server: OpenEvent error %d\n", GetLastError()); - init_done_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, "ole_server_init_done_event"); + init_done_event = OpenEventA(EVENT_MODIFY_STATE, FALSE, "ole_server_init_done_event"); ok(init_done_event != 0, "server: OpenEvent error %d\n", GetLastError()); SetEvent(init_done_event); @@ -300,8 +295,8 @@ static BOOL register_server(const char *server, BOOL inproc_handler) WCHAR buf[39 + 6]; char server_path[MAX_PATH]; - lstrcpy(server_path, server); - lstrcat(server_path, " ole_server"); + lstrcpyA(server_path, server); + lstrcatA(server_path, " ole_server"); lstrcpyW(buf, clsidW); StringFromGUID2(&CLSID_WineTestObject, buf + 6, 39); @@ -310,12 +305,12 @@ static BOOL register_server(const char *server, BOOL inproc_handler) KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY, NULL, &root, NULL); if (ret == ERROR_SUCCESS) { - ret = RegSetValue(root, "LocalServer32", REG_SZ, server_path, strlen(server_path)); + ret = RegSetValueA(root, "LocalServer32", REG_SZ, server_path, strlen(server_path)); ok(ret == ERROR_SUCCESS, "RegSetValue error %u\n", ret); if (inproc_handler) { - ret = RegSetValue(root, "InprocHandler32", REG_SZ, "ole32.dll", 9); + ret = RegSetValueA(root, "InprocHandler32", REG_SZ, "ole32.dll", 9); ok(ret == ERROR_SUCCESS, "RegSetValue error %u\n", ret); } @@ -339,11 +334,11 @@ static void unregister_server(void) DELETE, NULL, &root, NULL); if (ret == ERROR_SUCCESS) { - ret = RegDeleteKey(root, "InprocHandler32"); + ret = RegDeleteKeyA(root, "InprocHandler32"); ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret); - ret = RegDeleteKey(root, "LocalServer32"); + ret = RegDeleteKeyA(root, "LocalServer32"); ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret); - ret = RegDeleteKey(root, ""); + ret = RegDeleteKeyA(root, ""); ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret); RegCloseKey(root); } @@ -352,7 +347,7 @@ static void unregister_server(void) static HANDLE start_server(const char *argv0) { PROCESS_INFORMATION pi; - STARTUPINFO si; + STARTUPINFOA si; SECURITY_ATTRIBUTES sa; char cmdline[MAX_PATH * 2]; BOOL ret; @@ -369,7 +364,7 @@ static HANDLE start_server(const char *argv0) sa.bInheritHandle = TRUE; sprintf(cmdline, "\"%s\" ole_server -server", argv0); - ret = CreateProcess(argv0, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + ret = CreateProcessA(argv0, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError()); if (!ret) return 0; @@ -391,26 +386,26 @@ START_TEST(ole_server) int argc; char **argv; - mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_ole_server"); + mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_ole_server"); ok(mapping != 0, "CreateFileMapping failed\n"); info = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096); argc = winetest_get_mainargs(&argv); - done_event = CreateEvent(NULL, TRUE, FALSE, "ole_server_done_event"); + done_event = CreateEventA(NULL, TRUE, FALSE, "ole_server_done_event"); ok(done_event != 0, "CreateEvent error %d\n", GetLastError()); - init_done_event = CreateEvent(NULL, TRUE, FALSE, "ole_server_init_done_event"); + init_done_event = CreateEventA(NULL, TRUE, FALSE, "ole_server_init_done_event"); ok(init_done_event != 0, "CreateEvent error %d\n", GetLastError()); if (argc > 2) { - if (!lstrcmpi(argv[2], "-Embedding")) + if (!lstrcmpiA(argv[2], "-Embedding")) { trace("server: Refusing to be run by ole32\n"); return; } - if (!lstrcmpi(argv[2], "-server")) + if (!lstrcmpiA(argv[2], "-server")) { info->child_failures = 0; ole_server(); diff --git a/rostests/winetests/ole32/propvariant.c b/rostests/winetests/ole32/propvariant.c index ac912ae60f2..f601e62f9c7 100644 --- a/rostests/winetests/ole32/propvariant.c +++ b/rostests/winetests/ole32/propvariant.c @@ -74,8 +74,8 @@ static const struct valid_mapping { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */ { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_I8 */ { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_UI8 */ - { PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */ - { PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */ + { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */ + { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */ @@ -140,7 +140,7 @@ static const char* wine_vtypes[VT_CLSID+1] = }; -static void expect(HRESULT hr, VARTYPE vt) +static void expect(HRESULT hr, VARTYPE vt, BOOL copy) { int idx = vt & VT_TYPEMASK; BYTE flags; @@ -168,7 +168,7 @@ static void expect(HRESULT hr, VARTYPE vt) } if(flags == PROP_INV) - ok(hr == STG_E_INVALIDPARAMETER, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr); + ok(hr == copy ? DISP_E_BADVARTYPE : STG_E_INVALIDPARAMETER, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr); else if(flags == PROP_V0) ok(hr == S_OK, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr); else if(flags & PROP_TODO) @@ -190,32 +190,125 @@ static void expect(HRESULT hr, VARTYPE vt) static void test_validtypes(void) { - PROPVARIANT propvar; + PROPVARIANT propvar, copy, uninit; HRESULT hr; - unsigned int i; + unsigned int i, ret; - memset(&propvar, 0, sizeof(propvar)); + memset(&uninit, 0x77, sizeof(uninit)); + + memset(&propvar, 0x55, sizeof(propvar)); + hr = PropVariantClear(&propvar); + ok(hr == STG_E_INVALIDPARAMETER, "expected STG_E_INVALIDPARAMETER, got %08x\n", hr); + ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt); + ok(U(propvar).uhVal.QuadPart == 0, "expected 0, got %#x/%#x\n", + U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart); for (i = 0; i < sizeof(valid_types)/sizeof(valid_types[0]); i++) { VARTYPE vt; + memset(&propvar, 0x55, sizeof(propvar)); + if (i == VT_RECORD) + memset(&propvar, 0, sizeof(propvar)); + else if (i == VT_BLOB || i == VT_BLOB_OBJECT) + { + U(propvar).blob.cbSize = 0; + U(propvar).blob.pBlobData = NULL; + } + else + U(propvar).pszVal = NULL; vt = propvar.vt = i; + memset(©, 0x77, sizeof(copy)); + hr = PropVariantCopy(©, &propvar); + expect(hr, vt, TRUE); + if (hr == S_OK) + { + ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt); + ok(U(copy).uhVal.QuadPart == U(propvar).uhVal.QuadPart, "%u: expected %#x/%#x, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart, + U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart); + } + else + { + ret = memcmp(©, &uninit, sizeof(copy)); + ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i); + } hr = PropVariantClear(&propvar); - expect(hr, vt); + expect(hr, vt, FALSE); + ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt); + ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart); + memset(&propvar, 0x55, sizeof(propvar)); + U(propvar).pszVal = NULL; vt = propvar.vt = i | VT_ARRAY; + memset(©, 0x77, sizeof(copy)); + hr = PropVariantCopy(©, &propvar); + expect(hr, vt, TRUE); + if (hr == S_OK) + { + ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt); + ok(U(copy).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n", + i, U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart); + } + else + { + ret = memcmp(©, &uninit, sizeof(copy)); + ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i); + } hr = PropVariantClear(&propvar); - expect(hr, vt); + expect(hr, vt, FALSE); + ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt); + ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart); + memset(&propvar, 0x55, sizeof(propvar)); + U(propvar).caub.cElems = 0; + U(propvar).caub.pElems = NULL; vt = propvar.vt = i | VT_VECTOR; + memset(©, 0x77, sizeof(copy)); + hr = PropVariantCopy(©, &propvar); + expect(hr, vt, TRUE); + if (hr == S_OK) + { + ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt); + ok(!U(copy).caub.cElems, "%u: expected 0, got %d\n", i, U(copy).caub.cElems); + ok(!U(copy).caub.pElems, "%u: expected NULL, got %p\n", i, U(copy).caub.pElems); + } + else + { + ret = memcmp(©, &uninit, sizeof(copy)); + ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i); + } hr = PropVariantClear(&propvar); - expect(hr, vt); + expect(hr, vt, FALSE); + ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt); + ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart); + memset(&propvar, 0x55, sizeof(propvar)); + U(propvar).pszVal = NULL; vt = propvar.vt = i | VT_BYREF; + memset(©, 0x77, sizeof(copy)); + hr = PropVariantCopy(©, &propvar); + expect(hr, vt, TRUE); + if (hr == S_OK) + { + ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt, copy.vt); + ok(U(copy).uhVal.QuadPart == U(propvar).uhVal.QuadPart, "%u: expected %#x/%#x, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart, + U(copy).uhVal.u.LowPart, U(copy).uhVal.u.HighPart); + } + else + { + ret = memcmp(©, &uninit, sizeof(copy)); + ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay unchanged\n", i); + } hr = PropVariantClear(&propvar); - expect(hr, vt); - + expect(hr, vt, FALSE); + ok(propvar.vt == 0, "expected 0, got %d\n", propvar.vt); + ok(U(propvar).uhVal.QuadPart == 0, "%u: expected 0, got %#x/%#x\n", + i, U(propvar).uhVal.u.LowPart, U(propvar).uhVal.u.HighPart); } } diff --git a/rostests/winetests/ole32/stg_prop.c b/rostests/winetests/ole32/stg_prop.c index 2040556c343..ba323fe5164 100644 --- a/rostests/winetests/ole32/stg_prop.c +++ b/rostests/winetests/ole32/stg_prop.c @@ -24,6 +24,7 @@ #include #include +#include #define COBJMACROS #include #include diff --git a/rostests/winetests/ole32/storage32.c b/rostests/winetests/ole32/storage32.c index b224ab50952..4c7c7d29903 100644 --- a/rostests/winetests/ole32/storage32.c +++ b/rostests/winetests/ole32/storage32.c @@ -254,7 +254,7 @@ static void test_create_storage_modes(void) static void test_stgcreatestorageex(void) { HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen); - HMODULE hOle32 = GetModuleHandle("ole32"); + HMODULE hOle32 = GetModuleHandleA("ole32"); IStorage *stg = NULL; STGOPTIONS stgoptions = {1, 0, 4096}; HRESULT r; @@ -933,7 +933,48 @@ static void test_storage_refcount(void) r = IStorage_Release(stg); ok(r == 0, "wrong ref count\n"); } - IStorage_Release(stgprio); + + /* Multiple STGM_PRIORITY opens are possible. */ + r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg); + ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); + if(stg) + { + r = IStorage_Release(stg); + ok(r == 0, "wrong ref count\n"); + } + + r = StgOpenStorage( NULL, stgprio, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg); + ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r); + if(stg) + { + static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 }; + IStorage *stg2; + STATSTG statstg; + + r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME ); + ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r); + ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type); + ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart); + ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart); + ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE), + "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode); + ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported); + ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n"); + ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits); + ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved); + + r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 ); + ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r); + + IStorage_Release(stg2); + + r = IStorage_Commit( stg, 0 ); + ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r); + + r = IStorage_Release(stg); + ok(r == 0, "wrong ref count\n"); + } + /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */ DeleteFileA(filenameA); } @@ -2178,7 +2219,7 @@ static void test_fmtusertypestg(void) static const char fileA[] = {'f','m','t','t','e','s','t',0}; static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0}; static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0}; - static WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0}; + static const WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0}; hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg); ok(hr == S_OK, "should succeed, res=%x\n", hr); @@ -3086,19 +3127,21 @@ if (hr == S_OK) { /* writer mode */ hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); ok(hr == S_OK, "got %08x\n", hr); + if(hr == S_OK) + { + ref = IStorage_AddRef(stg); + IStorage_Release(stg); - ref = IStorage_AddRef(stg); - IStorage_Release(stg); + hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock); + ok(hr == S_OK, "got %08x\n", hr); - hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock); - ok(hr == S_OK, "got %08x\n", hr); + ref2 = IStorage_AddRef(stg); + IStorage_Release(stg); + ok(ref2 == ref + 1, "got %u\n", ref2); - ref2 = IStorage_AddRef(stg); - IStorage_Release(stg); - ok(ref2 == ref + 1, "got %u\n", ref2); - - IDirectWriterLock_Release(dwlock); - IStorage_Release(stg); + IDirectWriterLock_Release(dwlock); + IStorage_Release(stg); + } DeleteFileW(fileW); } diff --git a/rostests/winetests/ole32/usrmarshal.c b/rostests/winetests/ole32/usrmarshal.c index e50968b0972..cec2ece0010 100644 --- a/rostests/winetests/ole32/usrmarshal.c +++ b/rostests/winetests/ole32/usrmarshal.c @@ -247,8 +247,8 @@ static void test_marshal_HGLOBAL(void) static HENHMETAFILE create_emf(void) { const RECT rect = {0, 0, 100, 100}; - HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0"); - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); + HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0"); + ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); return CloseEnhMetaFile(hdc); } @@ -319,8 +319,8 @@ static void test_marshal_HENHMETAFILE(void) static HMETAFILE create_mf(void) { RECT rect = {0, 0, 100, 100}; - HDC hdc = CreateMetaFile(NULL); - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); + HDC hdc = CreateMetaFileA(NULL); + ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL); return CloseMetaFile(hdc); }