* Sync with Wine 1.7.17.
CORE-8080
svn path=/trunk/; revision=62939
//#include "objbase.h"
//#include "shlguid.h"
#include <ole2.h>
-//#include "urlmon.h" /* for CLSID_FileProtocol */
+#include <urlmon.h> /* for CLSID_FileProtocol */
#include <ctxtcall.h>
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)
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);
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;
}
"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\""
" publicKeyToken=\"6595b6414666f1df\" />"
"<file name=\"testlib.dll\">"
+" <comClass"
+" clsid=\"{0000033a-0000-0000-c000-000000000046}\""
+" progid=\"FTMarshal\""
+" />"
+" <comClass"
+" clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
+" progid=\"WineOOPTest\""
+" />"
" <comClass description=\"Test com class\""
" clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
" progid=\"ProgId.ProgId\""
" <comClass clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
" progid=\"StdFont\""
" />"
+" <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
+" <progid>ProgId.ProgId.1</progid>"
+" </comClass>"
" <comInterfaceProxyStub "
" name=\"Iifaceps\""
" iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
" iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
" proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
" />"
+" <clrClass "
+" clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
+" name=\"clrclass\""
+" >"
+" <progid>clrprogid.1</progid>"
+" </clrClass>"
"</assembly>";
DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
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);
}
{
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;
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);
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';
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];
/* 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);
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;
/* 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);
{
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);
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)
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");
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);
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);
}
static void test_CoRegisterClassObject(void)
{
+ ULONG_PTR ctxcookie;
+ HANDLE handle;
DWORD cookie;
HRESULT hr;
IClassFactory *pcf;
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();
}
static inline BOOL is_module_loaded(const char *module)
{
- return GetModuleHandle(module) != 0;
+ return GetModuleHandleA(module) != 0;
}
static void test_CoFreeUnusedLibraries(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);
/* 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);
{
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);
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();
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;
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;
}
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;
DWORD class_reg;
HRESULT hres;
- if(!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx")) {
+ if(!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) {
win_skip("skipping OleCreateDefaultHandler tests\n");
return;
}
#include <wine/test.h>
+#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 */
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,
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;
}
IDataObject* pDataObj, DWORD grfKeyState,
POINTL pt, DWORD* pdwEffect)
{
- return E_NOTIMPL;
+ CHECK_EXPECT(DropTarget_Drop);
+ return 0xbeefbeef;
}
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) ||
BOOL fEscapePressed,
DWORD grfKeyState)
{
- /* always drop */
+ CHECK_EXPECT(DropSource_QueryContinueDrag);
return DRAGDROP_S_DROP;
}
IDropSource *iface,
DWORD dwEffect)
{
+ CHECK_EXPECT(DropSource_GiveFeedback);
return DRAGDROP_S_USEDEFAULTCURSORS;
}
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,
IDataObject_AddRef(iface);
return S_OK;
}
+
+ trace("DataObject_QueryInterface: %s\n", wine_dbgstr_guid(riid));
return E_NOINTERFACE;
}
FORMATETC *pformatetcIn,
STGMEDIUM *pmedium)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
FORMATETC *pformatetc,
STGMEDIUM *pmedium)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
IDataObject *iface,
FORMATETC *pformatetc)
{
+ CHECK_EXPECT(DataObject_QueryGetData);
return S_OK;
}
FORMATETC *pformatectIn,
FORMATETC *pformatetcOut)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
STGMEDIUM *pmedium,
BOOL fRelease)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
DWORD dwDirection,
IEnumFORMATETC **ppenumFormatEtc)
{
+ CHECK_EXPECT(DataObject_EnumFormatEtc);
+ *ppenumFormatEtc = &EnumFORMATETC;
+ formats_enumerated = FALSE;
return S_OK;
}
IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
IDataObject *iface,
DWORD dwConnection)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
IDataObject *iface,
IEnumSTATDATA **ppenumAdvise)
{
+ ok(0, "unexpected call\n");
return E_NOTIMPL;
}
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)
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");
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);
#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 =
{
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,
return S_OK;
}
+ if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection))
+ {
+ *ppvObj = &ExternalConnection;
+ return S_OK;
+ }
+
*ppvObj = NULL;
return E_NOINTERFACE;
}
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)
{
SetEvent((HANDLE)msg.lParam);
}
else
- DispatchMessage(&msg);
+ DispatchMessageA(&msg);
}
HeapFree(GetProcessHeap(), 0, data);
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;
/* 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" );
IStream *pStream = NULL;
cLocks = 0;
+ external_connections = 0;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, CreateStreamOnHGlobal);
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);
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 */
IUnknown *pProxy = NULL;
cLocks = 0;
+ external_connections = 0;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, CreateStreamOnHGlobal);
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);
IStream_Release(pStream);
ok_more_than_one_lock();
+ ok_zero_external_conn();
+ ok_last_release_closes(FALSE);
IUnknown_Release(pProxy);
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);
static const LARGE_INTEGER llZero;
cLocks = 0;
+ external_connections = 0;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, CreateStreamOnHGlobal);
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);
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);
}
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);
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);
}
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);
ok_ole_success(hr, CoUnmarshalInterface);
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);
IStream_Release(pStream);
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);
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);
}
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 */
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 */
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);
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 */
}
ok_more_than_one_lock();
+ ok_non_zero_external_conn();
/* release the original proxy to test that we successfully keep the
* original object alive */
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);
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 */
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);
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);
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);
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);
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);
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);
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);
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);
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);
struct ncu_params ncu_params;
cLocks = 0;
+ external_connections = 0;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, CreateStreamOnHGlobal);
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);
CloseHandle(thread);
ok_no_locks();
+ ok_zero_external_conn();
+ ok_last_release_closes(TRUE);
end_host_object(host_tid, host_thread);
}
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);
}
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);
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);
}
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();
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);
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();
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" );
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);
/* 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);
}
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 */
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);
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
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
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);
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);
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 );
IUnknown *pProxy2 = NULL;
cLocks = 0;
+ external_connections = 0;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, CreateStreamOnHGlobal);
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);
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();
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;
end_host_object(tid, thread);
- PostMessage(hwnd, WM_QUIT, 0, 0);
+ PostMessageA(hwnd, WM_QUIT, 0, 0);
return 0;
}
/* 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);
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);
}
LPVOID *ppvObj)
{
*ppvObj = NULL;
- SendMessage(hwnd_app, WM_USER+2, 0, 0);
+ SendMessageA(hwnd_app, WM_USER+2, 0, 0);
return S_OK;
}
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);
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);
}
{
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);
}
}
}
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
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");
}
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;
}
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
{
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);
}
}
}
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;
HANDLE quit_event;
HANDLE ready_event;
- heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
+ heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
cLocks = 0;
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);
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 );
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);
}
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;
START_TEST(marshal)
{
- HMODULE hOle32 = GetModuleHandle("ole32");
+ HMODULE hOle32 = GetModuleHandleA("ole32");
int argc;
char **argv;
/* 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();
#include <winbase.h>
#include <winnls.h>
#include <wingdi.h>
+#include <winreg.h>
#include <ole2.h>
//#include "objbase.h"
//#include "shlguid.h"
#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,
{ NULL, 0 }
};
- GetSystemDirectory(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0]));
+ GetSystemDirectoryA(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0]));
expected_method_list = methods_cacheinitnew;
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;
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; i<sizeof(ole_data)/sizeof(DWORD); i++)
+ ok(((DWORD*)&ole_data)[i] == 0, "ole_data[%d] = %x\n", i, ((DWORD*)&ole_data)[i]);
+
+ SET_EXPECT(Storage_OpenStream_Ole);
+ hr = SetConvertStg(&Storage, TRUE);
+ ok(hr == S_OK, "SetConvertStg returned %x\n", hr);
+ CHECK_CALLED(Storage_OpenStream_Ole);
+
+ SET_EXPECT(Storage_OpenStream_CompObj);
+ SET_EXPECT(Storage_Stat);
+ SET_EXPECT(Storage_CreateStream_CompObj);
+ hr = WriteFmtUserTypeStg(&Storage, 0, NULL);
+ ok(hr == S_OK, "WriteFmtUserTypeStg returned %x\n", hr);
+ todo_wine CHECK_CALLED(Storage_OpenStream_CompObj);
+ CHECK_CALLED(Storage_Stat);
+ CHECK_CALLED(Storage_CreateStream_CompObj);
+ 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);
+
+ ret = IStream_Release(comp_obj_stream);
+ ok(!ret, "comp_obj_stream was not freed\n");
+ ret = IStream_Release(ole_stream);
+ ok(!ret, "ole_stream was not freed\n");
+
+ ret = RegDeleteKeyA(root, "AutoConvertTo");
+ ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
+ ret = RegDeleteKeyA(root, "");
+ ok(ret == ERROR_SUCCESS, "RegDeleteKey error %u\n", ret);
+ RegCloseKey(root);
+}
+
START_TEST(ole2)
{
DWORD dwRegister;
test_OleRun();
test_OleLockRunning();
test_OleDraw();
+ test_OleDoAutoConvert();
CoUninitialize();
}
static const char *debugstr_guid(const GUID *guid)
{
- static char buf[50];
int i;
if (!guid) return "(null)";
return guid_name[i].name;
}
- sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
- guid->Data1, 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 *******************************/
{
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);
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);
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);
}
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);
}
static HANDLE start_server(const char *argv0)
{
PROCESS_INFORMATION pi;
- STARTUPINFO si;
+ STARTUPINFOA si;
SECURITY_ATTRIBUTES sa;
char cmdline[MAX_PATH * 2];
BOOL ret;
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;
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();
{ 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 */
};
-static void expect(HRESULT hr, VARTYPE vt)
+static void expect(HRESULT hr, VARTYPE vt, BOOL copy)
{
int idx = vt & VT_TYPEMASK;
BYTE flags;
}
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)
static void test_validtypes(void)
{
- PROPVARIANT propvar;
+ PROPVARIANT propvar, copy, uninit;
HRESULT hr;
- unsigned int i;
+ unsigned int i, ret;
+
+ memset(&uninit, 0x77, sizeof(uninit));
- memset(&propvar, 0, sizeof(propvar));
+ 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);
}
}
#include <windef.h>
#include <winbase.h>
+#include <winuser.h>
#define COBJMACROS
#include <objbase.h>
#include <wine/test.h>
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;
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);
}
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);
/* 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);
}
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);
}
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);
}