+static void test_marshal_channel_buffer(void)
+{
+ DWORD registration_key;
+ IUnknown *proxy = NULL;
+ IOleWindow *ole_window;
+ HWND hwnd;
+ CLSID clsid;
+ DWORD tid;
+ HANDLE thread;
+ HRESULT hr;
+
+ struct host_object_data object_data = { NULL, &IID_IOleClientSite, (IUnknown*)&Test_OleClientSite,
+ MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer,
+ &CLSID_WineTestPSFactoryBuffer };
+
+ cLocks = 0;
+ external_connections = 0;
+
+ hr = CoGetPSClsid(&IID_IOleWindow, &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 = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+ tid = start_host_object2(&object_data, &thread);
+
+ IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
+ hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy);
+ ok_ole_success(hr, CoUnmarshalInterface);
+ IStream_Release(object_data.stream);
+
+ hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®istration_key);
+ ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
+
+ hr = CoRegisterPSClsid(&IID_IOleWindow, &CLSID_WineTestPSFactoryBuffer);
+ ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr);
+
+ SET_EXPECT(CreateStub);
+ SET_EXPECT(CreateProxy);
+ hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window);
+ ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr);
+ CHECK_CALLED(CreateStub);
+ CHECK_CALLED(CreateProxy);
+
+ SET_EXPECT(Invoke);
+ SET_EXPECT(GetWindow);
+ hr = IOleWindow_GetWindow(ole_window, &hwnd);
+ ok(hr == S_OK, "GetWindow failed: %08x\n", hr);
+ ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd);
+ CHECK_CALLED(Invoke);
+ CHECK_CALLED(GetWindow);
+
+ IOleWindow_Release(ole_window);
+
+ SET_EXPECT(Disconnect);
+ IUnknown_Release(proxy);
+todo_wine
+ CHECK_CALLED(Disconnect);
+
+ hr = CoRevokeClassObject(registration_key);
+ ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr);
+
+ end_host_object(tid, thread);
+}
+
+static const CLSID *unmarshal_class;
+DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass);
+DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax);
+DEFINE_EXPECT(CustomMarshal_MarshalInterface);
+
+static HRESULT WINAPI CustomMarshal_QueryInterface(IMarshal *iface, REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) {
+ *ppv = iface;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI CustomMarshal_AddRef(IMarshal *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI CustomMarshal_Release(IMarshal *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI CustomMarshal_GetUnmarshalClass(IMarshal *iface, REFIID riid,
+ void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
+{
+ CHECK_EXPECT(CustomMarshal_GetUnmarshalClass);
+ *clsid = *unmarshal_class;
+ return S_OK;
+}
+
+static HRESULT WINAPI CustomMarshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid,
+ void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
+{
+ CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax);
+ ok(size != NULL, "size = NULL\n");
+
+ *size = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI CustomMarshal_MarshalInterface(IMarshal *iface, IStream *stream,
+ REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
+{
+ IMarshal *std_marshal;
+ STATSTG stat;
+ HRESULT hr;
+
+ CHECK_EXPECT(CustomMarshal_MarshalInterface);
+
+ if(unmarshal_class != &CLSID_StdMarshal)
+ return S_OK;
+
+ hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT);
+ ok_ole_success(hr, IStream_Stat);
+ ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart);
+ ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart);
+
+ hr = CoGetStandardMarshal(riid, (IUnknown*)iface,
+ dwDestContext, NULL, mshlflags, &std_marshal);
+ ok_ole_success(hr, CoGetStandardMarshal);
+ hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv,
+ dwDestContext, pvDestContext, mshlflags);
+ ok_ole_success(hr, IMarshal_MarshalInterface);
+ IMarshal_Release(std_marshal);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CustomMarshal_UnmarshalInterface(IMarshal *iface,
+ IStream *stream, REFIID riid, void **ppv)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CustomMarshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CustomMarshal_DisconnectObject(IMarshal *iface, DWORD res)
+{
+ ok(0, "unexpected call\n");
+ return E_NOTIMPL;
+}
+
+static IMarshalVtbl CustomMarshalVtbl =
+{
+ CustomMarshal_QueryInterface,
+ CustomMarshal_AddRef,
+ CustomMarshal_Release,
+ CustomMarshal_GetUnmarshalClass,
+ CustomMarshal_GetMarshalSizeMax,
+ CustomMarshal_MarshalInterface,
+ CustomMarshal_UnmarshalInterface,
+ CustomMarshal_ReleaseMarshalData,
+ CustomMarshal_DisconnectObject
+};
+
+static IMarshal CustomMarshal = { &CustomMarshalVtbl };
+
+static void test_StdMarshal_custom_marshaling(void)
+{
+ IStream *stream;
+ IUnknown *unk;
+ DWORD size;
+ HRESULT hr;
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ unmarshal_class = &CLSID_StdMarshal;
+ SET_EXPECT(CustomMarshal_GetUnmarshalClass);
+ SET_EXPECT(CustomMarshal_MarshalInterface);
+ hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+ CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
+ CHECK_CALLED(CustomMarshal_MarshalInterface);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
+ ok_ole_success(hr, CoUnmarshalInterface);
+ ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n");
+ IUnknown_Release(unk);
+ IStream_Release(stream);
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ SET_EXPECT(CustomMarshal_GetUnmarshalClass);
+ SET_EXPECT(CustomMarshal_MarshalInterface);
+ hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+ CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
+ CHECK_CALLED(CustomMarshal_MarshalInterface);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ hr = CoReleaseMarshalData(stream);
+ ok_ole_success(hr, CoReleaseMarshalData);
+ IStream_Release(stream);
+
+ SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
+ hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoGetMarshalSizeMax);
+ CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
+ ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
+}
+
+static void test_DfMarshal_custom_marshaling(void)
+{
+ DWORD size, read;
+ IStream *stream;
+ OBJREF objref;
+ HRESULT hr;
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ unmarshal_class = &CLSID_DfMarshal;
+ SET_EXPECT(CustomMarshal_GetUnmarshalClass);
+ SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
+ SET_EXPECT(CustomMarshal_MarshalInterface);
+ hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoMarshalInterface);
+ CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
+ CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
+ CHECK_CALLED(CustomMarshal_MarshalInterface);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData);
+ hr = IStream_Read(stream, &objref, size, &read);
+ ok_ole_success(hr, IStream_Read);
+ ok(read == size, "read = %d, expected %d\n", read, size);
+ ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
+ objref.signature);
+ ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags);
+ ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
+ wine_dbgstr_guid(&objref.iid));
+ ok(IsEqualIID(&objref.u_objref.u_custom.clsid, &CLSID_DfMarshal),
+ "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid));
+ ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n",
+ objref.u_objref.u_custom.cbExtension);
+ ok(!objref.u_objref.u_custom.size, "custom.size = %d\n",
+ objref.u_objref.u_custom.size);
+
+ IStream_Release(stream);
+
+ SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
+ hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoGetMarshalSizeMax);
+ CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
+ ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
+}
+
+static void test_CoGetStandardMarshal(void)
+{
+ DUALSTRINGARRAY *dualstringarr;
+ STDOBJREF *stdobjref;
+ OBJREF objref;
+ IMarshal *marshal;
+ DWORD size, read;
+ IStream *stream;
+ IUnknown *unk;
+ CLSID clsid;
+ HRESULT hr;
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok_ole_success(hr, CreateStreamOnHGlobal);
+
+ hr = CoGetStandardMarshal(&IID_IUnknown, &Test_Unknown,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal);
+ ok_ole_success(hr, CoGetStandardMarshal);
+
+ hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
+ ok_ole_success(hr, IMarshal_GetUnmarshalClass);
+ ok(IsEqualGUID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", wine_dbgstr_guid(&clsid));
+
+ hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size);
+ ok_ole_success(hr, IMarshal_GetMarshalSizeMax);
+ hr = CoGetMarshalSizeMax(&read, &IID_IUnknown, &Test_Unknown,
+ MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, CoGetMarshalSizeMax);
+ ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read);
+
+ hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
+ &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, IMarshal_MarshalInterface);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
+ hr = IStream_Read(stream, &objref, size, &read);
+ ok_ole_success(hr, IStream_Read);
+ ok(read == size, "read = %d, expected %d\n", read, size);
+ ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
+ objref.signature);
+ ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags);
+ ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
+ wine_dbgstr_guid(&objref.iid));
+ stdobjref = &objref.u_objref.u_standard.std;
+ ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags);
+ ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n",
+ stdobjref->cPublicRefs);
+ dualstringarr = &objref.u_objref.u_standard.saResAddr;
+ ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n",
+ dualstringarr->wNumEntries);
+ ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n",
+ dualstringarr->wSecurityOffset);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk);
+ ok_ole_success(hr, IMarshal_UnmarshalInterface);
+ IUnknown_Release(unk);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
+ &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok_ole_success(hr, IMarshal_MarshalInterface);
+
+ hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+ ok_ole_success(hr, IStream_Seek);
+ hr = IMarshal_ReleaseMarshalData(marshal, stream);
+ ok_ole_success(hr, IMarshal_ReleaseMarshalData);
+ IStream_Release(stream);
+
+ IMarshal_Release(marshal);
+}