ntdll: Rename attach_dlls() to LdrInitializeThunk().
[wine.git] / dlls / atl / atl.c
blobe753429327e5cfc38718f28955b4d484aa9e5452
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/heap.h"
27 #include "wine/unicode.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(atl);
31 #define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer)
33 HINSTANCE atl_instance;
35 typedef unsigned char cpp_bool;
37 static ICatRegister *catreg;
39 /***********************************************************************
40 * AtlAdvise [atl100.@]
42 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
44 IConnectionPointContainer *container;
45 IConnectionPoint *cp;
46 HRESULT hres;
48 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
50 if(!pUnkCP)
51 return E_INVALIDARG;
53 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
54 if(FAILED(hres))
55 return hres;
57 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
58 IConnectionPointContainer_Release(container);
59 if(FAILED(hres))
60 return hres;
62 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
63 IConnectionPoint_Release(cp);
64 return hres;
67 /***********************************************************************
68 * AtlUnadvise [atl100.@]
70 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
72 IConnectionPointContainer *container;
73 IConnectionPoint *cp;
74 HRESULT hres;
76 TRACE("%p %p %d\n", pUnkCP, iid, dw);
78 if(!pUnkCP)
79 return E_INVALIDARG;
81 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
82 if(FAILED(hres))
83 return hres;
85 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
86 IConnectionPointContainer_Release(container);
87 if(FAILED(hres))
88 return hres;
90 hres = IConnectionPoint_Unadvise(cp, dw);
91 IConnectionPoint_Release(cp);
92 return hres;
95 /***********************************************************************
96 * AtlFreeMarshalStream [atl100.@]
98 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
100 FIXME("%p\n", stm);
101 return S_OK;
104 /***********************************************************************
105 * AtlMarshalPtrInProc [atl100.@]
107 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
109 FIXME("%p %p %p\n", pUnk, iid, pstm);
110 return E_FAIL;
113 /***********************************************************************
114 * AtlUnmarshalPtr [atl100.@]
116 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
118 FIXME("%p %p %p\n", stm, iid, ppUnk);
119 return E_FAIL;
122 /***********************************************************************
123 * AtlCreateTargetDC [atl100.@]
125 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
127 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
128 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
129 DEVMODEW *devmode = NULL;
131 TRACE( "(%p, %p)\n", hdc, dv );
133 if (dv)
135 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
136 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
137 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
138 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
140 else
142 if (hdc) return hdc;
143 driver = displayW;
145 return CreateDCW( driver, device, port, devmode );
148 /***********************************************************************
149 * AtlHiMetricToPixel [atl100.@]
151 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
153 HDC dc = GetDC(NULL);
154 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
155 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
156 ReleaseDC( NULL, dc );
159 /***********************************************************************
160 * AtlPixelToHiMetric [atl100.@]
162 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
164 HDC dc = GetDC(NULL);
165 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
166 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
167 ReleaseDC( NULL, dc );
170 /***********************************************************************
171 * AtlComPtrAssign [atl100.@]
173 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
175 TRACE("(%p %p)\n", pp, p);
177 if (p) IUnknown_AddRef(p);
178 if (*pp) IUnknown_Release(*pp);
179 *pp = p;
180 return p;
183 /***********************************************************************
184 * AtlComQIPtrAssign [atl100.@]
186 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
188 IUnknown *new_p = NULL;
190 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
192 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
193 if (*pp) IUnknown_Release(*pp);
194 *pp = new_p;
195 return new_p;
198 /***********************************************************************
199 * AtlInternalQueryInterface [atl100.@]
201 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
203 int i = 0;
204 HRESULT rc = E_NOINTERFACE;
205 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
207 if (IsEqualGUID(iid,&IID_IUnknown))
209 TRACE("Returning IUnknown\n");
210 *ppvObject = ((LPSTR)this+pEntries[0].dw);
211 IUnknown_AddRef((IUnknown*)*ppvObject);
212 return S_OK;
215 while (pEntries[i].pFunc != 0)
217 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
218 pEntries[i].dw, pEntries[i].pFunc);
220 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
222 TRACE("MATCH\n");
223 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
225 TRACE("Offset\n");
226 *ppvObject = ((LPSTR)this+pEntries[i].dw);
227 IUnknown_AddRef((IUnknown*)*ppvObject);
228 return S_OK;
230 else
232 TRACE("Function\n");
233 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
234 if(rc==S_OK || pEntries[i].piid)
235 return rc;
238 i++;
240 TRACE("Done returning (0x%x)\n",rc);
241 return rc;
244 /***********************************************************************
245 * AtlIPersistStreamInit_Load [atl100.@]
247 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
248 void *pThis, IUnknown *pUnk)
250 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
252 return S_OK;
255 /***********************************************************************
256 * AtlIPersistStreamInit_Save [atl100.@]
258 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
259 ATL_PROPMAP_ENTRY *pMap, void *pThis,
260 IUnknown *pUnk)
262 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
264 return S_OK;
267 /***********************************************************************
268 * AtlIPersistPropertyBag_Load [atl100.@]
270 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
271 ATL_PROPMAP_ENTRY *pMap, void *pThis,
272 IUnknown *pUnk)
274 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
276 return S_OK;
279 /***********************************************************************
280 * AtlIPersistPropertyBag_Save [atl100.@]
282 HRESULT WINAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty,
283 BOOL fSaveAll, ATL_PROPMAP_ENTRY *pMap,
284 void *pThis, IUnknown *pUnk)
286 FIXME("(%p, %d, %d, %p, %p, %p)\n", pPropBag, fClearDirty, fSaveAll, pMap, pThis, pUnk);
288 return S_OK;
291 /***********************************************************************
292 * AtlModuleAddTermFunc [atl100.@]
294 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
296 _ATL_TERMFUNC_ELEM *termfunc_elem;
298 TRACE("version %04x (%p %p %ld)\n", _ATL_VER, pM, pFunc, dw);
300 if (_ATL_VER > _ATL_VER_30 || pM->cbSize > ATLVer1Size) {
301 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
302 termfunc_elem->pFunc = pFunc;
303 termfunc_elem->dw = dw;
304 termfunc_elem->pNext = pM->m_pTermFuncs;
306 pM->m_pTermFuncs = termfunc_elem;
309 return S_OK;
312 #if _ATL_VER > _ATL_VER_30
314 /***********************************************************************
315 * AtlCallTermFunc [atl100.@]
317 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
319 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
321 TRACE("(%p)\n", pM);
323 while(iter) {
324 iter->pFunc(iter->dw);
325 tmp = iter;
326 iter = iter->pNext;
327 HeapFree(GetProcessHeap(), 0, tmp);
330 pM->m_pTermFuncs = NULL;
333 #endif
335 /***********************************************************************
336 * AtlLoadTypeLib [atl100.56]
338 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
339 BSTR *pbstrPath, ITypeLib **ppTypeLib)
341 size_t path_len, index_len;
342 ITypeLib *typelib = NULL;
343 WCHAR *path;
344 HRESULT hres;
346 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
348 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
350 index_len = lpszIndex ? strlenW(lpszIndex) : 0;
351 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
352 if(!path)
353 return E_OUTOFMEMORY;
355 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
356 if(!path_len) {
357 heap_free(path);
358 return HRESULT_FROM_WIN32(GetLastError());
361 if(index_len)
362 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
364 hres = LoadTypeLib(path, &typelib);
365 if(FAILED(hres)) {
366 WCHAR *ptr;
368 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
369 if(*ptr != '.')
370 ptr = path+path_len;
371 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
372 hres = LoadTypeLib(path, &typelib);
375 if(SUCCEEDED(hres)) {
376 *pbstrPath = SysAllocString(path);
377 if(!*pbstrPath) {
378 ITypeLib_Release(typelib);
379 hres = E_OUTOFMEMORY;
383 heap_free(path);
384 if(FAILED(hres))
385 return hres;
387 *ppTypeLib = typelib;
388 return S_OK;
391 #if _ATL_VER <= _ATL_VER_80
393 /***********************************************************************
394 * AtlRegisterTypeLib [atl80.19]
396 HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index)
398 ITypeLib *typelib;
399 BSTR path;
400 HRESULT hres;
402 TRACE("(%p %s)\n", inst, debugstr_w(index));
404 hres = AtlLoadTypeLib(inst, index, &path, &typelib);
405 if(FAILED(hres))
406 return hres;
408 hres = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
409 ITypeLib_Release(typelib);
410 SysFreeString(path);
411 return hres;
414 #endif
416 #if _ATL_VER > _ATL_VER_30
418 /***********************************************************************
419 * AtlWinModuleInit [atl100.65]
421 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
423 TRACE("(%p)\n", winmod);
425 if(winmod->cbSize != sizeof(*winmod))
426 return E_INVALIDARG;
428 InitializeCriticalSection(&winmod->m_csWindowCreate);
429 winmod->m_pCreateWndList = NULL;
430 return S_OK;
433 /***********************************************************************
434 * AtlWinModuleAddCreateWndData [atl100.43]
436 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
438 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
440 pData->m_pThis = pvObject;
441 pData->m_dwThreadID = GetCurrentThreadId();
443 EnterCriticalSection(&pM->m_csWindowCreate);
444 pData->m_pNext = pM->m_pCreateWndList;
445 pM->m_pCreateWndList = pData;
446 LeaveCriticalSection(&pM->m_csWindowCreate);
449 /***********************************************************************
450 * AtlWinModuleExtractCreateWndData [atl100.44]
452 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
454 _AtlCreateWndData *iter, *prev = NULL;
455 DWORD thread_id;
457 TRACE("(%p)\n", winmod);
459 thread_id = GetCurrentThreadId();
461 EnterCriticalSection(&winmod->m_csWindowCreate);
463 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
464 prev = iter;
465 if(iter) {
466 if(prev)
467 prev->m_pNext = iter->m_pNext;
468 else
469 winmod->m_pCreateWndList = iter->m_pNext;
472 LeaveCriticalSection(&winmod->m_csWindowCreate);
474 return iter ? iter->m_pThis : NULL;
477 /***********************************************************************
478 * AtlComModuleGetClassObject [atl100.15]
480 #if _ATL_VER < _ATL_VER_110
481 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
483 _ATL_OBJMAP_ENTRY **iter;
484 HRESULT hres;
486 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
488 if(!pm)
489 return E_INVALIDARG;
491 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
492 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
493 if(!(*iter)->pCF)
494 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
495 if((*iter)->pCF)
496 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
497 TRACE("returning %p (%08x)\n", *ppv, hres);
498 return hres;
502 WARN("Class %s not found\n", debugstr_guid(rclsid));
503 return CLASS_E_CLASSNOTAVAILABLE;
505 #else
506 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
508 _ATL_OBJMAP_ENTRY_EX **iter;
509 HRESULT hres;
511 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
513 if(!pm)
514 return E_INVALIDARG;
516 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
517 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
518 if(!(*iter)->pCache->pCF)
519 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCache->pCF);
520 if((*iter)->pCache->pCF)
521 hres = IUnknown_QueryInterface((*iter)->pCache->pCF, riid, ppv);
522 TRACE("returning %p (%08x)\n", *ppv, hres);
523 return hres;
527 WARN("Class %s not found\n", debugstr_guid(rclsid));
528 return CLASS_E_CLASSNOTAVAILABLE;
530 #endif
532 /***********************************************************************
533 * AtlComModuleRegisterClassObjects [atl100.17]
535 #if _ATL_VER < _ATL_VER_110
536 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
538 _ATL_OBJMAP_ENTRY **iter;
539 IUnknown *unk;
540 HRESULT hres;
542 TRACE("(%p %x %x)\n", module, context, flags);
544 if(!module)
545 return E_INVALIDARG;
547 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
548 if(!(*iter)->pfnGetClassObject)
549 continue;
551 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
552 if(FAILED(hres))
553 return hres;
555 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
556 IUnknown_Release(unk);
557 if(FAILED(hres))
558 return hres;
561 return S_OK;
563 #else
564 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
566 _ATL_OBJMAP_ENTRY_EX **iter;
567 IUnknown *unk;
568 HRESULT hres;
570 TRACE("(%p %x %x)\n", module, context, flags);
572 if(!module)
573 return E_INVALIDARG;
575 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
576 if(!(*iter)->pfnGetClassObject)
577 continue;
579 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
580 if(FAILED(hres))
581 return hres;
583 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->pCache->dwRegister);
584 IUnknown_Release(unk);
585 if(FAILED(hres))
586 return hres;
589 return S_OK;
591 #endif
593 /***********************************************************************
594 * AtlComModuleRevokeClassObjects [atl100.20]
596 #if _ATL_VER < _ATL_VER_110
597 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
599 _ATL_OBJMAP_ENTRY **iter;
600 HRESULT hres;
602 TRACE("(%p)\n", module);
604 if(!module)
605 return E_INVALIDARG;
607 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
608 hres = CoRevokeClassObject((*iter)->dwRegister);
609 if(FAILED(hres))
610 return hres;
613 return S_OK;
615 #else
616 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
618 _ATL_OBJMAP_ENTRY_EX **iter;
619 HRESULT hres;
621 TRACE("(%p)\n", module);
623 if(!module)
624 return E_INVALIDARG;
626 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
627 hres = CoRevokeClassObject((*iter)->pCache->dwRegister);
628 if(FAILED(hres))
629 return hres;
632 return S_OK;
634 #endif
636 /***********************************************************************
637 * AtlComModuleUnregisterServer [atl100.22]
639 #if _ATL_VER < _ATL_VER_110
640 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
642 const struct _ATL_CATMAP_ENTRY *catmap;
643 _ATL_OBJMAP_ENTRY **iter;
644 HRESULT hres;
646 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
648 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
649 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
650 continue;
652 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
654 catmap = (*iter)->pfnGetCategoryMap();
655 if(catmap) {
656 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
657 if(FAILED(hres))
658 return hres;
661 hres = (*iter)->pfnUpdateRegistry(FALSE);
662 if(FAILED(hres))
663 return hres;
666 if(bRegTypeLib) {
667 ITypeLib *typelib;
668 TLIBATTR *attr;
669 BSTR path;
671 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
672 if(FAILED(hres))
673 return hres;
675 SysFreeString(path);
676 hres = ITypeLib_GetLibAttr(typelib, &attr);
677 if(SUCCEEDED(hres)) {
678 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
679 ITypeLib_ReleaseTLibAttr(typelib, attr);
681 ITypeLib_Release(typelib);
682 if(FAILED(hres))
683 return hres;
686 return S_OK;
688 #else
689 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
691 const struct _ATL_CATMAP_ENTRY *catmap;
692 _ATL_OBJMAP_ENTRY_EX **iter;
693 HRESULT hres;
695 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
697 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
698 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
699 continue;
701 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
703 catmap = (*iter)->pfnGetCategoryMap();
704 if(catmap) {
705 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
706 if(FAILED(hres))
707 return hres;
710 hres = (*iter)->pfnUpdateRegistry(FALSE);
711 if(FAILED(hres))
712 return hres;
715 if(bRegTypeLib) {
716 ITypeLib *typelib;
717 TLIBATTR *attr;
718 BSTR path;
720 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
721 if(FAILED(hres))
722 return hres;
724 SysFreeString(path);
725 hres = ITypeLib_GetLibAttr(typelib, &attr);
726 if(SUCCEEDED(hres)) {
727 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
728 ITypeLib_ReleaseTLibAttr(typelib, attr);
730 ITypeLib_Release(typelib);
731 if(FAILED(hres))
732 return hres;
735 return S_OK;
737 #endif
739 #endif
741 /***********************************************************************
742 * AtlRegisterClassCategoriesHelper [atl100.49]
744 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
746 const struct _ATL_CATMAP_ENTRY *iter;
747 HRESULT hres;
749 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
751 if(!catmap)
752 return S_OK;
754 if(!catreg) {
755 ICatRegister *new_catreg;
757 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
758 &IID_ICatRegister, (void**)&new_catreg);
759 if(FAILED(hres))
760 return hres;
762 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
763 ICatRegister_Release(new_catreg);
766 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
767 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
769 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
770 if(reg)
771 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
772 else
773 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
774 }else {
775 if(reg)
776 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
777 else
778 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
780 if(FAILED(hres))
781 return hres;
784 if(!reg) {
785 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
787 static const WCHAR implemented_catW[] =
788 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
789 static const WCHAR required_catW[] =
790 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
792 ptr += StringFromGUID2(clsid, ptr, 64)-1;
793 *ptr++ = '\\';
795 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
796 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
798 memcpy(ptr, required_catW, sizeof(required_catW));
799 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
802 return S_OK;
805 /***********************************************************************
806 * AtlWaitWithMessageLoop [atl100.24]
808 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
810 MSG msg;
811 DWORD res;
813 TRACE("(%p)\n", handle);
815 while(1) {
816 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
817 switch(res) {
818 case WAIT_OBJECT_0:
819 return TRUE;
820 case WAIT_OBJECT_0+1:
821 if(GetMessageW(&msg, NULL, 0, 0) < 0)
822 return FALSE;
824 TranslateMessage(&msg);
825 DispatchMessageW(&msg);
826 break;
827 default:
828 return FALSE;
833 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
835 ITypeInfo *typeinfo, *src_typeinfo = NULL;
836 TYPEATTR *attr;
837 int type_flags;
838 unsigned i;
839 HRESULT hres;
841 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
842 if(FAILED(hres))
843 return hres;
845 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
846 if(FAILED(hres)) {
847 ITypeInfo_Release(typeinfo);
848 return hres;
851 for(i=0; i < attr->cImplTypes; i++) {
852 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
853 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
854 HREFTYPE ref;
856 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
857 if(SUCCEEDED(hres))
858 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
859 break;
863 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
864 ITypeInfo_Release(typeinfo);
865 if(FAILED(hres))
866 return hres;
868 if(!src_typeinfo) {
869 *iid = IID_NULL;
870 return S_OK;
873 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
874 if(SUCCEEDED(hres)) {
875 *iid = attr->guid;
876 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
878 ITypeInfo_Release(src_typeinfo);
879 return hres;
882 /***********************************************************************
883 * AtlGetObjectSourceInterface [atl100.54]
885 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
887 IProvideClassInfo2 *classinfo;
888 ITypeInfo *typeinfo;
889 ITypeLib *typelib;
890 IPersist *persist;
891 IDispatch *disp;
892 HRESULT hres;
894 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
896 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
897 if(FAILED(hres))
898 return hres;
900 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
901 IDispatch_Release(disp);
902 if(FAILED(hres))
903 return hres;
905 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
906 ITypeInfo_Release(typeinfo);
907 if(SUCCEEDED(hres)) {
908 TLIBATTR *attr;
910 hres = ITypeLib_GetLibAttr(typelib, &attr);
911 if(SUCCEEDED(hres)) {
912 *libid = attr->guid;
913 *major = attr->wMajorVerNum;
914 *minor = attr->wMinorVerNum;
915 ITypeLib_ReleaseTLibAttr(typelib, attr);
916 }else {
917 ITypeLib_Release(typelib);
920 if(FAILED(hres))
921 return hres;
923 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
924 if(SUCCEEDED(hres)) {
925 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
926 IProvideClassInfo2_Release(classinfo);
927 ITypeLib_Release(typelib);
928 return hres;
931 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
932 if(SUCCEEDED(hres)) {
933 CLSID clsid;
935 hres = IPersist_GetClassID(persist, &clsid);
936 if(SUCCEEDED(hres))
937 hres = get_default_source(typelib, &clsid, iid);
938 IPersist_Release(persist);
941 return hres;
944 #if _ATL_VER >= _ATL_VER90
946 /***********************************************************************
947 * AtlSetPerUserRegistration [atl100.67]
949 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
951 FIXME("stub: bEnable: %d\n", bEnable);
952 return E_NOTIMPL;
955 /***********************************************************************
956 * AtlGetPerUserRegistration [atl100.68]
958 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
960 FIXME("stub: returning false\n");
961 *pbEnabled = 0;
962 return S_OK;
965 #endif
967 /***********************************************************************
968 * AtlGetVersion [atl100.@]
970 DWORD WINAPI AtlGetVersion(void *pReserved)
972 TRACE("version %04x (%p)\n", _ATL_VER, pReserved);
973 return _ATL_VER;
976 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
978 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
980 switch(fdwReason) {
981 case DLL_PROCESS_ATTACH:
982 atl_instance = hinstDLL;
983 DisableThreadLibraryCalls(hinstDLL);
984 break;
985 case DLL_PROCESS_DETACH:
986 if (lpvReserved) break;
987 if(catreg)
988 ICatRegister_Release(catreg);
991 return TRUE;