1 /* 2 * Copyright 2012 Stefan Leichter 3 * Copyright 2012 Jacek Caban for CodeWeavers 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #define COBJMACROS 21 22 #include "wine/atlbase.h" 23 #include "wine/atlcom.h" 24 25 #include "wine/debug.h" 26 #include "wine/heap.h" 27 #include "wine/unicode.h" 28 29 #ifdef __REACTOS__ 30 #include <wingdi.h> 31 #endif 32 33 WINE_DEFAULT_DEBUG_CHANNEL(atl); 34 35 #define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer) 36 37 HINSTANCE atl_instance; 38 39 typedef unsigned char cpp_bool; 40 41 static ICatRegister *catreg; 42 43 /*********************************************************************** 44 * AtlAdvise [atl100.@] 45 */ 46 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw) 47 { 48 IConnectionPointContainer *container; 49 IConnectionPoint *cp; 50 HRESULT hres; 51 52 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw); 53 54 if(!pUnkCP) 55 return E_INVALIDARG; 56 57 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container); 58 if(FAILED(hres)) 59 return hres; 60 61 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp); 62 IConnectionPointContainer_Release(container); 63 if(FAILED(hres)) 64 return hres; 65 66 hres = IConnectionPoint_Advise(cp, pUnk, pdw); 67 IConnectionPoint_Release(cp); 68 return hres; 69 } 70 71 /*********************************************************************** 72 * AtlUnadvise [atl100.@] 73 */ 74 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw) 75 { 76 IConnectionPointContainer *container; 77 IConnectionPoint *cp; 78 HRESULT hres; 79 80 TRACE("%p %p %d\n", pUnkCP, iid, dw); 81 82 if(!pUnkCP) 83 return E_INVALIDARG; 84 85 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container); 86 if(FAILED(hres)) 87 return hres; 88 89 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp); 90 IConnectionPointContainer_Release(container); 91 if(FAILED(hres)) 92 return hres; 93 94 hres = IConnectionPoint_Unadvise(cp, dw); 95 IConnectionPoint_Release(cp); 96 return hres; 97 } 98 99 /*********************************************************************** 100 * AtlFreeMarshalStream [atl100.@] 101 */ 102 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm) 103 { 104 FIXME("%p\n", stm); 105 return S_OK; 106 } 107 108 /*********************************************************************** 109 * AtlMarshalPtrInProc [atl100.@] 110 */ 111 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm) 112 { 113 FIXME("%p %p %p\n", pUnk, iid, pstm); 114 return E_FAIL; 115 } 116 117 /*********************************************************************** 118 * AtlUnmarshalPtr [atl100.@] 119 */ 120 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk) 121 { 122 FIXME("%p %p %p\n", stm, iid, ppUnk); 123 return E_FAIL; 124 } 125 126 /*********************************************************************** 127 * AtlCreateTargetDC [atl100.@] 128 */ 129 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv ) 130 { 131 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0}; 132 const WCHAR *driver = NULL, *device = NULL, *port = NULL; 133 DEVMODEW *devmode = NULL; 134 135 TRACE( "(%p, %p)\n", hdc, dv ); 136 137 if (dv) 138 { 139 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset); 140 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset); 141 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset); 142 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset); 143 } 144 else 145 { 146 if (hdc) return hdc; 147 driver = displayW; 148 } 149 return CreateDCW( driver, device, port, devmode ); 150 } 151 152 /*********************************************************************** 153 * AtlHiMetricToPixel [atl100.@] 154 */ 155 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix) 156 { 157 HDC dc = GetDC(NULL); 158 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100; 159 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100; 160 ReleaseDC( NULL, dc ); 161 } 162 163 /*********************************************************************** 164 * AtlPixelToHiMetric [atl100.@] 165 */ 166 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric) 167 { 168 HDC dc = GetDC(NULL); 169 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX ); 170 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY ); 171 ReleaseDC( NULL, dc ); 172 } 173 174 /*********************************************************************** 175 * AtlComPtrAssign [atl100.@] 176 */ 177 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p) 178 { 179 TRACE("(%p %p)\n", pp, p); 180 181 if (p) IUnknown_AddRef(p); 182 if (*pp) IUnknown_Release(*pp); 183 *pp = p; 184 return p; 185 } 186 187 /*********************************************************************** 188 * AtlComQIPtrAssign [atl100.@] 189 */ 190 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid) 191 { 192 IUnknown *new_p = NULL; 193 194 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid)); 195 196 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p); 197 if (*pp) IUnknown_Release(*pp); 198 *pp = new_p; 199 return new_p; 200 } 201 202 /*********************************************************************** 203 * AtlInternalQueryInterface [atl100.@] 204 */ 205 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) 206 { 207 int i = 0; 208 HRESULT rc = E_NOINTERFACE; 209 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject); 210 211 if (IsEqualGUID(iid,&IID_IUnknown)) 212 { 213 TRACE("Returning IUnknown\n"); 214 *ppvObject = ((LPSTR)this+pEntries[0].dw); 215 IUnknown_AddRef((IUnknown*)*ppvObject); 216 return S_OK; 217 } 218 219 while (pEntries[i].pFunc != 0) 220 { 221 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid), 222 pEntries[i].dw, pEntries[i].pFunc); 223 224 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid)) 225 { 226 TRACE("MATCH\n"); 227 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1) 228 { 229 TRACE("Offset\n"); 230 *ppvObject = ((LPSTR)this+pEntries[i].dw); 231 IUnknown_AddRef((IUnknown*)*ppvObject); 232 return S_OK; 233 } 234 else 235 { 236 TRACE("Function\n"); 237 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw); 238 if(rc==S_OK || pEntries[i].piid) 239 return rc; 240 } 241 } 242 i++; 243 } 244 TRACE("Done returning (0x%x)\n",rc); 245 return rc; 246 } 247 248 /*********************************************************************** 249 * AtlIPersistStreamInit_Load [atl100.@] 250 */ 251 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap, 252 void *pThis, IUnknown *pUnk) 253 { 254 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk); 255 256 return S_OK; 257 } 258 259 /*********************************************************************** 260 * AtlIPersistStreamInit_Save [atl100.@] 261 */ 262 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty, 263 ATL_PROPMAP_ENTRY *pMap, void *pThis, 264 IUnknown *pUnk) 265 { 266 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk); 267 268 return S_OK; 269 } 270 271 /*********************************************************************** 272 * AtlIPersistPropertyBag_Load [atl100.@] 273 */ 274 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog, 275 ATL_PROPMAP_ENTRY *pMap, void *pThis, 276 IUnknown *pUnk) 277 { 278 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk); 279 280 return S_OK; 281 } 282 283 /*********************************************************************** 284 * AtlIPersistPropertyBag_Save [atl100.@] 285 */ 286 HRESULT WINAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty, 287 BOOL fSaveAll, ATL_PROPMAP_ENTRY *pMap, 288 void *pThis, IUnknown *pUnk) 289 { 290 FIXME("(%p, %d, %d, %p, %p, %p)\n", pPropBag, fClearDirty, fSaveAll, pMap, pThis, pUnk); 291 292 return S_OK; 293 } 294 295 /*********************************************************************** 296 * AtlModuleAddTermFunc [atl100.@] 297 */ 298 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw) 299 { 300 _ATL_TERMFUNC_ELEM *termfunc_elem; 301 302 TRACE("version %04x (%p %p %ld)\n", _ATL_VER, pM, pFunc, dw); 303 304 if (_ATL_VER > _ATL_VER_30 || pM->cbSize > ATLVer1Size) { 305 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM)); 306 termfunc_elem->pFunc = pFunc; 307 termfunc_elem->dw = dw; 308 termfunc_elem->pNext = pM->m_pTermFuncs; 309 310 pM->m_pTermFuncs = termfunc_elem; 311 } 312 313 return S_OK; 314 } 315 316 #if _ATL_VER > _ATL_VER_30 317 318 /*********************************************************************** 319 * AtlCallTermFunc [atl100.@] 320 */ 321 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM) 322 { 323 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp; 324 325 TRACE("(%p)\n", pM); 326 327 while(iter) { 328 iter->pFunc(iter->dw); 329 tmp = iter; 330 iter = iter->pNext; 331 HeapFree(GetProcessHeap(), 0, tmp); 332 } 333 334 pM->m_pTermFuncs = NULL; 335 } 336 337 #endif 338 339 /*********************************************************************** 340 * AtlLoadTypeLib [atl100.56] 341 */ 342 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex, 343 BSTR *pbstrPath, ITypeLib **ppTypeLib) 344 { 345 size_t path_len, index_len; 346 ITypeLib *typelib = NULL; 347 WCHAR *path; 348 HRESULT hres; 349 350 static const WCHAR tlb_extW[] = {'.','t','l','b',0}; 351 352 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib); 353 354 index_len = lpszIndex ? strlenW(lpszIndex) : 0; 355 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW)); 356 if(!path) 357 return E_OUTOFMEMORY; 358 359 path_len = GetModuleFileNameW(inst, path, MAX_PATH); 360 if(!path_len) { 361 heap_free(path); 362 return HRESULT_FROM_WIN32(GetLastError()); 363 } 364 365 if(index_len) 366 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR)); 367 368 hres = LoadTypeLib(path, &typelib); 369 if(FAILED(hres)) { 370 WCHAR *ptr; 371 372 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--); 373 if(*ptr != '.') 374 ptr = path+path_len; 375 memcpy(ptr, tlb_extW, sizeof(tlb_extW)); 376 hres = LoadTypeLib(path, &typelib); 377 } 378 379 if(SUCCEEDED(hres)) { 380 *pbstrPath = SysAllocString(path); 381 if(!*pbstrPath) { 382 ITypeLib_Release(typelib); 383 hres = E_OUTOFMEMORY; 384 } 385 } 386 387 heap_free(path); 388 if(FAILED(hres)) 389 return hres; 390 391 *ppTypeLib = typelib; 392 return S_OK; 393 } 394 395 #if _ATL_VER <= _ATL_VER_80 396 397 /*********************************************************************** 398 * AtlRegisterTypeLib [atl80.19] 399 */ 400 HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index) 401 { 402 ITypeLib *typelib; 403 BSTR path; 404 HRESULT hres; 405 406 TRACE("(%p %s)\n", inst, debugstr_w(index)); 407 408 hres = AtlLoadTypeLib(inst, index, &path, &typelib); 409 if(FAILED(hres)) 410 return hres; 411 412 hres = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */ 413 ITypeLib_Release(typelib); 414 SysFreeString(path); 415 return hres; 416 } 417 418 #endif 419 420 #if _ATL_VER > _ATL_VER_30 421 422 /*********************************************************************** 423 * AtlWinModuleInit [atl100.65] 424 */ 425 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod) 426 { 427 TRACE("(%p)\n", winmod); 428 429 if(winmod->cbSize != sizeof(*winmod)) 430 return E_INVALIDARG; 431 432 InitializeCriticalSection(&winmod->m_csWindowCreate); 433 winmod->m_pCreateWndList = NULL; 434 return S_OK; 435 } 436 437 /*********************************************************************** 438 * AtlWinModuleAddCreateWndData [atl100.43] 439 */ 440 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject) 441 { 442 TRACE("(%p, %p, %p)\n", pM, pData, pvObject); 443 444 pData->m_pThis = pvObject; 445 pData->m_dwThreadID = GetCurrentThreadId(); 446 447 EnterCriticalSection(&pM->m_csWindowCreate); 448 pData->m_pNext = pM->m_pCreateWndList; 449 pM->m_pCreateWndList = pData; 450 LeaveCriticalSection(&pM->m_csWindowCreate); 451 } 452 453 /*********************************************************************** 454 * AtlWinModuleExtractCreateWndData [atl100.44] 455 */ 456 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod) 457 { 458 _AtlCreateWndData *iter, *prev = NULL; 459 DWORD thread_id; 460 461 TRACE("(%p)\n", winmod); 462 463 thread_id = GetCurrentThreadId(); 464 465 EnterCriticalSection(&winmod->m_csWindowCreate); 466 467 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext) 468 prev = iter; 469 if(iter) { 470 if(prev) 471 prev->m_pNext = iter->m_pNext; 472 else 473 winmod->m_pCreateWndList = iter->m_pNext; 474 } 475 476 LeaveCriticalSection(&winmod->m_csWindowCreate); 477 478 return iter ? iter->m_pThis : NULL; 479 } 480 481 /*********************************************************************** 482 * AtlComModuleGetClassObject [atl100.15] 483 */ 484 #if _ATL_VER < _ATL_VER_110 485 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv) 486 { 487 _ATL_OBJMAP_ENTRY **iter; 488 HRESULT hres; 489 490 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv); 491 492 if(!pm) 493 return E_INVALIDARG; 494 495 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) { 496 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) { 497 if(!(*iter)->pCF) 498 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF); 499 if((*iter)->pCF) 500 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv); 501 TRACE("returning %p (%08x)\n", *ppv, hres); 502 return hres; 503 } 504 } 505 506 WARN("Class %s not found\n", debugstr_guid(rclsid)); 507 return CLASS_E_CLASSNOTAVAILABLE; 508 } 509 #else 510 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv) 511 { 512 _ATL_OBJMAP_ENTRY_EX **iter; 513 HRESULT hres; 514 515 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv); 516 517 if(!pm) 518 return E_INVALIDARG; 519 520 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) { 521 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) { 522 if(!(*iter)->pCache->pCF) 523 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCache->pCF); 524 if((*iter)->pCache->pCF) 525 hres = IUnknown_QueryInterface((*iter)->pCache->pCF, riid, ppv); 526 TRACE("returning %p (%08x)\n", *ppv, hres); 527 return hres; 528 } 529 } 530 531 WARN("Class %s not found\n", debugstr_guid(rclsid)); 532 return CLASS_E_CLASSNOTAVAILABLE; 533 } 534 #endif 535 536 /*********************************************************************** 537 * AtlComModuleRegisterClassObjects [atl100.17] 538 */ 539 #if _ATL_VER < _ATL_VER_110 540 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags) 541 { 542 _ATL_OBJMAP_ENTRY **iter; 543 IUnknown *unk; 544 HRESULT hres; 545 546 TRACE("(%p %x %x)\n", module, context, flags); 547 548 if(!module) 549 return E_INVALIDARG; 550 551 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) { 552 if(!(*iter)->pfnGetClassObject) 553 continue; 554 555 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk); 556 if(FAILED(hres)) 557 return hres; 558 559 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister); 560 IUnknown_Release(unk); 561 if(FAILED(hres)) 562 return hres; 563 } 564 565 return S_OK; 566 } 567 #else 568 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags) 569 { 570 _ATL_OBJMAP_ENTRY_EX **iter; 571 IUnknown *unk; 572 HRESULT hres; 573 574 TRACE("(%p %x %x)\n", module, context, flags); 575 576 if(!module) 577 return E_INVALIDARG; 578 579 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) { 580 if(!(*iter)->pfnGetClassObject) 581 continue; 582 583 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk); 584 if(FAILED(hres)) 585 return hres; 586 587 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->pCache->dwRegister); 588 IUnknown_Release(unk); 589 if(FAILED(hres)) 590 return hres; 591 } 592 593 return S_OK; 594 } 595 #endif 596 597 /*********************************************************************** 598 * AtlComModuleRevokeClassObjects [atl100.20] 599 */ 600 #if _ATL_VER < _ATL_VER_110 601 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module) 602 { 603 _ATL_OBJMAP_ENTRY **iter; 604 HRESULT hres; 605 606 TRACE("(%p)\n", module); 607 608 if(!module) 609 return E_INVALIDARG; 610 611 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) { 612 hres = CoRevokeClassObject((*iter)->dwRegister); 613 if(FAILED(hres)) 614 return hres; 615 } 616 617 return S_OK; 618 } 619 #else 620 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module) 621 { 622 _ATL_OBJMAP_ENTRY_EX **iter; 623 HRESULT hres; 624 625 TRACE("(%p)\n", module); 626 627 if(!module) 628 return E_INVALIDARG; 629 630 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) { 631 hres = CoRevokeClassObject((*iter)->pCache->dwRegister); 632 if(FAILED(hres)) 633 return hres; 634 } 635 636 return S_OK; 637 } 638 #endif 639 640 /*********************************************************************** 641 * AtlComModuleUnregisterServer [atl100.22] 642 */ 643 #if _ATL_VER < _ATL_VER_110 644 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid) 645 { 646 const struct _ATL_CATMAP_ENTRY *catmap; 647 _ATL_OBJMAP_ENTRY **iter; 648 HRESULT hres; 649 650 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid)); 651 652 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) { 653 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid))) 654 continue; 655 656 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid)); 657 658 catmap = (*iter)->pfnGetCategoryMap(); 659 if(catmap) { 660 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE); 661 if(FAILED(hres)) 662 return hres; 663 } 664 665 hres = (*iter)->pfnUpdateRegistry(FALSE); 666 if(FAILED(hres)) 667 return hres; 668 } 669 670 if(bRegTypeLib) { 671 ITypeLib *typelib; 672 TLIBATTR *attr; 673 BSTR path; 674 675 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib); 676 if(FAILED(hres)) 677 return hres; 678 679 SysFreeString(path); 680 hres = ITypeLib_GetLibAttr(typelib, &attr); 681 if(SUCCEEDED(hres)) { 682 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind); 683 ITypeLib_ReleaseTLibAttr(typelib, attr); 684 } 685 ITypeLib_Release(typelib); 686 if(FAILED(hres)) 687 return hres; 688 } 689 690 return S_OK; 691 } 692 #else 693 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid) 694 { 695 const struct _ATL_CATMAP_ENTRY *catmap; 696 _ATL_OBJMAP_ENTRY_EX **iter; 697 HRESULT hres; 698 699 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid)); 700 701 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) { 702 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid))) 703 continue; 704 705 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid)); 706 707 catmap = (*iter)->pfnGetCategoryMap(); 708 if(catmap) { 709 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE); 710 if(FAILED(hres)) 711 return hres; 712 } 713 714 hres = (*iter)->pfnUpdateRegistry(FALSE); 715 if(FAILED(hres)) 716 return hres; 717 } 718 719 if(bRegTypeLib) { 720 ITypeLib *typelib; 721 TLIBATTR *attr; 722 BSTR path; 723 724 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib); 725 if(FAILED(hres)) 726 return hres; 727 728 SysFreeString(path); 729 hres = ITypeLib_GetLibAttr(typelib, &attr); 730 if(SUCCEEDED(hres)) { 731 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind); 732 ITypeLib_ReleaseTLibAttr(typelib, attr); 733 } 734 ITypeLib_Release(typelib); 735 if(FAILED(hres)) 736 return hres; 737 } 738 739 return S_OK; 740 } 741 #endif 742 743 #endif 744 745 /*********************************************************************** 746 * AtlRegisterClassCategoriesHelper [atl100.49] 747 */ 748 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg) 749 { 750 const struct _ATL_CATMAP_ENTRY *iter; 751 HRESULT hres; 752 753 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg); 754 755 if(!catmap) 756 return S_OK; 757 758 if(!catreg) { 759 ICatRegister *new_catreg; 760 761 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, 762 &IID_ICatRegister, (void**)&new_catreg); 763 if(FAILED(hres)) 764 return hres; 765 766 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL)) 767 ICatRegister_Release(new_catreg); 768 } 769 770 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) { 771 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */ 772 773 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) { 774 if(reg) 775 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid); 776 else 777 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid); 778 }else { 779 if(reg) 780 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid); 781 else 782 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid); 783 } 784 if(FAILED(hres)) 785 return hres; 786 } 787 788 if(!reg) { 789 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6; 790 791 static const WCHAR implemented_catW[] = 792 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0}; 793 static const WCHAR required_catW[] = 794 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0}; 795 796 ptr += StringFromGUID2(clsid, ptr, 64)-1; 797 *ptr++ = '\\'; 798 799 memcpy(ptr, implemented_catW, sizeof(implemented_catW)); 800 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 801 802 memcpy(ptr, required_catW, sizeof(required_catW)); 803 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); 804 } 805 806 return S_OK; 807 } 808 809 /*********************************************************************** 810 * AtlWaitWithMessageLoop [atl100.24] 811 */ 812 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle) 813 { 814 MSG msg; 815 DWORD res; 816 817 TRACE("(%p)\n", handle); 818 819 while(1) { 820 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT); 821 switch(res) { 822 case WAIT_OBJECT_0: 823 return TRUE; 824 case WAIT_OBJECT_0+1: 825 if(GetMessageW(&msg, NULL, 0, 0) < 0) 826 return FALSE; 827 828 TranslateMessage(&msg); 829 DispatchMessageW(&msg); 830 break; 831 default: 832 return FALSE; 833 } 834 } 835 } 836 837 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid) 838 { 839 ITypeInfo *typeinfo, *src_typeinfo = NULL; 840 TYPEATTR *attr; 841 int type_flags; 842 unsigned i; 843 HRESULT hres; 844 845 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo); 846 if(FAILED(hres)) 847 return hres; 848 849 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr); 850 if(FAILED(hres)) { 851 ITypeInfo_Release(typeinfo); 852 return hres; 853 } 854 855 for(i=0; i < attr->cImplTypes; i++) { 856 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags); 857 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) { 858 HREFTYPE ref; 859 860 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref); 861 if(SUCCEEDED(hres)) 862 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo); 863 break; 864 } 865 } 866 867 ITypeInfo_ReleaseTypeAttr(typeinfo, attr); 868 ITypeInfo_Release(typeinfo); 869 if(FAILED(hres)) 870 return hres; 871 872 if(!src_typeinfo) { 873 *iid = IID_NULL; 874 return S_OK; 875 } 876 877 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr); 878 if(SUCCEEDED(hres)) { 879 *iid = attr->guid; 880 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr); 881 } 882 ITypeInfo_Release(src_typeinfo); 883 return hres; 884 } 885 886 /*********************************************************************** 887 * AtlGetObjectSourceInterface [atl100.54] 888 */ 889 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor) 890 { 891 IProvideClassInfo2 *classinfo; 892 ITypeInfo *typeinfo; 893 ITypeLib *typelib; 894 IPersist *persist; 895 IDispatch *disp; 896 HRESULT hres; 897 898 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor); 899 900 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp); 901 if(FAILED(hres)) 902 return hres; 903 904 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo); 905 IDispatch_Release(disp); 906 if(FAILED(hres)) 907 return hres; 908 909 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0); 910 ITypeInfo_Release(typeinfo); 911 if(SUCCEEDED(hres)) { 912 TLIBATTR *attr; 913 914 hres = ITypeLib_GetLibAttr(typelib, &attr); 915 if(SUCCEEDED(hres)) { 916 *libid = attr->guid; 917 *major = attr->wMajorVerNum; 918 *minor = attr->wMinorVerNum; 919 ITypeLib_ReleaseTLibAttr(typelib, attr); 920 }else { 921 ITypeLib_Release(typelib); 922 } 923 } 924 if(FAILED(hres)) 925 return hres; 926 927 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo); 928 if(SUCCEEDED(hres)) { 929 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid); 930 IProvideClassInfo2_Release(classinfo); 931 ITypeLib_Release(typelib); 932 return hres; 933 } 934 935 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist); 936 if(SUCCEEDED(hres)) { 937 CLSID clsid; 938 939 hres = IPersist_GetClassID(persist, &clsid); 940 if(SUCCEEDED(hres)) 941 hres = get_default_source(typelib, &clsid, iid); 942 IPersist_Release(persist); 943 } 944 945 return hres; 946 } 947 948 #if _ATL_VER >= _ATL_VER90 949 950 /*********************************************************************** 951 * AtlSetPerUserRegistration [atl100.67] 952 */ 953 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable) 954 { 955 FIXME("stub: bEnable: %d\n", bEnable); 956 return E_NOTIMPL; 957 } 958 959 /*********************************************************************** 960 * AtlGetPerUserRegistration [atl100.68] 961 */ 962 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled) 963 { 964 FIXME("stub: returning false\n"); 965 *pbEnabled = 0; 966 return S_OK; 967 } 968 969 #endif 970 971 /*********************************************************************** 972 * AtlGetVersion [atl100.@] 973 */ 974 DWORD WINAPI AtlGetVersion(void *pReserved) 975 { 976 TRACE("version %04x (%p)\n", _ATL_VER, pReserved); 977 return _ATL_VER; 978 } 979 980 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 981 { 982 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); 983 984 switch(fdwReason) { 985 case DLL_PROCESS_ATTACH: 986 atl_instance = hinstDLL; 987 DisableThreadLibraryCalls(hinstDLL); 988 break; 989 case DLL_PROCESS_DETACH: 990 if (lpvReserved) break; 991 if(catreg) 992 ICatRegister_Release(catreg); 993 } 994 995 return TRUE; 996 } 997