comctl32/tooltips: Reset window subclass data when removing tools.
[wine.git] / dlls / atl / atl.c
blob0e48a391d95518929201097bda5a7c37514c2d1a
1 /*
2 * Copyright 2012 Stefan Leichter
3 * Copyright 2012 Jacek Caban for CodeWeavers
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.
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.
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
20 #define COBJMACROS
22 #include "atlbase.h"
23 #include "atlcom.h"
25 #include "wine/debug.h"
26 #include "wine/unicode.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(atl);
30 #define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer)
32 HINSTANCE atl_instance;
34 typedef unsigned char cpp_bool;
36 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size)
38 return HeapAlloc(GetProcessHeap(), 0, size);
41 static inline BOOL heap_free(void *mem)
43 return HeapFree(GetProcessHeap(), 0, mem);
46 static ICatRegister *catreg;
48 /***********************************************************************
49 * AtlAdvise [atl100.@]
51 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
53 IConnectionPointContainer *container;
54 IConnectionPoint *cp;
55 HRESULT hres;
57 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
59 if(!pUnkCP)
60 return E_INVALIDARG;
62 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
63 if(FAILED(hres))
64 return hres;
66 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
67 IConnectionPointContainer_Release(container);
68 if(FAILED(hres))
69 return hres;
71 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
72 IConnectionPoint_Release(cp);
73 return hres;
76 /***********************************************************************
77 * AtlUnadvise [atl100.@]
79 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
81 IConnectionPointContainer *container;
82 IConnectionPoint *cp;
83 HRESULT hres;
85 TRACE("%p %p %d\n", pUnkCP, iid, dw);
87 if(!pUnkCP)
88 return E_INVALIDARG;
90 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
91 if(FAILED(hres))
92 return hres;
94 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
95 IConnectionPointContainer_Release(container);
96 if(FAILED(hres))
97 return hres;
99 hres = IConnectionPoint_Unadvise(cp, dw);
100 IConnectionPoint_Release(cp);
101 return hres;
104 /***********************************************************************
105 * AtlFreeMarshalStream [atl100.@]
107 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
109 FIXME("%p\n", stm);
110 return S_OK;
113 /***********************************************************************
114 * AtlMarshalPtrInProc [atl100.@]
116 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
118 FIXME("%p %p %p\n", pUnk, iid, pstm);
119 return E_FAIL;
122 /***********************************************************************
123 * AtlUnmarshalPtr [atl100.@]
125 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
127 FIXME("%p %p %p\n", stm, iid, ppUnk);
128 return E_FAIL;
131 /***********************************************************************
132 * AtlCreateTargetDC [atl100.@]
134 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
136 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
137 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
138 DEVMODEW *devmode = NULL;
140 TRACE( "(%p, %p)\n", hdc, dv );
142 if (dv)
144 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
145 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
146 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
147 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
149 else
151 if (hdc) return hdc;
152 driver = displayW;
154 return CreateDCW( driver, device, port, devmode );
157 /***********************************************************************
158 * AtlHiMetricToPixel [atl100.@]
160 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
162 HDC dc = GetDC(NULL);
163 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
164 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
165 ReleaseDC( NULL, dc );
168 /***********************************************************************
169 * AtlPixelToHiMetric [atl100.@]
171 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
173 HDC dc = GetDC(NULL);
174 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
175 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
176 ReleaseDC( NULL, dc );
179 /***********************************************************************
180 * AtlComPtrAssign [atl100.@]
182 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
184 TRACE("(%p %p)\n", pp, p);
186 if (p) IUnknown_AddRef(p);
187 if (*pp) IUnknown_Release(*pp);
188 *pp = p;
189 return p;
192 /***********************************************************************
193 * AtlComQIPtrAssign [atl100.@]
195 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
197 IUnknown *new_p = NULL;
199 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
201 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
202 if (*pp) IUnknown_Release(*pp);
203 *pp = new_p;
204 return new_p;
207 /***********************************************************************
208 * AtlInternalQueryInterface [atl100.@]
210 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
212 int i = 0;
213 HRESULT rc = E_NOINTERFACE;
214 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
216 if (IsEqualGUID(iid,&IID_IUnknown))
218 TRACE("Returning IUnknown\n");
219 *ppvObject = ((LPSTR)this+pEntries[0].dw);
220 IUnknown_AddRef((IUnknown*)*ppvObject);
221 return S_OK;
224 while (pEntries[i].pFunc != 0)
226 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
227 pEntries[i].dw, pEntries[i].pFunc);
229 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
231 TRACE("MATCH\n");
232 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
234 TRACE("Offset\n");
235 *ppvObject = ((LPSTR)this+pEntries[i].dw);
236 IUnknown_AddRef((IUnknown*)*ppvObject);
237 return S_OK;
239 else
241 TRACE("Function\n");
242 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
243 if(rc==S_OK || pEntries[i].piid)
244 return rc;
247 i++;
249 TRACE("Done returning (0x%x)\n",rc);
250 return rc;
253 /***********************************************************************
254 * AtlIPersistStreamInit_Load [atl100.@]
256 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
257 void *pThis, IUnknown *pUnk)
259 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
261 return S_OK;
264 /***********************************************************************
265 * AtlIPersistStreamInit_Save [atl100.@]
267 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
268 ATL_PROPMAP_ENTRY *pMap, void *pThis,
269 IUnknown *pUnk)
271 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
273 return S_OK;
276 /***********************************************************************
277 * AtlIPersistPropertyBag_Load [atl100.@]
279 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
280 ATL_PROPMAP_ENTRY *pMap, void *pThis,
281 IUnknown *pUnk)
283 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
285 return S_OK;
288 /***********************************************************************
289 * AtlIPersistPropertyBag_Save [atl100.@]
291 HRESULT WINAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty,
292 BOOL fSaveAll, ATL_PROPMAP_ENTRY *pMap,
293 void *pThis, IUnknown *pUnk)
295 FIXME("(%p, %d, %d, %p, %p, %p)\n", pPropBag, fClearDirty, fSaveAll, pMap, pThis, pUnk);
297 return S_OK;
300 /***********************************************************************
301 * AtlModuleAddTermFunc [atl100.@]
303 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
305 _ATL_TERMFUNC_ELEM *termfunc_elem;
307 TRACE("version %04x (%p %p %ld)\n", _ATL_VER, pM, pFunc, dw);
309 if (_ATL_VER > _ATL_VER_30 || pM->cbSize > ATLVer1Size) {
310 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
311 termfunc_elem->pFunc = pFunc;
312 termfunc_elem->dw = dw;
313 termfunc_elem->pNext = pM->m_pTermFuncs;
315 pM->m_pTermFuncs = termfunc_elem;
318 return S_OK;
321 #if _ATL_VER > _ATL_VER_30
323 /***********************************************************************
324 * AtlCallTermFunc [atl100.@]
326 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
328 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
330 TRACE("(%p)\n", pM);
332 while(iter) {
333 iter->pFunc(iter->dw);
334 tmp = iter;
335 iter = iter->pNext;
336 HeapFree(GetProcessHeap(), 0, tmp);
339 pM->m_pTermFuncs = NULL;
342 #endif
344 /***********************************************************************
345 * AtlLoadTypeLib [atl100.56]
347 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
348 BSTR *pbstrPath, ITypeLib **ppTypeLib)
350 size_t path_len, index_len;
351 ITypeLib *typelib = NULL;
352 WCHAR *path;
353 HRESULT hres;
355 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
357 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
359 index_len = lpszIndex ? strlenW(lpszIndex) : 0;
360 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
361 if(!path)
362 return E_OUTOFMEMORY;
364 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
365 if(!path_len) {
366 heap_free(path);
367 return HRESULT_FROM_WIN32(GetLastError());
370 if(index_len)
371 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
373 hres = LoadTypeLib(path, &typelib);
374 if(FAILED(hres)) {
375 WCHAR *ptr;
377 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
378 if(*ptr != '.')
379 ptr = path+path_len;
380 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
381 hres = LoadTypeLib(path, &typelib);
384 if(SUCCEEDED(hres)) {
385 *pbstrPath = SysAllocString(path);
386 if(!*pbstrPath) {
387 ITypeLib_Release(typelib);
388 hres = E_OUTOFMEMORY;
392 heap_free(path);
393 if(FAILED(hres))
394 return hres;
396 *ppTypeLib = typelib;
397 return S_OK;
400 #if _ATL_VER <= _ATL_VER_80
402 /***********************************************************************
403 * AtlRegisterTypeLib [atl80.19]
405 HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index)
407 ITypeLib *typelib;
408 BSTR path;
409 HRESULT hres;
411 TRACE("(%p %s)\n", inst, debugstr_w(index));
413 hres = AtlLoadTypeLib(inst, index, &path, &typelib);
414 if(FAILED(hres))
415 return hres;
417 hres = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
418 ITypeLib_Release(typelib);
419 SysFreeString(path);
420 return hres;
423 #endif
425 #if _ATL_VER > _ATL_VER_30
427 /***********************************************************************
428 * AtlWinModuleInit [atl100.65]
430 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
432 TRACE("(%p)\n", winmod);
434 if(winmod->cbSize != sizeof(*winmod))
435 return E_INVALIDARG;
437 InitializeCriticalSection(&winmod->m_csWindowCreate);
438 winmod->m_pCreateWndList = NULL;
439 return S_OK;
442 /***********************************************************************
443 * AtlWinModuleAddCreateWndData [atl100.43]
445 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
447 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
449 pData->m_pThis = pvObject;
450 pData->m_dwThreadID = GetCurrentThreadId();
452 EnterCriticalSection(&pM->m_csWindowCreate);
453 pData->m_pNext = pM->m_pCreateWndList;
454 pM->m_pCreateWndList = pData;
455 LeaveCriticalSection(&pM->m_csWindowCreate);
458 /***********************************************************************
459 * AtlWinModuleExtractCreateWndData [atl100.44]
461 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
463 _AtlCreateWndData *iter, *prev = NULL;
464 DWORD thread_id;
466 TRACE("(%p)\n", winmod);
468 thread_id = GetCurrentThreadId();
470 EnterCriticalSection(&winmod->m_csWindowCreate);
472 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
473 prev = iter;
474 if(iter) {
475 if(prev)
476 prev->m_pNext = iter->m_pNext;
477 else
478 winmod->m_pCreateWndList = iter->m_pNext;
481 LeaveCriticalSection(&winmod->m_csWindowCreate);
483 return iter ? iter->m_pThis : NULL;
486 /***********************************************************************
487 * AtlComModuleGetClassObject [atl100.15]
489 #if _ATL_VER < _ATL_VER_110
490 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
492 _ATL_OBJMAP_ENTRY **iter;
493 HRESULT hres;
495 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
497 if(!pm)
498 return E_INVALIDARG;
500 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
501 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
502 if(!(*iter)->pCF)
503 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
504 if((*iter)->pCF)
505 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
506 TRACE("returning %p (%08x)\n", *ppv, hres);
507 return hres;
511 WARN("Class %s not found\n", debugstr_guid(rclsid));
512 return CLASS_E_CLASSNOTAVAILABLE;
514 #else
515 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
517 _ATL_OBJMAP_ENTRY_EX **iter;
518 HRESULT hres;
520 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
522 if(!pm)
523 return E_INVALIDARG;
525 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
526 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
527 if(!(*iter)->pCache->pCF)
528 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCache->pCF);
529 if((*iter)->pCache->pCF)
530 hres = IUnknown_QueryInterface((*iter)->pCache->pCF, riid, ppv);
531 TRACE("returning %p (%08x)\n", *ppv, hres);
532 return hres;
536 WARN("Class %s not found\n", debugstr_guid(rclsid));
537 return CLASS_E_CLASSNOTAVAILABLE;
539 #endif
541 /***********************************************************************
542 * AtlComModuleRegisterClassObjects [atl100.17]
544 #if _ATL_VER < _ATL_VER_110
545 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
547 _ATL_OBJMAP_ENTRY **iter;
548 IUnknown *unk;
549 HRESULT hres;
551 TRACE("(%p %x %x)\n", module, context, flags);
553 if(!module)
554 return E_INVALIDARG;
556 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
557 if(!(*iter)->pfnGetClassObject)
558 continue;
560 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
561 if(FAILED(hres))
562 return hres;
564 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
565 IUnknown_Release(unk);
566 if(FAILED(hres))
567 return hres;
570 return S_OK;
572 #else
573 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
575 _ATL_OBJMAP_ENTRY_EX **iter;
576 IUnknown *unk;
577 HRESULT hres;
579 TRACE("(%p %x %x)\n", module, context, flags);
581 if(!module)
582 return E_INVALIDARG;
584 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
585 if(!(*iter)->pfnGetClassObject)
586 continue;
588 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
589 if(FAILED(hres))
590 return hres;
592 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->pCache->dwRegister);
593 IUnknown_Release(unk);
594 if(FAILED(hres))
595 return hres;
598 return S_OK;
600 #endif
602 /***********************************************************************
603 * AtlComModuleRevokeClassObjects [atl100.20]
605 #if _ATL_VER < _ATL_VER_110
606 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
608 _ATL_OBJMAP_ENTRY **iter;
609 HRESULT hres;
611 TRACE("(%p)\n", module);
613 if(!module)
614 return E_INVALIDARG;
616 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
617 hres = CoRevokeClassObject((*iter)->dwRegister);
618 if(FAILED(hres))
619 return hres;
622 return S_OK;
624 #else
625 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
627 _ATL_OBJMAP_ENTRY_EX **iter;
628 HRESULT hres;
630 TRACE("(%p)\n", module);
632 if(!module)
633 return E_INVALIDARG;
635 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
636 hres = CoRevokeClassObject((*iter)->pCache->dwRegister);
637 if(FAILED(hres))
638 return hres;
641 return S_OK;
643 #endif
645 /***********************************************************************
646 * AtlComModuleUnregisterServer [atl100.22]
648 #if _ATL_VER < _ATL_VER_110
649 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
651 const struct _ATL_CATMAP_ENTRY *catmap;
652 _ATL_OBJMAP_ENTRY **iter;
653 HRESULT hres;
655 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
657 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
658 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
659 continue;
661 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
663 catmap = (*iter)->pfnGetCategoryMap();
664 if(catmap) {
665 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
666 if(FAILED(hres))
667 return hres;
670 hres = (*iter)->pfnUpdateRegistry(FALSE);
671 if(FAILED(hres))
672 return hres;
675 if(bRegTypeLib) {
676 ITypeLib *typelib;
677 TLIBATTR *attr;
678 BSTR path;
680 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
681 if(FAILED(hres))
682 return hres;
684 SysFreeString(path);
685 hres = ITypeLib_GetLibAttr(typelib, &attr);
686 if(SUCCEEDED(hres)) {
687 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
688 ITypeLib_ReleaseTLibAttr(typelib, attr);
690 ITypeLib_Release(typelib);
691 if(FAILED(hres))
692 return hres;
695 return S_OK;
697 #else
698 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
700 const struct _ATL_CATMAP_ENTRY *catmap;
701 _ATL_OBJMAP_ENTRY_EX **iter;
702 HRESULT hres;
704 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
706 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
707 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
708 continue;
710 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
712 catmap = (*iter)->pfnGetCategoryMap();
713 if(catmap) {
714 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
715 if(FAILED(hres))
716 return hres;
719 hres = (*iter)->pfnUpdateRegistry(FALSE);
720 if(FAILED(hres))
721 return hres;
724 if(bRegTypeLib) {
725 ITypeLib *typelib;
726 TLIBATTR *attr;
727 BSTR path;
729 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
730 if(FAILED(hres))
731 return hres;
733 SysFreeString(path);
734 hres = ITypeLib_GetLibAttr(typelib, &attr);
735 if(SUCCEEDED(hres)) {
736 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
737 ITypeLib_ReleaseTLibAttr(typelib, attr);
739 ITypeLib_Release(typelib);
740 if(FAILED(hres))
741 return hres;
744 return S_OK;
746 #endif
748 #endif
750 /***********************************************************************
751 * AtlRegisterClassCategoriesHelper [atl100.49]
753 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
755 const struct _ATL_CATMAP_ENTRY *iter;
756 HRESULT hres;
758 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
760 if(!catmap)
761 return S_OK;
763 if(!catreg) {
764 ICatRegister *new_catreg;
766 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
767 &IID_ICatRegister, (void**)&new_catreg);
768 if(FAILED(hres))
769 return hres;
771 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
772 ICatRegister_Release(new_catreg);
775 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
776 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
778 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
779 if(reg)
780 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
781 else
782 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
783 }else {
784 if(reg)
785 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
786 else
787 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
789 if(FAILED(hres))
790 return hres;
793 if(!reg) {
794 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
796 static const WCHAR implemented_catW[] =
797 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
798 static const WCHAR required_catW[] =
799 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
801 ptr += StringFromGUID2(clsid, ptr, 64)-1;
802 *ptr++ = '\\';
804 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
805 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
807 memcpy(ptr, required_catW, sizeof(required_catW));
808 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
811 return S_OK;
814 /***********************************************************************
815 * AtlWaitWithMessageLoop [atl100.24]
817 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
819 MSG msg;
820 DWORD res;
822 TRACE("(%p)\n", handle);
824 while(1) {
825 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
826 switch(res) {
827 case WAIT_OBJECT_0:
828 return TRUE;
829 case WAIT_OBJECT_0+1:
830 if(GetMessageW(&msg, NULL, 0, 0) < 0)
831 return FALSE;
833 TranslateMessage(&msg);
834 DispatchMessageW(&msg);
835 break;
836 default:
837 return FALSE;
842 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
844 ITypeInfo *typeinfo, *src_typeinfo = NULL;
845 TYPEATTR *attr;
846 int type_flags;
847 unsigned i;
848 HRESULT hres;
850 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
851 if(FAILED(hres))
852 return hres;
854 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
855 if(FAILED(hres)) {
856 ITypeInfo_Release(typeinfo);
857 return hres;
860 for(i=0; i < attr->cImplTypes; i++) {
861 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
862 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
863 HREFTYPE ref;
865 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
866 if(SUCCEEDED(hres))
867 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
868 break;
872 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
873 ITypeInfo_Release(typeinfo);
874 if(FAILED(hres))
875 return hres;
877 if(!src_typeinfo) {
878 *iid = IID_NULL;
879 return S_OK;
882 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
883 if(SUCCEEDED(hres)) {
884 *iid = attr->guid;
885 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
887 ITypeInfo_Release(src_typeinfo);
888 return hres;
891 /***********************************************************************
892 * AtlGetObjectSourceInterface [atl100.54]
894 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
896 IProvideClassInfo2 *classinfo;
897 ITypeInfo *typeinfo;
898 ITypeLib *typelib;
899 IPersist *persist;
900 IDispatch *disp;
901 HRESULT hres;
903 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
905 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
906 if(FAILED(hres))
907 return hres;
909 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
910 IDispatch_Release(disp);
911 if(FAILED(hres))
912 return hres;
914 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
915 ITypeInfo_Release(typeinfo);
916 if(SUCCEEDED(hres)) {
917 TLIBATTR *attr;
919 hres = ITypeLib_GetLibAttr(typelib, &attr);
920 if(SUCCEEDED(hres)) {
921 *libid = attr->guid;
922 *major = attr->wMajorVerNum;
923 *minor = attr->wMinorVerNum;
924 ITypeLib_ReleaseTLibAttr(typelib, attr);
925 }else {
926 ITypeLib_Release(typelib);
929 if(FAILED(hres))
930 return hres;
932 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
933 if(SUCCEEDED(hres)) {
934 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
935 IProvideClassInfo2_Release(classinfo);
936 ITypeLib_Release(typelib);
937 return hres;
940 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
941 if(SUCCEEDED(hres)) {
942 CLSID clsid;
944 hres = IPersist_GetClassID(persist, &clsid);
945 if(SUCCEEDED(hres))
946 hres = get_default_source(typelib, &clsid, iid);
947 IPersist_Release(persist);
950 return hres;
953 #if _ATL_VER >= _ATL_VER90
955 /***********************************************************************
956 * AtlSetPerUserRegistration [atl100.67]
958 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
960 FIXME("stub: bEnable: %d\n", bEnable);
961 return E_NOTIMPL;
964 /***********************************************************************
965 * AtlGetPerUserRegistration [atl100.68]
967 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
969 FIXME("stub: returning false\n");
970 *pbEnabled = 0;
971 return S_OK;
974 #endif
976 /***********************************************************************
977 * AtlGetVersion [atl100.@]
979 DWORD WINAPI AtlGetVersion(void *pReserved)
981 TRACE("version %04x (%p)\n", _ATL_VER, pReserved);
982 return _ATL_VER;
985 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
987 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
989 switch(fdwReason) {
990 case DLL_PROCESS_ATTACH:
991 atl_instance = hinstDLL;
992 DisableThreadLibraryCalls(hinstDLL);
993 break;
994 case DLL_PROCESS_DETACH:
995 if (lpvReserved) break;
996 if(catreg)
997 ICatRegister_Release(catreg);
1000 return TRUE;