1 /* 2 * Default Handler Tests 3 * 4 * Copyright 2008 Huw Davies 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #define COBJMACROS 22 #define CONST_VTABLE 23 24 #include <stdarg.h> 25 #include <stdio.h> 26 27 #include "windef.h" 28 #include "winbase.h" 29 #include "objbase.h" 30 31 #include "wine/test.h" 32 33 #define DEFINE_EXPECT(func) \ 34 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 35 36 #define SET_EXPECT(func) \ 37 expect_ ## func = TRUE 38 39 #define CHECK_EXPECT2(func) \ 40 do { \ 41 ok(expect_ ##func, "unexpected call " #func "\n"); \ 42 called_ ## func = TRUE; \ 43 }while(0) 44 45 #define CHECK_EXPECT(func) \ 46 do { \ 47 CHECK_EXPECT2(func); \ 48 expect_ ## func = FALSE; \ 49 }while(0) 50 51 #define CHECK_CALLED(func) \ 52 do { \ 53 ok(called_ ## func, "expected " #func "\n"); \ 54 expect_ ## func = called_ ## func = FALSE; \ 55 }while(0) 56 57 #define CHECK_NOT_CALLED(func) \ 58 do { \ 59 ok(!called_ ## func, "unexpected " #func "\n"); \ 60 expect_ ## func = called_ ## func = FALSE; \ 61 }while(0) 62 63 DEFINE_EXPECT(CF_QueryInterface_ClassFactory); 64 DEFINE_EXPECT(CF_CreateInstance); 65 DEFINE_EXPECT(CF_QueryInterface_IMarshal); 66 67 static HRESULT create_storage(IStorage **stg) 68 { 69 HRESULT hr; 70 ILockBytes *lock_bytes; 71 72 hr = CreateILockBytesOnHGlobal(NULL, TRUE, &lock_bytes); 73 if(SUCCEEDED(hr)) 74 { 75 hr = StgCreateDocfileOnILockBytes(lock_bytes, 76 STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, stg); 77 ILockBytes_Release(lock_bytes); 78 } 79 return hr; 80 } 81 82 typedef struct 83 { 84 DWORD version; 85 DWORD flags; 86 DWORD link_update_opt; 87 DWORD res; 88 DWORD moniker_size; 89 } ole_stream_header_t; 90 91 static void test_olestream(void) 92 { 93 HRESULT hr; 94 const CLSID non_existent_class = {0xa5f1772f, 0x3772, 0x490f, {0x9e, 0xc6, 0x77, 0x13, 0xe8, 0xb3, 0x4b, 0x5d}}; 95 IOleObject *ole_obj; 96 IPersistStorage *persist; 97 IStorage *stg; 98 IStream *stm; 99 static const WCHAR olestream[] = {1,'O','l','e',0}; 100 ULONG read; 101 ole_stream_header_t header; 102 103 hr = create_storage(&stg); 104 ok(hr == S_OK, "got %08x\n", hr); 105 106 hr = IStorage_OpenStream(stg, olestream, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stm); 107 ok(hr == STG_E_FILENOTFOUND, "got %08x\n", hr); 108 109 hr = OleCreateDefaultHandler(&non_existent_class, 0, &IID_IOleObject, (void**)&ole_obj); 110 ok(hr == S_OK, "got %08x\n", hr); 111 112 hr = IOleObject_QueryInterface(ole_obj, &IID_IPersistStorage, (void**)&persist); 113 ok(hr == S_OK, "got %08x\n", hr); 114 115 hr = IPersistStorage_InitNew(persist, stg); 116 ok(hr == S_OK, "got %08x\n", hr); 117 118 hr = IStorage_OpenStream(stg, olestream, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stm); 119 ok(hr == S_OK, "got %08x\n", hr); 120 hr = IStream_Read(stm, &header, sizeof(header), &read); 121 ok(hr == S_OK, "got %08x\n", hr); 122 ok(read == sizeof(header), "read %d\n", read); 123 ok(header.version == 0x02000001, "got version %08x\n", header.version); 124 ok(header.flags == 0x0, "got flags %08x\n", header.flags); 125 ok(header.link_update_opt == 0x0, "got link update option %08x\n", header.link_update_opt); 126 ok(header.res == 0x0, "got reserved %08x\n", header.res); 127 ok(header.moniker_size == 0x0, "got moniker size %08x\n", header.moniker_size); 128 129 IStream_Release(stm); 130 131 IPersistStorage_Release(persist); 132 IOleObject_Release(ole_obj); 133 134 IStorage_Release(stg); 135 } 136 137 static HRESULT WINAPI test_class_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 138 { 139 if(IsEqualGUID(riid, &IID_IUnknown)) { 140 *ppv = iface; 141 return S_OK; 142 }else if(IsEqualGUID(riid, &IID_IOleObject)) { 143 ok(0, "unexpected query for IOleObject interface\n"); 144 *ppv = NULL; 145 return E_NOINTERFACE; 146 } 147 148 *ppv = NULL; 149 return E_NOINTERFACE; 150 } 151 152 static ULONG WINAPI test_class_AddRef(IUnknown *iface) 153 { 154 return 2; 155 } 156 157 static ULONG WINAPI test_class_Release(IUnknown *iface) 158 { 159 return 1; 160 } 161 162 static const IUnknownVtbl test_class_vtbl = { 163 test_class_QueryInterface, 164 test_class_AddRef, 165 test_class_Release, 166 }; 167 168 static IUnknown test_class = { &test_class_vtbl }; 169 170 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) 171 { 172 if(IsEqualGUID(riid, &IID_IUnknown)) { 173 *ppv = iface; 174 return S_OK; 175 }else if(IsEqualGUID(riid, &IID_IMarshal)) { 176 CHECK_EXPECT(CF_QueryInterface_IMarshal); 177 *ppv = NULL; 178 return E_NOINTERFACE; 179 }else if(IsEqualGUID(riid, &IID_IClassFactory)) { 180 CHECK_EXPECT(CF_QueryInterface_ClassFactory); 181 *ppv = iface; 182 return S_OK; 183 } 184 185 ok(0, "unexpected interface: %s\n", wine_dbgstr_guid(riid)); 186 *ppv = NULL; 187 return E_NOINTERFACE; 188 } 189 190 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 191 { 192 return 2; 193 } 194 195 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 196 { 197 return 1; 198 } 199 200 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, 201 IUnknown *pUnkOuter, REFIID riid, void **ppv) 202 { 203 CHECK_EXPECT(CF_CreateInstance); 204 205 ok(pUnkOuter == NULL, "pUnkOuter != NULL\n"); 206 todo_wine ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", wine_dbgstr_guid(riid)); 207 if(IsEqualGUID(riid, &IID_IOleObject)) { 208 *ppv = NULL; 209 return E_NOINTERFACE; 210 } 211 212 *ppv = &test_class; 213 return S_OK; 214 } 215 216 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 217 { 218 ok(0, "unexpected call\n"); 219 return E_NOTIMPL; 220 } 221 222 static const IClassFactoryVtbl ClassFactoryVtbl = { 223 ClassFactory_QueryInterface, 224 ClassFactory_AddRef, 225 ClassFactory_Release, 226 ClassFactory_CreateInstance, 227 ClassFactory_LockServer 228 }; 229 230 static IClassFactory ClassFactory = { &ClassFactoryVtbl }; 231 232 static void test_default_handler_run(void) 233 { 234 const CLSID test_server_clsid = {0x0f77e570,0x80c3,0x11e2,{0x9e,0x96,0x08,0x00,0x20,0x0c,0x9a,0x66}}; 235 236 IUnknown *unk; 237 IRunnableObject *ro; 238 IOleObject *oleobj; 239 IPersistStorage *persist; 240 DWORD class_reg; 241 HRESULT hres; 242 243 if(!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) { 244 win_skip("skipping OleCreateDefaultHandler tests\n"); 245 return; 246 } 247 248 hres = CoRegisterClassObject(&test_server_clsid, (IUnknown*)&ClassFactory, 249 CLSCTX_INPROC_SERVER, 0, &class_reg); 250 ok(hres == S_OK, "CoRegisterClassObject failed: %x\n", hres); 251 252 hres = OleCreateDefaultHandler(&test_server_clsid, NULL, &IID_IUnknown, (void**)&unk); 253 ok(hres == S_OK, "OleCreateDefaultHandler failed: %x\n", hres); 254 255 hres = IUnknown_QueryInterface(unk, &IID_IRunnableObject, (void**)&ro); 256 ok(hres == S_OK, "QueryInterface(IRunnableObject) failed: %x\n", hres); 257 IUnknown_Release(unk); 258 259 hres = IRunnableObject_Run(ro, NULL); 260 ok(hres == REGDB_E_CLASSNOTREG, "Run returned: %x, expected REGDB_E_CLASSNOTREG\n", hres); 261 IRunnableObject_Release(ro); 262 263 SET_EXPECT(CF_QueryInterface_IMarshal); 264 CoRevokeClassObject(class_reg); 265 todo_wine CHECK_CALLED(CF_QueryInterface_IMarshal); 266 267 hres = CoRegisterClassObject(&test_server_clsid, (IUnknown*)&ClassFactory, 268 CLSCTX_LOCAL_SERVER, 0, &class_reg); 269 ok(hres == S_OK, "CoRegisterClassObject failed: %x\n", hres); 270 271 hres = OleCreateDefaultHandler(&test_server_clsid, NULL, &IID_IUnknown, (void**)&unk); 272 ok(hres == S_OK, "OleCreateDefaultHandler failed: %x\n", hres); 273 274 hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj); 275 ok(hres == S_OK, "QueryInterface(IID_IOleObject) failed: %x\n", hres); 276 277 hres = IOleObject_QueryInterface(oleobj, &IID_IPersistStorage, (void**)&persist); 278 ok(hres == S_OK, "QueryInterface(IID_IPersistStorage) failed: %x\n", hres); 279 IPersistStorage_Release(persist); 280 IOleObject_Release(oleobj); 281 282 hres = IUnknown_QueryInterface(unk, &IID_IRunnableObject, (void**)&ro); 283 ok(hres == S_OK, "QueryInterface(IRunnableObject) failed: %x\n", hres); 284 IUnknown_Release(unk); 285 286 SET_EXPECT(CF_QueryInterface_ClassFactory); 287 SET_EXPECT(CF_CreateInstance); 288 hres = IRunnableObject_Run(ro, NULL); 289 todo_wine 290 ok(hres == S_OK, "Run failed: %x\n", hres); 291 CHECK_CALLED(CF_QueryInterface_ClassFactory); 292 CHECK_CALLED(CF_CreateInstance); 293 IRunnableObject_Release(ro); 294 295 SET_EXPECT(CF_QueryInterface_ClassFactory); 296 SET_EXPECT(CF_CreateInstance); 297 hres = CoCreateInstance(&test_server_clsid, NULL, CLSCTX_LOCAL_SERVER, 298 &IID_IOleObject, (void**)&oleobj); 299 todo_wine 300 ok(hres == REGDB_E_CLASSNOTREG, "expected REGDB_E_CLASSNOTREG, got %x\n", hres); 301 todo_wine 302 CHECK_NOT_CALLED(CF_QueryInterface_ClassFactory); 303 todo_wine 304 CHECK_NOT_CALLED(CF_CreateInstance); 305 306 SET_EXPECT(CF_QueryInterface_IMarshal); 307 CoRevokeClassObject(class_reg); 308 todo_wine CHECK_CALLED(CF_QueryInterface_IMarshal); 309 } 310 311 START_TEST(defaulthandler) 312 { 313 OleInitialize(NULL); 314 315 test_olestream(); 316 test_default_handler_run(); 317 318 OleUninitialize(); 319 } 320