Author: akhaldi
Date: Tue Nov 17 10:31:59 2015
New Revision: 69909
URL:
http://svn.reactos.org/svn/reactos?rev=69909&view=rev
Log:
[OLE32_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
Modified:
trunk/rostests/winetests/ole32/compobj.c
trunk/rostests/winetests/ole32/marshal.c
trunk/rostests/winetests/ole32/moniker.c
trunk/rostests/winetests/ole32/ole2.c
trunk/rostests/winetests/ole32/propvariant.c
trunk/rostests/winetests/ole32/storage32.c
trunk/rostests/winetests/ole32/usrmarshal.c
Modified: trunk/rostests/winetests/ole32/compobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/compobj.c…
==============================================================================
--- trunk/rostests/winetests/ole32/compobj.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/compobj.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -46,6 +46,32 @@
extern const IID GUID_NULL;
+#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(CreateStub);
+
/* functions that are not present on all versions of Windows */
static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
@@ -135,6 +161,7 @@
return 1; /* non-heap-based object */
}
+static IID create_instance_iid;
static HRESULT WINAPI Test_IClassFactory_CreateInstance(
LPCLASSFACTORY iface,
IUnknown *pUnkOuter,
@@ -142,6 +169,7 @@
LPVOID *ppvObj)
{
*ppvObj = NULL;
+ create_instance_iid = *riid;
if (pUnkOuter) return CLASS_E_NOAGGREGATION;
return E_NOINTERFACE;
}
@@ -772,6 +800,30 @@
CoUninitialize();
}
+static void test_CoCreateInstanceEx(void)
+{
+ MULTI_QI qi_res = { &IID_IMoniker };
+ DWORD cookie;
+ HRESULT hr;
+
+ CoInitialize(NULL);
+
+ hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown
*)&Test_ClassFactory,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
+ ok_ole_success(hr, "CoRegisterClassObject");
+
+ create_instance_iid = IID_NULL;
+ hr = CoCreateInstanceEx(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1,
&qi_res);
+ ok(hr == E_NOINTERFACE, "CoCreateInstanceEx failed: %08x\n", hr);
+ ok(IsEqualGUID(&create_instance_iid, qi_res.pIID), "Unexpected
CreateInstance iid %s\n",
+ wine_dbgstr_guid(&create_instance_iid));
+
+ hr = CoRevokeClassObject(cookie);
+ ok_ole_success(hr, "CoRevokeClassObject");
+
+ CoUninitialize();
+}
+
static ATOM register_dummy_class(void)
{
WNDCLASSA wc =
@@ -912,6 +964,59 @@
CoUninitialize();
}
+static IUnknown Test_Unknown;
+
+static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void
**ppv)
+{
+ return IUnknown_QueryInterface(&Test_Unknown, riid, ppv);
+}
+
+static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt,
ULONG *fetched)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
+ EnumOLEVERB_QueryInterface,
+ EnumOLEVERB_AddRef,
+ EnumOLEVERB_Release,
+ EnumOLEVERB_Next,
+ EnumOLEVERB_Skip,
+ EnumOLEVERB_Reset,
+ EnumOLEVERB_Clone
+};
+
+static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl };
+
static HRESULT WINAPI Test_IUnknown_QueryInterface(
IUnknown *iface,
REFIID riid,
@@ -919,16 +1024,17 @@
{
if (ppvObj == NULL) return E_POINTER;
- if (IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IWineTest))
- {
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) {
*ppvObj = iface;
- IUnknown_AddRef(iface);
- return S_OK;
- }
-
- *ppvObj = NULL;
- return E_NOINTERFACE;
+ }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) {
+ *ppvObj = &EnumOLEVERB;
+ }else {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppvObj);
+ return S_OK;
}
static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
@@ -949,6 +1055,8 @@
};
static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
+
+static IPSFactoryBuffer *ps_factory_buffer;
static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
IPSFactoryBuffer * This,
@@ -993,7 +1101,13 @@
/* [unique][in] */ IUnknown *pUnkServer,
/* [out] */ IRpcStubBuffer **ppStub)
{
- return E_NOTIMPL;
+ CHECK_EXPECT(CreateStub);
+
+ ok(pUnkServer == (IUnknown*)&Test_Unknown, "unexpected pUnkServer
%p\n", pUnkServer);
+ if(!ps_factory_buffer)
+ return E_NOTIMPL;
+
+ return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB,
pUnkServer, ppStub);
}
static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
@@ -1037,9 +1151,31 @@
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
ok_ole_success(hr, "CreateStreamOnHGlobal");
+ SET_EXPECT(CreateStub);
hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC,
NULL, MSHLFLAGS_NORMAL);
ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead
of 0x%08x\n", hr);
+ CHECK_CALLED(CreateStub);
+
+ hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
+ ok_ole_success(hr, "CoGetPSClsid");
+
+ hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
&IID_IPSFactoryBuffer, (void **)&ps_factory_buffer);
+ ok_ole_success(hr, "CoGetClassObject");
+
+ hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer);
+ ok_ole_success(hr, "CoRegisterPSClsid");
+
+ SET_EXPECT(CreateStub);
+ hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB,
MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of
0x%08x\n", hr);
+ CHECK_CALLED(CreateStub);
+
+ hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown,
MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of
0x%08x\n", hr);
+
IStream_Release(stream);
+ IPSFactoryBuffer_Release(ps_factory_buffer);
+ ps_factory_buffer = NULL;
hr = CoRevokeClassObject(dwRegistrationKey);
ok_ole_success(hr, "CoRevokeClassObject");
@@ -2135,9 +2271,45 @@
return 0;
}
+static const char cls_name[] = "cowait_test_class";
+static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg)
+{
+ HANDLE *handles = arg;
+ BOOL success;
+ DWORD index;
+ HRESULT hr;
+ HWND hWnd;
+ MSG msg;
+
+ hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
+
+ hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0,
640, 480, 0, 0, 0, 0);
+ ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
+
+ index = 0xdeadbeef;
+ PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
+ hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
+ ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n",
hr);
+ ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n",
index);
+ success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
+ ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
+
+ index = 0xdeadbeef;
+ PostMessageA(hWnd, WM_USER, 0, 0);
+ hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
+ ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n",
hr);
+ ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n",
index);
+ success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE);
+ ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
+
+ DestroyWindow(hWnd);
+ CoUninitialize();
+ return 0;
+}
+
static void test_CoWaitForMultipleHandles(void)
{
- static const char cls_name[] = "cowait_test_class";
HANDLE handles[2], thread;
DWORD index, tid;
WNDCLASSEXA wc;
@@ -2440,6 +2612,12 @@
CloseHandle(thread);
}
+ /* test message pumping when CoWaitForMultipleHandles is called from non main
apartment thread */
+ thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0,
&tid);
+ index = WaitForSingleObject(thread, 500);
+ ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+ CloseHandle(thread);
+
CloseHandle(handles[0]);
CloseHandle(handles[1]);
DestroyWindow(hWnd);
@@ -2493,6 +2671,7 @@
test_CoCreateInstance();
test_ole_menu();
test_CoGetClassObject();
+ test_CoCreateInstanceEx();
test_CoRegisterMessageFilter();
test_CoRegisterPSClsid();
test_CoGetPSClsid();
Modified: trunk/rostests/winetests/ole32/marshal.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/marshal.c…
==============================================================================
--- trunk/rostests/winetests/ole32/marshal.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/marshal.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -122,7 +122,7 @@
static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface,
REFIID riid, void **ppv)
{
- ok(0, "unxpected call\n");
+ ok(0, "unexpected call\n");
*ppv = NULL;
return E_NOINTERFACE;
}
@@ -202,6 +202,24 @@
static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
+static ULONG WINAPI TestCrash_IUnknown_Release(LPUNKNOWN iface)
+{
+ UnlockModule();
+ if(!cLocks) {
+ trace("crashing...\n");
+ *(int**)0xc = 0;
+ }
+ return 1; /* non-heap-based object */
+}
+
+static const IUnknownVtbl TestCrashUnknown_Vtbl =
+{
+ Test_IUnknown_QueryInterface,
+ Test_IUnknown_AddRef,
+ TestCrash_IUnknown_Release,
+};
+
+static IUnknown TestCrash_Unknown = { &TestCrashUnknown_Vtbl };
static HRESULT WINAPI Test_IClassFactory_QueryInterface(
LPCLASSFACTORY iface,
@@ -1087,6 +1105,63 @@
ok_last_release_closes(TRUE);
end_host_object(host_tid, host_thread);
+}
+
+static BOOL crash_thread_success;
+
+static DWORD CALLBACK crash_couninitialize_proc(void *p)
+{
+ IStream *stream;
+ HRESULT hr;
+
+ cLocks = 0;
+
+ CoInitialize(NULL);
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown,
MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+
+ IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+
+ hr = CoReleaseMarshalData(stream);
+ ok_ole_success(hr, CoReleaseMarshalData);
+
+ ok_no_locks();
+
+ hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown,
MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+
+ ok_more_than_one_lock();
+
+ trace("CoUninitialize >>>\n");
+ CoUninitialize();
+ trace("CoUninitialize <<<\n");
+
+ ok_no_locks();
+
+ IStream_Release(stream);
+ crash_thread_success = TRUE;
+ return 0;
+}
+
+static void test_crash_couninitialize(void)
+{
+ HANDLE thread;
+ DWORD tid;
+
+ if(!GetProcAddress(GetModuleHandleA("kernel32.dll"),
"CreateActCtxW")) {
+ win_skip("Skipping crash tests on win2k.\n");
+ return;
+ }
+
+ crash_thread_success = FALSE;
+ thread = CreateThread(NULL, 0, crash_couninitialize_proc, NULL, 0, &tid);
+ ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
+ CloseHandle(thread);
+ ok(crash_thread_success, "Crash thread failed\n");
}
/* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
@@ -2859,6 +2934,63 @@
static HWND hwnd_app;
+struct local_server
+{
+ IPersist IPersist_iface; /* a nice short interface */
+};
+
+static HRESULT WINAPI local_server_QueryInterface(IPersist *iface, REFIID iid, void
**obj)
+{
+ *obj = NULL;
+
+ if (IsEqualGUID(iid, &IID_IUnknown) ||
+ IsEqualGUID(iid, &IID_IPersist))
+ *obj = iface;
+
+ if (*obj)
+ {
+ IPersist_AddRef(iface);
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI local_server_AddRef(IPersist *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI local_server_Release(IPersist *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid)
+{
+ HRESULT hr;
+
+ *clsid = IID_IUnknown;
+
+ /* Test calling CoDisconnectObject within a COM call */
+ hr = CoDisconnectObject((IUnknown *)iface, 0);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ return S_OK;
+}
+
+static const IPersistVtbl local_server_persist_vtbl =
+{
+ local_server_QueryInterface,
+ local_server_AddRef,
+ local_server_Release,
+ local_server_GetClassID
+};
+
+struct local_server local_server_class =
+{
+ {&local_server_persist_vtbl}
+};
+
static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
LPCLASSFACTORY iface,
REFIID riid,
@@ -2893,12 +3025,12 @@
REFIID riid,
LPVOID *ppvObj)
{
- if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
- {
- *ppvObj = iface;
- return S_OK;
- }
- return CLASS_E_CLASSNOTAVAILABLE;
+ IPersist *persist = &local_server_class.IPersist_iface;
+ HRESULT hr;
+ IPersist_AddRef( persist );
+ hr = IPersist_QueryInterface( persist, riid, ppvObj );
+ IPersist_Release( persist );
+ return hr;
}
static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
@@ -2928,24 +3060,25 @@
DWORD cookie;
HRESULT hr;
HANDLE ready_event;
- HANDLE quit_event;
DWORD wait;
+ HANDLE handles[2];
heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
-
+ ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready
Event");
+ handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
+ handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat
Event");
+
+again:
hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown
*)&TestOOP_ClassFactory,
CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
ok_ole_success(hr, CoRegisterClassObject);
- ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready
Event");
SetEvent(ready_event);
- quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
-
do
{
- wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, 30000, QS_ALLINPUT);
- if (wait == WAIT_OBJECT_0+1)
+ wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT);
+ if (wait == WAIT_OBJECT_0+2)
{
MSG msg;
@@ -2956,12 +3089,20 @@
DispatchMessageA(&msg);
}
}
- }
- while (wait == WAIT_OBJECT_0+1);
+ else if (wait == WAIT_OBJECT_0+1)
+ {
+ hr = CoRevokeClassObject(cookie);
+ ok_ole_success(hr, CoRevokeClassObject);
+ goto again;
+ }
+ }
+ while (wait == WAIT_OBJECT_0+2);
ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" );
hr = CoRevokeClassObject(cookie);
ok_ole_success(hr, CoRevokeClassObject);
+ CloseHandle(handles[0]);
+ CloseHandle(handles[1]);
}
static HANDLE create_target_process(const char *arg)
@@ -2976,7 +3117,7 @@
pi.hThread = NULL;
pi.hProcess = NULL;
winetest_get_mainargs( &argv );
- sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
+ sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg);
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);
@@ -2989,10 +3130,13 @@
DWORD cookie;
HRESULT hr;
IClassFactory * cf;
+ IPersist *persist;
DWORD ret;
HANDLE process;
HANDLE quit_event;
HANDLE ready_event;
+ HANDLE repeat_event;
+ CLSID clsid;
heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
@@ -3059,15 +3203,29 @@
ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready
Event");
ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
+
+ hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER,
&IID_IPersist, (void **)&persist);
+ ok_ole_success(hr, CoCreateInstance);
+
+ IPersist_Release(persist);
+
+ hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER,
&IID_IPersist, (void **)&persist);
+ ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE
object should have failed\n");
+
+ /* Re-register the class and try calling CoDisconnectObject from within a call to
that object */
+ repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat
Event");
+ SetEvent(repeat_event);
+ CloseHandle(repeat_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);
+ hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER,
&IID_IPersist, (void **)&persist);
ok_ole_success(hr, CoCreateInstance);
- IClassFactory_Release(cf);
-
- 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");
+ /* GetClassID will call CoDisconnectObject */
+ IPersist_GetClassID(persist, &clsid);
+ IPersist_Release(persist);
quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
SetEvent(quit_event);
@@ -3556,6 +3714,7 @@
test_globalinterfacetable();
test_manualresetevent();
+ test_crash_couninitialize();
/* must be last test as channel hooks can't be unregistered */
test_channel_hook();
Modified: trunk/rostests/winetests/ole32/moniker.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/moniker.c…
==============================================================================
--- trunk/rostests/winetests/ole32/moniker.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/moniker.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -99,7 +99,7 @@
static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface,
REFIID riid, void **ppv)
{
- ok(0, "unxpected call\n");
+ ok(0, "unexpected call\n");
*ppv = NULL;
return E_NOINTERFACE;
}
Modified: trunk/rostests/winetests/ole32/ole2.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/ole2.c?re…
==============================================================================
--- trunk/rostests/winetests/ole32/ole2.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/ole2.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -117,6 +117,32 @@
static HRESULT g_QIFailsWith;
static UINT cf_test_1, cf_test_2, cf_test_3;
+
+/****************************************************************************
+ * PresentationDataHeader
+ *
+ * This structure represents the header of the \002OlePresXXX stream in
+ * the OLE object storage.
+ */
+typedef struct PresentationDataHeader
+{
+ /* clipformat:
+ * - standard clipformat:
+ * DWORD length = 0xffffffff;
+ * DWORD cfFormat;
+ * - or custom clipformat:
+ * DWORD length;
+ * CHAR format_name[length]; (null-terminated)
+ */
+ DWORD unknown3; /* 4, possibly TYMED_ISTREAM */
+ DVASPECT dvAspect;
+ DWORD lindex;
+ DWORD tymed;
+ DWORD unknown7; /* 0 */
+ DWORD dwObjectExtentX;
+ DWORD dwObjectExtentY;
+ DWORD dwSize;
+} PresentationDataHeader;
#define CHECK_EXPECTED_METHOD(method_name) \
do { \
@@ -1045,6 +1071,7 @@
{
HRESULT hr;
IOleObject *pObject;
+ DWORD fmt;
static const struct expected_method methods_oleload[] =
{
@@ -1101,6 +1128,105 @@
IOleObject_Release(pObject);
CHECK_NO_EXTRA_METHODS();
+ }
+
+ for (fmt = CF_TEXT; fmt < CF_MAX; fmt++)
+ {
+ static const WCHAR olrepres[] = {
2,'O','l','e','P','r','e','s','0','0','0',0
};
+ IStorage *stg;
+ IStream *stream;
+ IUnknown *obj;
+ DWORD data, i, tymed, data_size;
+ PresentationDataHeader header;
+ HDC hdc;
+ HGDIOBJ hobj;
+ RECT rc;
+ char buf[256];
+
+ for (i = 0; i < 7; i++)
+ {
+ hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE |
STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &stg);
+ ok(hr == S_OK, "StgCreateDocfile error %#x\n", hr);
+
+ hr = IStorage_SetClass(stg, &CLSID_WineTest);
+ ok(hr == S_OK, "SetClass error %#x\n", hr);
+
+ hr = IStorage_CreateStream(stg, olrepres, STGM_READWRITE |
STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, &stream);
+ ok(hr == S_OK, "CreateStream error %#x\n", hr);
+
+ data = ~0;
+ hr = IStream_Write(stream, &data, sizeof(data), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ data = fmt;
+ hr = IStream_Write(stream, &data, sizeof(data), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ switch (fmt)
+ {
+ case CF_BITMAP:
+ /* FIXME: figure out stream format */
+ hobj = CreateBitmap(1, 1, 1, 1, NULL);
+ data_size = GetBitmapBits(hobj, sizeof(buf), buf);
+ DeleteObject(hobj);
+ break;
+
+ case CF_METAFILEPICT:
+ case CF_ENHMETAFILE:
+ hdc = CreateMetaFileA(NULL);
+ hobj = CloseMetaFile(hdc);
+ data_size = GetMetaFileBitsEx(hobj, sizeof(buf), buf);
+ DeleteMetaFile(hobj);
+ break;
+
+ default:
+ data_size = sizeof(buf);
+ memset(buf, 'A', sizeof(buf));
+ break;
+ }
+
+ tymed = 1 << i;
+
+ header.unknown3 = 4;
+ header.dvAspect = DVASPECT_CONTENT;
+ header.lindex = -1;
+ header.tymed = tymed;
+ header.unknown7 = 0;
+ header.dwObjectExtentX = 1;
+ header.dwObjectExtentY = 1;
+ header.dwSize = data_size;
+ hr = IStream_Write(stream, &header, sizeof(header), NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ hr = IStream_Write(stream, buf, data_size, NULL);
+ ok(hr == S_OK, "Write error %#x\n", hr);
+
+ IStream_Release(stream);
+
+ hr = OleLoad(stg, &IID_IUnknown, NULL, (void **)&obj);
+ /* FIXME: figure out stream format */
+ if (fmt == CF_BITMAP && hr != S_OK)
+ {
+ IStorage_Release(stg);
+ continue;
+ }
+ ok(hr == S_OK, "OleLoad error %#x: cfFormat = %u, tymed = %u\n",
hr, fmt, tymed);
+
+ hdc = CreateCompatibleDC(0);
+ SetRect(&rc, 0, 0, 100, 100);
+ hr = OleDraw(obj, DVASPECT_CONTENT, hdc, &rc);
+ DeleteDC(hdc);
+ if (fmt == CF_METAFILEPICT)
+ ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, tymed =
%u\n", hr, fmt, tymed);
+ else if (fmt == CF_ENHMETAFILE)
+todo_wine
+ ok(hr == S_OK, "OleDraw error %#x: cfFormat = %u, tymed =
%u\n", hr, fmt, tymed);
+ else
+ ok(hr == OLE_E_BLANK || hr == OLE_E_NOTRUNNING || hr == E_FAIL,
"OleDraw should fail: %#x, cfFormat = %u, tymed = %u\n", hr, fmt,
header.tymed);
+
+ IUnknown_Release(obj);
+ IStorage_Release(stg);
+ }
}
}
@@ -1936,7 +2062,6 @@
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_ENHMF;
hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
- todo_wine
ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned
OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
fmtetc.cfFormat = CF_TEXT;
@@ -1945,7 +2070,6 @@
fmtetc.lindex = -1;
fmtetc.tymed = TYMED_NULL;
hr = IDataObject_QueryGetData(pDataObject, &fmtetc);
- todo_wine
ok(hr == OLE_E_NOTRUNNING, "IDataObject_QueryGetData should have returned
OLE_E_NOTRUNNING instead of 0x%08x\n", hr);
hr = IOleObject_QueryInterface(pObject, &IID_IRunnableObject, (void
**)&pRunnableObject);
@@ -2107,7 +2231,7 @@
static HRESULT WINAPI OleRun_GetRunningClass(IRunnableObject *iface, CLSID *clsid)
{
- ok(0, "unxpected\n");
+ ok(0, "unexpected\n");
return E_NOTIMPL;
}
@@ -2119,20 +2243,20 @@
static BOOL WINAPI OleRun_IsRunning(IRunnableObject *iface)
{
- ok(0, "unxpected\n");
+ ok(0, "unexpected\n");
return FALSE;
}
static HRESULT WINAPI OleRun_LockRunning(IRunnableObject *iface, BOOL lock,
BOOL last_unlock_closes)
{
- ok(0, "unxpected\n");
+ ok(0, "unexpected\n");
return E_NOTIMPL;
}
static HRESULT WINAPI OleRun_SetContainedObject(IRunnableObject *iface, BOOL contained)
{
- ok(0, "unxpected\n");
+ ok(0, "unexpected\n");
return E_NOTIMPL;
}
Modified: trunk/rostests/winetests/ole32/propvariant.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/propvaria…
==============================================================================
--- trunk/rostests/winetests/ole32/propvariant.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/propvariant.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -140,7 +140,7 @@
};
-static void expect(HRESULT hr, VARTYPE vt, BOOL copy)
+static void expect(HRESULT hr, VARTYPE vt, BOOL copy, int line)
{
int idx = vt & VT_TYPEMASK;
BYTE flags;
@@ -168,7 +168,12 @@
}
if(flags == PROP_INV)
- ok(hr == copy ? DISP_E_BADVARTYPE : STG_E_INVALIDPARAMETER, "%s (%s): got
%08x\n", wine_vtypes[idx], modifier, hr);
+ {
+ if (copy && (vt & VT_VECTOR))
+ ok(hr == DISP_E_BADVARTYPE || hr == STG_E_INVALIDPARAMETER, "%s (%s):
got %08x (line %d)\n", wine_vtypes[idx], modifier, hr, line);
+ else
+ ok(hr == (copy ? DISP_E_BADVARTYPE : STG_E_INVALIDPARAMETER), "%s (%s):
got %08x (line %d)\n", wine_vtypes[idx], modifier, hr, line);
+ }
else if(flags == PROP_V0)
ok(hr == S_OK, "%s (%s): got %08x\n", wine_vtypes[idx], modifier, hr);
else if(flags & PROP_TODO)
@@ -220,7 +225,7 @@
vt = propvar.vt = i;
memset(©, 0x77, sizeof(copy));
hr = PropVariantCopy(©, &propvar);
- expect(hr, vt, TRUE);
+ expect(hr, vt, TRUE, __LINE__);
if (hr == S_OK)
{
ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt,
copy.vt);
@@ -234,7 +239,7 @@
ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay
unchanged\n", i);
}
hr = PropVariantClear(&propvar);
- expect(hr, vt, FALSE);
+ expect(hr, vt, FALSE, __LINE__);
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);
@@ -244,7 +249,7 @@
vt = propvar.vt = i | VT_ARRAY;
memset(©, 0x77, sizeof(copy));
hr = PropVariantCopy(©, &propvar);
- expect(hr, vt, TRUE);
+ expect(hr, vt, TRUE, __LINE__);
if (hr == S_OK)
{
ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt,
copy.vt);
@@ -257,7 +262,7 @@
ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay
unchanged\n", i);
}
hr = PropVariantClear(&propvar);
- expect(hr, vt, FALSE);
+ expect(hr, vt, FALSE, __LINE__);
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);
@@ -268,7 +273,7 @@
vt = propvar.vt = i | VT_VECTOR;
memset(©, 0x77, sizeof(copy));
hr = PropVariantCopy(©, &propvar);
- expect(hr, vt, TRUE);
+ expect(hr, vt, TRUE, __LINE__);
if (hr == S_OK)
{
ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt,
copy.vt);
@@ -281,7 +286,7 @@
ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay
unchanged\n", i);
}
hr = PropVariantClear(&propvar);
- expect(hr, vt, FALSE);
+ expect(hr, vt, FALSE, __LINE__);
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);
@@ -291,7 +296,7 @@
vt = propvar.vt = i | VT_BYREF;
memset(©, 0x77, sizeof(copy));
hr = PropVariantCopy(©, &propvar);
- expect(hr, vt, TRUE);
+ expect(hr, vt, TRUE, __LINE__);
if (hr == S_OK)
{
ok(copy.vt == propvar.vt, "expected %d, got %d\n", propvar.vt,
copy.vt);
@@ -305,7 +310,7 @@
ok(!ret || broken(ret) /* win2000 */, "%d: copy should stay
unchanged\n", i);
}
hr = PropVariantClear(&propvar);
- expect(hr, vt, FALSE);
+ expect(hr, vt, FALSE, __LINE__);
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);
Modified: trunk/rostests/winetests/ole32/storage32.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/storage32…
==============================================================================
--- trunk/rostests/winetests/ole32/storage32.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/storage32.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -224,7 +224,7 @@
return S_OK;
}
-static ILockBytesVtbl TestLockBytes_Vtbl = {
+static /* const */ ILockBytesVtbl TestLockBytes_Vtbl = {
TestLockBytes_QueryInterface,
TestLockBytes_AddRef,
TestLockBytes_Release,
@@ -517,6 +517,7 @@
ULARGE_INTEGER p;
unsigned char buffer[0x100];
IUnknown *unk;
+ BOOL ret;
DeleteFileA(filenameA);
@@ -695,8 +696,8 @@
IStorage_Release(stg);
}
- r = DeleteFileA(filenameA);
- ok(r, "file should exist\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "file should exist\n");
}
static BOOL touch_file(LPCSTR filename)
@@ -743,6 +744,7 @@
IStorage *stg = NULL, *stg2 = NULL;
HRESULT r;
DWORD stgm;
+ BOOL ret;
/* try opening a zero length file - it should stay zero length */
DeleteFileA(filenameA);
@@ -902,8 +904,8 @@
r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0,
&stg);
ok(r == STG_E_INVALIDFLAG, "should fail\n");
- r = DeleteFileA(filenameA);
- ok(r, "file didn't exist\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "file didn't exist\n");
}
static void test_storage_suminfo(void)
@@ -1226,6 +1228,7 @@
static const WCHAR stmname[] = {
'C','O','N','T','E','N','T','S',0
};
static const WCHAR stmname2[] = {
'A','B','C','D','E','F','G','H','I',0
};
static const WCHAR stmname3[] = {
'A','B','C','D','E','F','G','H','I','J',0
};
+ static const STATSTG stat_null;
STATSTG stat;
IEnumSTATSTG *ee = NULL;
ULONG count;
@@ -1271,10 +1274,12 @@
r = IStorage_DestroyElement(stg, stmname);
ok(r==S_OK, "IStorage->DestroyElement failed\n");
+ memset(&stat, 0xad, sizeof(stat));
count = 0xf00;
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
ok(count == 0, "count wrong\n");
+ ok(memcmp(&stat, &stat_null, sizeof(stat)) == 0, "stat is not
zeroed\n");
/* reset and try again */
r = IEnumSTATSTG_Reset(ee);
@@ -1401,6 +1406,7 @@
static const WCHAR stmname2[] = { 'F','O','O',0 };
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
static const WCHAR stgname2[] = {
'T','E','M','P','S','T','G',0 };
+ BOOL ret;
DeleteFileA(filenameA);
@@ -1521,8 +1527,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_substorage_share(void)
@@ -1533,6 +1539,7 @@
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
static const WCHAR stmname[] = {
'C','O','N','T','E','N','T','S',0
};
static const WCHAR othername[] = {
'N','E','W','N','A','M','E',0 };
+ BOOL ret;
DeleteFileA(filenameA);
@@ -1612,8 +1619,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_revert(void)
@@ -1626,6 +1633,7 @@
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
static const WCHAR stgname2[] = {
'T','E','M','P','S','T','G',0 };
STATSTG statstg;
+ BOOL ret;
DeleteFileA(filenameA);
@@ -1743,8 +1751,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
/* Revert only invalidates objects in transacted mode */
r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
@@ -1763,8 +1771,8 @@
IStream_Release(stm);
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_parent_free(void)
@@ -1776,6 +1784,7 @@
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
ULONG ref;
STATSTG statstg;
+ BOOL ret;
DeleteFileA(filenameA);
@@ -1825,8 +1834,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_nonroot_transacted(void)
@@ -1837,6 +1846,7 @@
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
static const WCHAR stmname[] = {
'C','O','N','T','E','N','T','S',0
};
static const WCHAR stmname2[] = { 'F','O','O',0 };
+ BOOL ret;
DeleteFileA(filenameA);
@@ -1945,8 +1955,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_ReadClassStm(void)
@@ -2415,6 +2425,7 @@
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 const WCHAR strmNameW[] =
{1,'C','o','m','p','O','b','j',0};
+ static const STATSTG statstg_null;
hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0,
&stg);
ok(hr == S_OK, "should succeed, res=%x\n", hr);
@@ -2433,6 +2444,7 @@
BOOL found = FALSE;
STATSTG statstg;
DWORD got;
+ memset(&statstg, 0xad, sizeof(statstg));
while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK
&& got == 1)
{
if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
@@ -2441,6 +2453,7 @@
ok(0, "found unexpected stream or storage\n");
CoTaskMemFree(statstg.pwcsName);
}
+ ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0,
"statstg is not zeroed\n");
ok(found == TRUE, "expected storage to contain stream
\\0001CompObj\n");
IEnumSTATSTG_Release(stat);
}
@@ -2457,6 +2470,7 @@
BOOL found = FALSE;
STATSTG statstg;
DWORD got;
+ memset(&statstg, 0xad, sizeof(statstg));
while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK
&& got == 1)
{
if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
@@ -2465,6 +2479,7 @@
ok(0, "found unexpected stream or storage\n");
CoTaskMemFree(statstg.pwcsName);
}
+ ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0,
"statstg is not zeroed\n");
ok(found == TRUE, "expected storage to contain stream
\\0001CompObj\n");
IEnumSTATSTG_Release(stat);
}
@@ -2929,6 +2944,7 @@
static const WCHAR stgname2[] = { 'S','T','G',0 };
static const WCHAR stmname[] = {
'C','O','N','T','E','N','T','S',0
};
static const WCHAR stmname2[] = { 'E','N','T','S',0
};
+ BOOL ret;
DeleteFileA(filenameA);
@@ -2985,8 +3001,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_toplevel_stat(void)
@@ -3072,6 +3088,7 @@
HRESULT r;
ULONG ref;
static const WCHAR stgname[] = {
'P','E','R','M','S','T','G',0 };
+ BOOL ret;
DeleteFileA(filenameA);
@@ -3107,8 +3124,8 @@
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_copyto_locking(void)
@@ -3119,6 +3136,7 @@
static const WCHAR stgname[] = { 'S','T','G','1',0
};
static const WCHAR stgname2[] = { 'S','T','G','2',0
};
static const WCHAR stmname[] = {
'C','O','N','T','E','N','T','S',0
};
+ BOOL ret;
DeleteFileA(filenameA);
@@ -3158,8 +3176,8 @@
IStorage_Release(stg2);
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_copyto_recursive(void)
@@ -3168,6 +3186,7 @@
HRESULT r;
static const WCHAR stgname[] = { 'S','T','G','1',0
};
static const WCHAR stgname2[] = { 'S','T','G','2',0
};
+ BOOL ret;
DeleteFileA(filenameA);
@@ -3209,8 +3228,8 @@
IStorage_Release(stg2);
IStorage_Release(stg);
- r = DeleteFileA(filenameA);
- ok( r == TRUE, "deleted file\n");
+ ret = DeleteFileA(filenameA);
+ ok(ret, "deleted file\n");
}
static void test_hglobal_storage_creation(void)
Modified: trunk/rostests/winetests/ole32/usrmarshal.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/ole32/usrmarsha…
==============================================================================
--- trunk/rostests/winetests/ole32/usrmarshal.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/ole32/usrmarshal.c [iso-8859-1] Tue Nov 17 10:31:59 2015
@@ -89,6 +89,91 @@
umcb->pStubMsg = stub_msg;
umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
+}
+
+#define RELEASEMARSHALDATA WM_USER
+
+struct host_object_data
+{
+ IStream *stream;
+ IID iid;
+ IUnknown *object;
+ MSHLFLAGS marshal_flags;
+ HANDLE marshal_event;
+ IMessageFilter *filter;
+};
+
+static DWORD CALLBACK host_object_proc(LPVOID p)
+{
+ struct host_object_data *data = p;
+ HRESULT hr;
+ MSG msg;
+
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ if (data->filter)
+ {
+ IMessageFilter * prev_filter = NULL;
+ hr = CoRegisterMessageFilter(data->filter, &prev_filter);
+ if (prev_filter) IMessageFilter_Release(prev_filter);
+ ok(hr == S_OK, "got %08x\n", hr);
+ }
+
+ hr = CoMarshalInterface(data->stream, &data->iid, data->object,
MSHCTX_INPROC, NULL, data->marshal_flags);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ /* force the message queue to be created before signaling parent thread */
+ PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+ SetEvent(data->marshal_event);
+
+ while (GetMessageA(&msg, NULL, 0, 0))
+ {
+ if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
+ {
+ CoReleaseMarshalData(data->stream);
+ SetEvent((HANDLE)msg.lParam);
+ }
+ else
+ DispatchMessageA(&msg);
+ }
+
+ HeapFree(GetProcessHeap(), 0, data);
+
+ CoUninitialize();
+
+ return hr;
+}
+
+static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS
marshal_flags, IMessageFilter *filter, HANDLE *thread)
+{
+ DWORD tid = 0;
+ HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+ struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
+
+ data->stream = stream;
+ data->iid = *riid;
+ data->object = object;
+ data->marshal_flags = marshal_flags;
+ data->marshal_event = marshal_event;
+ data->filter = filter;
+
+ *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
+
+ /* wait for marshaling to complete before returning */
+ ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
+ CloseHandle(marshal_event);
+
+ return tid;
+}
+
+static void end_host_object(DWORD tid, HANDLE thread)
+{
+ 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" );
+ CloseHandle(thread);
}
static const char cf_marshaled[] =
@@ -533,6 +618,17 @@
Test_IUnknown_Release,
};
+struct test_stream
+{
+ IStream IStream_iface;
+ LONG refs;
+};
+
+static inline struct test_stream *impl_from_IStream(IStream *iface)
+{
+ return CONTAINING_RECORD(iface, struct test_stream, IStream_iface);
+}
+
static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface,
REFIID riid, LPVOID *ppvObj)
{
@@ -552,12 +648,14 @@
static ULONG WINAPI Test_IStream_AddRef(IStream *iface)
{
- return 2; /* non-heap-based object */
+ struct test_stream *This = impl_from_IStream(iface);
+ return InterlockedIncrement(&This->refs);
}
static ULONG WINAPI Test_IStream_Release(IStream *iface)
{
- return 1; /* non-heap-based object */
+ struct test_stream *This = impl_from_IStream(iface);
+ return InterlockedDecrement(&This->refs);
}
static const IStreamVtbl TestStream_Vtbl =
@@ -569,13 +667,15 @@
};
static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 };
-static IStream Test_Stream = { &TestStream_Vtbl };
+static TestUnknown Test_Unknown2 = { {&TestUnknown_Vtbl}, 1 };
+static struct test_stream Test_Stream = { {&TestStream_Vtbl}, 1 };
+static struct test_stream Test_Stream2 = { {&TestStream_Vtbl}, 1 };
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *,
REFIID);
unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char
*, IUnknown *, REFIID);
unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *,
IUnknown **, REFIID);
-static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx)
+static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in,
BOOL out)
{
USER_MARSHAL_CB umcb;
MIDL_STUB_MESSAGE stub_msg;
@@ -644,11 +744,17 @@
CoReleaseMarshalData(stm);
IStream_Release(stm);
- unk2 = NULL;
+ Test_Unknown2.refs = 1;
+ unk2 = &Test_Unknown2.IUnknown_iface;
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size,
umcb_ctx);
+ umcb.pStubMsg->IsClient = client;
+ umcb.pStubMsg->fIsIn = in;
+ umcb.pStubMsg->fIsOut = out;
+
WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2,
&IID_IUnknown);
ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
+ ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
HeapFree(GetProcessHeap(), 0, buffer);
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_INPROC);
IUnknown_Release(unk2);
@@ -663,17 +769,26 @@
*/
/* All three are marshalled as inproc */
- marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC);
- marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC);
- marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff));
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC, 0,0,0);
+ marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC,0,0,0);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff),0,0,0);
/* All three are marshalled as remote */
- marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE);
- marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_DIFFERENTMACHINE);
- marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE,
0xffff));
-}
-
-static void test_marshal_STGMEDIUM(void)
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,0);
+ marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE,
MSHCTX_DIFFERENTMACHINE,0,0,0);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE,
0xffff),0,0,0);
+
+ /* Test different combinations of client, in and out */
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,1);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,0);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,1);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,0);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,1);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,0);
+ marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,1);
+}
+
+static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out)
{
USER_MARSHAL_CB umcb;
MIDL_STUB_MESSAGE stub_msg;
@@ -682,13 +797,17 @@
ULONG size, expect_size;
STGMEDIUM med, med2;
IUnknown *unk = &Test_Unknown.IUnknown_iface;
- IStream *stm = &Test_Stream;
+ IStream *stm = &Test_Stream.IStream_iface;
/* TYMED_NULL with pUnkForRelease */
+
+ Test_Unknown.refs = 1;
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 2 *
sizeof(DWORD), unk, &IID_IUnknown);
expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
+ *(DWORD*)expect_buffer = TYMED_NULL;
+ *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer,
expect_size, MSHCTX_DIFFERENTMACHINE);
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags,
expect_buffer + 2 * sizeof(DWORD), unk, &IID_IUnknown);
@@ -709,25 +828,41 @@
ok(!memcmp(buffer+8, expect_buffer + 8, expect_buffer_end - expect_buffer - 8),
"buffer mismatch\n");
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size,
MSHCTX_DIFFERENTMACHINE);
-
- /* native crashes if this is uninitialised, presumably because it
- tries to release it */
+ umcb.pStubMsg->IsClient = client;
+ umcb.pStubMsg->fIsIn = in;
+ umcb.pStubMsg->fIsOut = out;
+
+ Test_Unknown2.refs = 1;
+ med2.tymed = TYMED_NULL;
+ U(med2).pstm = NULL;
+ med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
+
+ STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
+
+ ok(med2.tymed == TYMED_NULL, "got tymed %x\n", med2.tymed);
+ ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
+ ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
+ STGMEDIUM_UserFree(&umcb.Flags, &med2);
+
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer,
expect_size, MSHCTX_DIFFERENTMACHINE);
med2.tymed = TYMED_NULL;
U(med2).pstm = NULL;
med2.pUnkForRelease = NULL;
-
- STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
-
- ok(med2.tymed == TYMED_NULL, "got tymed %x\n", med2.tymed);
- ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
-
- HeapFree(GetProcessHeap(), 0, buffer);
+ STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
STGMEDIUM_UserFree(&umcb.Flags, &med2);
+ ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
+
HeapFree(GetProcessHeap(), 0, expect_buffer);
/* TYMED_ISTREAM with pUnkForRelease */
+
+ Test_Unknown.refs = 1;
+ Test_Stream.refs = 1;
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 3 *
sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
@@ -736,6 +871,9 @@
expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
/* There may be a hole between the two interfaces so init the buffer to something */
memset(expect_buffer, 0xcc, expect_size);
+ *(DWORD*)expect_buffer = TYMED_ISTREAM;
+ *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
+ *((DWORD*)expect_buffer + 2) = 0xcafe;
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer,
expect_size, MSHCTX_DIFFERENTMACHINE);
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags,
expect_buffer + 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags,
expect_buffer_end, unk, &IID_IUnknown);
@@ -759,24 +897,98 @@
ok(!memcmp(buffer + 12, expect_buffer + 12, (buffer_end - buffer) - 12), "buffer
mismatch\n");
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size,
MSHCTX_DIFFERENTMACHINE);
-
- /* native crashes if this is uninitialised, presumably because it
- tries to release it */
+ umcb.pStubMsg->IsClient = client;
+ umcb.pStubMsg->fIsIn = in;
+ umcb.pStubMsg->fIsOut = out;
+
+ Test_Stream2.refs = 1;
+ Test_Unknown2.refs = 1;
+ med2.tymed = TYMED_ISTREAM;
+ U(med2).pstm = &Test_Stream2.IStream_iface;
+ med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
+
+ STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
+
+ ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
+ ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n");
+ ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
+ ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
+ ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
+ STGMEDIUM_UserFree(&umcb.Flags, &med2);
+
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer,
expect_size, MSHCTX_DIFFERENTMACHINE);
med2.tymed = TYMED_NULL;
U(med2).pstm = NULL;
med2.pUnkForRelease = NULL;
+ STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
+ STGMEDIUM_UserFree(&umcb.Flags, &med2);
+
+ ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
+ ok(Test_Stream.refs == 1, "got %d\n", Test_Stream.refs);
+
+ HeapFree(GetProcessHeap(), 0, expect_buffer);
+
+ /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
+
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
+ expect_size = 3 * sizeof(DWORD);
+
+ med.tymed = TYMED_ISTREAM;
+ U(med).pstm = NULL;
+ med.pUnkForRelease = NULL;
+
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
+ size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
+ ok(size == expect_size, "size %d should be %d bytes\n", size,
expect_size);
+
+ buffer = HeapAlloc(GetProcessHeap(), 0, size);
+ memset(buffer, 0xcc, size);
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size,
MSHCTX_DIFFERENTMACHINE);
+ buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
+ ok(buffer_end - buffer == expect_size, "buffer size mismatch\n");
+ ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer);
+ ok(*((DWORD*)buffer+1) == 0, "got %08x\n", *((DWORD*)buffer+1));
+ ok(*((DWORD*)buffer+2) == 0, "got %08x\n", *((DWORD*)buffer+2));
+
+ init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size,
MSHCTX_DIFFERENTMACHINE);
+ umcb.pStubMsg->IsClient = client;
+ umcb.pStubMsg->fIsIn = in;
+ umcb.pStubMsg->fIsOut = out;
+
+ Test_Stream2.refs = 1;
+ Test_Unknown2.refs = 1;
+ med2.tymed = TYMED_ISTREAM;
+ U(med2).pstm = &Test_Stream2.IStream_iface;
+ med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
- ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n");
- ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
+ ok(U(med2).pstm == NULL, "Incorrectly unmarshalled\n");
+ ok(med2.pUnkForRelease == &Test_Unknown2.IUnknown_iface, "Incorrectly
unmarshalled\n");
+ ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
+ ok(Test_Unknown2.refs == 1, "got %d\n", Test_Unknown2.refs);
HeapFree(GetProcessHeap(), 0, buffer);
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0,
MSHCTX_DIFFERENTMACHINE);
STGMEDIUM_UserFree(&umcb.Flags, &med2);
-
- HeapFree(GetProcessHeap(), 0, expect_buffer);
+}
+
+static void test_marshal_STGMEDIUM(void)
+{
+ marshal_STGMEDIUM(0, 0, 0);
+ marshal_STGMEDIUM(0, 0, 1);
+ marshal_STGMEDIUM(0, 1, 0);
+ marshal_STGMEDIUM(0, 1, 1);
+ /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get
zero-initialised.
+ However since inline stubs don't set fIsIn or fIsOut this behaviour would
break
+ ref counting in GetDataHere_Proxy for example, as we'd end up not releasing
the original
+ interface. For simplicity we don't test or implement this. */
+ marshal_STGMEDIUM(1, 1, 1);
}
static void test_marshal_SNB(void)
@@ -984,9 +1196,156 @@
DeleteObject(hBrush);
}
+struct obj
+{
+ IDataObject IDataObject_iface;
+};
+
+static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj)
+{
+ *obj = NULL;
+
+ if (IsEqualGUID(iid, &IID_IUnknown) ||
+ IsEqualGUID(iid, &IID_IDataObject))
+ *obj = iface;
+
+ if (*obj)
+ {
+ IDataObject_AddRef(iface);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI obj_AddRef(IDataObject *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI obj_Release(IDataObject *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt,
+ STGMEDIUM *med)
+{
+ ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease );
+
+ if (fmt->cfFormat == 2)
+ {
+ IStream_Release(U(med)->pstm);
+ U(med)->pstm = &Test_Stream2.IStream_iface;
+ }
+
+ return S_OK;
+}
+
+static const IDataObjectVtbl obj_data_object_vtbl =
+{
+ obj_QueryInterface,
+ obj_AddRef,
+ obj_Release,
+ NULL, /* GetData */
+ obj_DO_GetDataHere,
+ NULL, /* QueryGetData */
+ NULL, /* GetCanonicalFormatEtc */
+ NULL, /* SetData */
+ NULL, /* EnumFormatEtc */
+ NULL, /* DAdvise */
+ NULL, /* DUnadvise */
+ NULL /* EnumDAdvise */
+};
+
+static struct obj obj =
+{
+ {&obj_data_object_vtbl}
+};
+
+static void test_GetDataHere_Proxy(void)
+{
+ HRESULT hr;
+ IStream *stm;
+ HANDLE thread;
+ DWORD tid;
+ static const LARGE_INTEGER zero;
+ IDataObject *data;
+ FORMATETC fmt;
+ STGMEDIUM med;
+
+ hr = CreateStreamOnHGlobal( NULL, TRUE, &stm );
+ ok( hr == S_OK, "got %08x\n", hr );
+ tid = start_host_object2( stm, &IID_IDataObject, (IUnknown
*)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread );
+
+ IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL );
+ hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data );
+ ok( hr == S_OK, "got %08x\n", hr );
+ IStream_Release( stm );
+
+ Test_Stream.refs = 1;
+ Test_Stream2.refs = 1;
+ Test_Unknown.refs = 1;
+
+ fmt.cfFormat = 1;
+ fmt.ptd = NULL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ U(med).pstm = NULL;
+ med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
+
+ fmt.tymed = med.tymed = TYMED_NULL;
+ hr = IDataObject_GetDataHere( data, &fmt, &med );
+ ok( hr == DV_E_TYMED, "got %08x\n", hr );
+
+ for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1)
+ {
+ med.tymed = fmt.tymed;
+ hr = IDataObject_GetDataHere( data, &fmt, &med );
+ ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08x
for tymed %d\n", hr, fmt.tymed );
+ ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
+ }
+
+ fmt.tymed = TYMED_ISTREAM;
+ med.tymed = TYMED_ISTORAGE;
+ hr = IDataObject_GetDataHere( data, &fmt, &med );
+ ok( hr == DV_E_TYMED, "got %08x\n", hr );
+
+ fmt.tymed = med.tymed = TYMED_ISTREAM;
+ U(med).pstm = &Test_Stream.IStream_iface;
+ med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
+
+ hr = IDataObject_GetDataHere( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
+ ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk
changed\n" );
+
+ ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
+ ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
+
+ fmt.cfFormat = 2;
+ fmt.tymed = med.tymed = TYMED_ISTREAM;
+ U(med).pstm = &Test_Stream.IStream_iface;
+ med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
+
+ hr = IDataObject_GetDataHere( data, &fmt, &med );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
+ ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk
changed\n" );
+
+ ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
+ ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
+ ok( Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs );
+
+ IDataObject_Release( data );
+ end_host_object( tid, thread );
+}
+
START_TEST(usrmarshal)
{
- CoInitialize(NULL);
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
test_marshal_CLIPFORMAT();
test_marshal_HWND();
@@ -1001,5 +1360,7 @@
test_marshal_HICON();
test_marshal_HBRUSH();
+ test_GetDataHere_Proxy();
+
CoUninitialize();
}