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