2 * OLE DB Marshaling Tests
4 * Copyright 2009 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wine/test.h"
36 #define RELEASEMARSHALDATA WM_USER
38 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
40 struct host_object_data
45 MSHLFLAGS marshal_flags;
47 IMessageFilter *filter;
50 static DWORD CALLBACK host_object_proc(LPVOID p)
52 struct host_object_data *data = p;
56 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
60 IMessageFilter * prev_filter = NULL;
61 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
62 if (prev_filter) IMessageFilter_Release(prev_filter);
63 ok_ole_success(hr, CoRegisterMessageFilter);
66 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
67 ok_ole_success(hr, CoMarshalInterface);
69 /* force the message queue to be created before signaling parent thread */
70 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
72 SetEvent(data->marshal_event);
74 while (GetMessage(&msg, NULL, 0, 0))
76 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
78 CoReleaseMarshalData(data->stream);
79 SetEvent((HANDLE)msg.lParam);
82 DispatchMessage(&msg);
85 HeapFree(GetProcessHeap(), 0, data);
92 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
95 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
96 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
98 data->stream = stream;
100 data->object = object;
101 data->marshal_flags = marshal_flags;
102 data->marshal_event = marshal_event;
103 data->filter = filter;
105 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
107 /* wait for marshaling to complete before returning */
108 ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
109 CloseHandle(marshal_event);
114 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
116 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
119 static void end_host_object(DWORD tid, HANDLE thread)
121 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
122 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
123 /* be careful of races - don't return until hosting thread has terminated */
124 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
128 #define TEST_PROPID 0xdead
129 static const WCHAR wszDBPropertyTestString[] = {'D','B','P','r','o','p','e','r','t','y','T','e','s','t','S','t','r','i','n','g',0};
130 static const WCHAR wszDBPropertyColumnName[] = {'C','o','l','u','m','n',0};
132 static HRESULT WINAPI Test_DBProperties_QueryInterface(
133 IDBProperties* iface,
137 if (IsEqualIID(riid, &IID_IUnknown) ||
138 IsEqualIID(riid, &IID_IDBProperties))
144 return E_NOINTERFACE;
147 static ULONG WINAPI Test_DBProperties_AddRef(
148 IDBProperties* iface)
153 static ULONG WINAPI Test_DBProperties_Release(
154 IDBProperties* iface)
159 /*** IDBProperties methods ***/
160 static HRESULT WINAPI Test_DBProperties_GetProperties(
161 IDBProperties* iface,
162 ULONG cPropertyIDSets,
163 const DBPROPIDSET rgPropertyIDSets[],
164 ULONG *pcPropertySets,
165 DBPROPSET **prgPropertySets)
167 ok(cPropertyIDSets == 0, "Expected cPropertyIDSets to be 0 instead of %d\n", cPropertyIDSets);
168 ok(*pcPropertySets == 0, "Expected *pcPropertySets to be 0 instead of %d\n", *pcPropertySets);
170 *prgPropertySets = CoTaskMemAlloc(sizeof(DBPROPSET));
171 (*prgPropertySets)[0].rgProperties = CoTaskMemAlloc(sizeof(DBPROP));
172 (*prgPropertySets)[0].rgProperties[0].dwPropertyID = TEST_PROPID;
173 (*prgPropertySets)[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
174 (*prgPropertySets)[0].rgProperties[0].dwStatus = S_OK;
175 (*prgPropertySets)[0].rgProperties[0].colid.eKind = DBKIND_GUID_NAME;
177 (*prgPropertySets)[0].rgProperties[0].colid.uGuid.guid = IID_IDBProperties;
178 (*prgPropertySets)[0].rgProperties[0].colid.uName.pwszName = CoTaskMemAlloc(sizeof(wszDBPropertyColumnName));
179 memcpy((*prgPropertySets)[0].rgProperties[0].colid.uName.pwszName, wszDBPropertyColumnName, sizeof(wszDBPropertyColumnName));
180 /* vValue contents */
181 V_VT(&(*prgPropertySets)[0].rgProperties[0].vValue) = VT_BSTR;
182 V_BSTR(&(*prgPropertySets)[0].rgProperties[0].vValue) = SysAllocString(wszDBPropertyTestString);
183 (*prgPropertySets)[0].cProperties = 1;
184 (*prgPropertySets)[0].guidPropertySet = IID_IDBProperties;
189 static HRESULT WINAPI Test_DBProperties_GetPropertyInfo(
190 IDBProperties* iface,
191 ULONG cPropertyIDSets,
192 const DBPROPIDSET rgPropertyIDSets[],
193 ULONG *pcPropertyInfoSets,
194 DBPROPINFOSET **prgPropertyInfoSets,
195 OLECHAR **ppDescBuffer)
200 static HRESULT WINAPI Test_DBProperties_SetProperties(
201 IDBProperties* iface,
203 DBPROPSET rgPropertySets[])
208 static const IDBPropertiesVtbl Test_DBProperties_Vtbl =
210 Test_DBProperties_QueryInterface,
211 Test_DBProperties_AddRef,
212 Test_DBProperties_Release,
213 Test_DBProperties_GetProperties,
214 Test_DBProperties_GetPropertyInfo,
215 Test_DBProperties_SetProperties,
218 static IDBProperties Test_DBProperties =
220 &Test_DBProperties_Vtbl
223 static void test_IDBProperties(void)
226 IStream *pStream = NULL;
227 IDBProperties *pProxy = NULL;
230 static const LARGE_INTEGER ullZero;
232 DBPROPSET *propsets = NULL;
234 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
235 ok_ole_success(hr, "CreateStreamOnHGlobal");
236 tid = start_host_object(pStream, &IID_IDBProperties, (IUnknown*)&Test_DBProperties, MSHLFLAGS_NORMAL, &thread);
238 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
239 hr = CoUnmarshalInterface(pStream, &IID_IDBProperties, (void **)&pProxy);
240 ok_ole_success(hr, "CoUnmarshalInterface");
241 IStream_Release(pStream);
244 hr = IDBProperties_GetProperties(pProxy, 0, NULL, &propset_count, &propsets);
245 ok(hr == S_OK, "IDBProperties_GetProperties failed with error 0x%08x\n", hr);
247 ok(propset_count == 1, "Expected propset_count of 1 but got %d\n", propset_count);
248 ok(propsets->rgProperties[0].dwPropertyID == TEST_PROPID, "Expected property ID of 0x%x, but got 0x%x\n", TEST_PROPID, propsets->rgProperties[0].dwPropertyID);
249 ok(propsets->rgProperties[0].dwOptions == DBPROPOPTIONS_REQUIRED, "Expected property options of 0x%x, but got 0x%x\n", DBPROPOPTIONS_REQUIRED, propsets->rgProperties[0].dwOptions);
250 ok(propsets->rgProperties[0].dwStatus == S_OK, "Expected property options of 0x%x, but got 0x%x\n", S_OK, propsets->rgProperties[0].dwStatus);
251 ok(propsets->rgProperties[0].colid.eKind == DBKIND_GUID_NAME, "Expected property colid kind of DBKIND_GUID_NAME, but got %d\n", propsets->rgProperties[0].colid.eKind);
253 ok(IsEqualGUID(&propsets->rgProperties[0].colid.uGuid.guid, &IID_IDBProperties), "Unexpected property colid guid\n");
254 ok(!lstrcmpW(propsets->rgProperties[0].colid.uName.pwszName, wszDBPropertyColumnName), "Unexpected property colid name\n");
255 /* vValue contents */
256 ok(V_VT(&propsets->rgProperties[0].vValue) == VT_BSTR, "Expected property value vt of VT_BSTR, but got %d\n", V_VT(&propsets->rgProperties[0].vValue));
257 ok(!lstrcmpW(V_BSTR(&propsets->rgProperties[0].vValue), wszDBPropertyTestString), "Unexpected property value string\n");
258 ok(propsets->cProperties == 1, "Expected property count of 1 but got %d\n", propsets->cProperties);
259 ok(IsEqualGUID(&propsets->guidPropertySet, &IID_IDBProperties), "Unexpected guid for property set\n");
261 IDBProperties_Release(pProxy);
263 end_host_object(tid, thread);
268 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
270 test_IDBProperties();