strmbase: Introduce a helper to trace reference time.
[wine.git] / dlls / atl / atl.c
blob8829987c6ac22756420a3360937c0383503a538d
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"
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 ICatRegister *catreg;
38 /***********************************************************************
39 * AtlAdvise [atl100.@]
41 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
43 IConnectionPointContainer *container;
44 IConnectionPoint *cp;
45 HRESULT hres;
47 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
49 if(!pUnkCP)
50 return E_INVALIDARG;
52 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
53 if(FAILED(hres))
54 return hres;
56 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
57 IConnectionPointContainer_Release(container);
58 if(FAILED(hres))
59 return hres;
61 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
62 IConnectionPoint_Release(cp);
63 return hres;
66 /***********************************************************************
67 * AtlUnadvise [atl100.@]
69 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
71 IConnectionPointContainer *container;
72 IConnectionPoint *cp;
73 HRESULT hres;
75 TRACE("%p %p %d\n", pUnkCP, iid, dw);
77 if(!pUnkCP)
78 return E_INVALIDARG;
80 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
81 if(FAILED(hres))
82 return hres;
84 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
85 IConnectionPointContainer_Release(container);
86 if(FAILED(hres))
87 return hres;
89 hres = IConnectionPoint_Unadvise(cp, dw);
90 IConnectionPoint_Release(cp);
91 return hres;
94 /***********************************************************************
95 * AtlFreeMarshalStream [atl100.@]
97 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
99 FIXME("%p\n", stm);
100 return S_OK;
103 /***********************************************************************
104 * AtlMarshalPtrInProc [atl100.@]
106 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
108 FIXME("%p %p %p\n", pUnk, iid, pstm);
109 return E_FAIL;
112 /***********************************************************************
113 * AtlUnmarshalPtr [atl100.@]
115 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
117 FIXME("%p %p %p\n", stm, iid, ppUnk);
118 return E_FAIL;
121 /***********************************************************************
122 * AtlCreateTargetDC [atl100.@]
124 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
126 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
127 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
128 DEVMODEW *devmode = NULL;
130 TRACE( "(%p, %p)\n", hdc, dv );
132 if (dv)
134 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
135 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
136 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
137 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
139 else
141 if (hdc) return hdc;
142 driver = displayW;
144 return CreateDCW( driver, device, port, devmode );
147 /***********************************************************************
148 * AtlHiMetricToPixel [atl100.@]
150 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
152 HDC dc = GetDC(NULL);
153 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
154 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
155 ReleaseDC( NULL, dc );
158 /***********************************************************************
159 * AtlPixelToHiMetric [atl100.@]
161 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
163 HDC dc = GetDC(NULL);
164 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
165 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
166 ReleaseDC( NULL, dc );
169 /***********************************************************************
170 * AtlComPtrAssign [atl100.@]
172 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
174 TRACE("(%p %p)\n", pp, p);
176 if (p) IUnknown_AddRef(p);
177 if (*pp) IUnknown_Release(*pp);
178 *pp = p;
179 return p;
182 /***********************************************************************
183 * AtlComQIPtrAssign [atl100.@]
185 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
187 IUnknown *new_p = NULL;
189 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
191 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
192 if (*pp) IUnknown_Release(*pp);
193 *pp = new_p;
194 return new_p;
197 /***********************************************************************
198 * AtlInternalQueryInterface [atl100.@]
200 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
202 int i = 0;
203 HRESULT rc = E_NOINTERFACE;
204 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
206 if (IsEqualGUID(iid,&IID_IUnknown))
208 TRACE("Returning IUnknown\n");
209 *ppvObject = ((LPSTR)this+pEntries[0].dw);
210 IUnknown_AddRef((IUnknown*)*ppvObject);
211 return S_OK;
214 while (pEntries[i].pFunc != 0)
216 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
217 pEntries[i].dw, pEntries[i].pFunc);
219 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
221 TRACE("MATCH\n");
222 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
224 TRACE("Offset\n");
225 *ppvObject = ((LPSTR)this+pEntries[i].dw);
226 IUnknown_AddRef((IUnknown*)*ppvObject);
227 return S_OK;
229 else
231 TRACE("Function\n");
232 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
233 if(rc==S_OK || pEntries[i].piid)
234 return rc;
237 i++;
239 TRACE("Done returning (0x%x)\n",rc);
240 return rc;
243 /***********************************************************************
244 * AtlIPersistStreamInit_Load [atl100.@]
246 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
247 void *pThis, IUnknown *pUnk)
249 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
251 return S_OK;
254 /***********************************************************************
255 * AtlIPersistStreamInit_Save [atl100.@]
257 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
258 ATL_PROPMAP_ENTRY *pMap, void *pThis,
259 IUnknown *pUnk)
261 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
263 return S_OK;
266 /***********************************************************************
267 * AtlIPersistPropertyBag_Load [atl100.@]
269 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
270 ATL_PROPMAP_ENTRY *pMap, void *pThis,
271 IUnknown *pUnk)
273 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
275 return S_OK;
278 /***********************************************************************
279 * AtlIPersistPropertyBag_Save [atl100.@]
281 HRESULT WINAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty,
282 BOOL fSaveAll, ATL_PROPMAP_ENTRY *pMap,
283 void *pThis, IUnknown *pUnk)
285 FIXME("(%p, %d, %d, %p, %p, %p)\n", pPropBag, fClearDirty, fSaveAll, pMap, pThis, pUnk);
287 return S_OK;
290 /***********************************************************************
291 * AtlModuleAddTermFunc [atl100.@]
293 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
295 _ATL_TERMFUNC_ELEM *termfunc_elem;
297 TRACE("version %04x (%p %p %ld)\n", _ATL_VER, pM, pFunc, dw);
299 if (_ATL_VER > _ATL_VER_30 || pM->cbSize > ATLVer1Size) {
300 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
301 termfunc_elem->pFunc = pFunc;
302 termfunc_elem->dw = dw;
303 termfunc_elem->pNext = pM->m_pTermFuncs;
305 pM->m_pTermFuncs = termfunc_elem;
308 return S_OK;
311 #if _ATL_VER > _ATL_VER_30
313 /***********************************************************************
314 * AtlCallTermFunc [atl100.@]
316 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
318 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
320 TRACE("(%p)\n", pM);
322 while(iter) {
323 iter->pFunc(iter->dw);
324 tmp = iter;
325 iter = iter->pNext;
326 HeapFree(GetProcessHeap(), 0, tmp);
329 pM->m_pTermFuncs = NULL;
332 #endif
334 /***********************************************************************
335 * AtlLoadTypeLib [atl100.56]
337 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
338 BSTR *pbstrPath, ITypeLib **ppTypeLib)
340 size_t path_len, index_len;
341 ITypeLib *typelib = NULL;
342 WCHAR *path;
343 HRESULT hres;
345 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
347 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
349 index_len = lpszIndex ? lstrlenW(lpszIndex) : 0;
350 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
351 if(!path)
352 return E_OUTOFMEMORY;
354 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
355 if(!path_len) {
356 heap_free(path);
357 return HRESULT_FROM_WIN32(GetLastError());
360 if(index_len)
361 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
363 hres = LoadTypeLib(path, &typelib);
364 if(FAILED(hres)) {
365 WCHAR *ptr;
367 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
368 if(*ptr != '.')
369 ptr = path+path_len;
370 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
371 hres = LoadTypeLib(path, &typelib);
374 if(SUCCEEDED(hres)) {
375 *pbstrPath = SysAllocString(path);
376 if(!*pbstrPath) {
377 ITypeLib_Release(typelib);
378 hres = E_OUTOFMEMORY;
382 heap_free(path);
383 if(FAILED(hres))
384 return hres;
386 *ppTypeLib = typelib;
387 return S_OK;
390 #if _ATL_VER <= _ATL_VER_80
392 /***********************************************************************
393 * AtlRegisterTypeLib [atl80.19]
395 HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index)
397 ITypeLib *typelib;
398 BSTR path;
399 HRESULT hres;
401 TRACE("(%p %s)\n", inst, debugstr_w(index));
403 hres = AtlLoadTypeLib(inst, index, &path, &typelib);
404 if(FAILED(hres))
405 return hres;
407 hres = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
408 ITypeLib_Release(typelib);
409 SysFreeString(path);
410 return hres;
413 #endif
415 #if _ATL_VER > _ATL_VER_30
417 /***********************************************************************
418 * AtlWinModuleInit [atl100.65]
420 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
422 TRACE("(%p)\n", winmod);
424 if(winmod->cbSize != sizeof(*winmod))
425 return E_INVALIDARG;
427 InitializeCriticalSection(&winmod->m_csWindowCreate);
428 winmod->m_pCreateWndList = NULL;
429 return S_OK;
432 /***********************************************************************
433 * AtlWinModuleAddCreateWndData [atl100.43]
435 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
437 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
439 pData->m_pThis = pvObject;
440 pData->m_dwThreadID = GetCurrentThreadId();
442 EnterCriticalSection(&pM->m_csWindowCreate);
443 pData->m_pNext = pM->m_pCreateWndList;
444 pM->m_pCreateWndList = pData;
445 LeaveCriticalSection(&pM->m_csWindowCreate);
448 /***********************************************************************
449 * AtlWinModuleExtractCreateWndData [atl100.44]
451 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
453 _AtlCreateWndData *iter, *prev = NULL;
454 DWORD thread_id;
456 TRACE("(%p)\n", winmod);
458 thread_id = GetCurrentThreadId();
460 EnterCriticalSection(&winmod->m_csWindowCreate);
462 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
463 prev = iter;
464 if(iter) {
465 if(prev)
466 prev->m_pNext = iter->m_pNext;
467 else
468 winmod->m_pCreateWndList = iter->m_pNext;
471 LeaveCriticalSection(&winmod->m_csWindowCreate);
473 return iter ? iter->m_pThis : NULL;
476 /***********************************************************************
477 * AtlComModuleGetClassObject [atl100.15]
479 #if _ATL_VER < _ATL_VER_110
480 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
482 _ATL_OBJMAP_ENTRY **iter;
483 HRESULT hres;
485 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
487 if(!pm)
488 return E_INVALIDARG;
490 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
491 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
492 if(!(*iter)->pCF)
493 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
494 if((*iter)->pCF)
495 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
496 TRACE("returning %p (%08x)\n", *ppv, hres);
497 return hres;
501 WARN("Class %s not found\n", debugstr_guid(rclsid));
502 return CLASS_E_CLASSNOTAVAILABLE;
504 #else
505 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
507 _ATL_OBJMAP_ENTRY_EX **iter;
508 HRESULT hres;
510 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
512 if(!pm)
513 return E_INVALIDARG;
515 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
516 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
517 if(!(*iter)->pCache->pCF)
518 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCache->pCF);
519 if((*iter)->pCache->pCF)
520 hres = IUnknown_QueryInterface((*iter)->pCache->pCF, riid, ppv);
521 TRACE("returning %p (%08x)\n", *ppv, hres);
522 return hres;
526 WARN("Class %s not found\n", debugstr_guid(rclsid));
527 return CLASS_E_CLASSNOTAVAILABLE;
529 #endif
531 /***********************************************************************
532 * AtlComModuleRegisterClassObjects [atl100.17]
534 #if _ATL_VER < _ATL_VER_110
535 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
537 _ATL_OBJMAP_ENTRY **iter;
538 IUnknown *unk;
539 HRESULT hres;
541 TRACE("(%p %x %x)\n", module, context, flags);
543 if(!module)
544 return E_INVALIDARG;
546 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
547 if(!(*iter)->pfnGetClassObject)
548 continue;
550 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
551 if(FAILED(hres))
552 return hres;
554 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
555 IUnknown_Release(unk);
556 if(FAILED(hres))
557 return hres;
560 return S_OK;
562 #else
563 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
565 _ATL_OBJMAP_ENTRY_EX **iter;
566 IUnknown *unk;
567 HRESULT hres;
569 TRACE("(%p %x %x)\n", module, context, flags);
571 if(!module)
572 return E_INVALIDARG;
574 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
575 if(!(*iter)->pfnGetClassObject)
576 continue;
578 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
579 if(FAILED(hres))
580 return hres;
582 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->pCache->dwRegister);
583 IUnknown_Release(unk);
584 if(FAILED(hres))
585 return hres;
588 return S_OK;
590 #endif
592 /***********************************************************************
593 * AtlComModuleRevokeClassObjects [atl100.20]
595 #if _ATL_VER < _ATL_VER_110
596 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
598 _ATL_OBJMAP_ENTRY **iter;
599 HRESULT hres;
601 TRACE("(%p)\n", module);
603 if(!module)
604 return E_INVALIDARG;
606 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
607 hres = CoRevokeClassObject((*iter)->dwRegister);
608 if(FAILED(hres))
609 return hres;
612 return S_OK;
614 #else
615 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
617 _ATL_OBJMAP_ENTRY_EX **iter;
618 HRESULT hres;
620 TRACE("(%p)\n", module);
622 if(!module)
623 return E_INVALIDARG;
625 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
626 hres = CoRevokeClassObject((*iter)->pCache->dwRegister);
627 if(FAILED(hres))
628 return hres;
631 return S_OK;
633 #endif
635 /***********************************************************************
636 * AtlComModuleUnregisterServer [atl100.22]
638 #if _ATL_VER < _ATL_VER_110
639 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
641 const struct _ATL_CATMAP_ENTRY *catmap;
642 _ATL_OBJMAP_ENTRY **iter;
643 HRESULT hres;
645 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
647 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
648 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
649 continue;
651 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
653 catmap = (*iter)->pfnGetCategoryMap();
654 if(catmap) {
655 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
656 if(FAILED(hres))
657 return hres;
660 hres = (*iter)->pfnUpdateRegistry(FALSE);
661 if(FAILED(hres))
662 return hres;
665 if(bRegTypeLib) {
666 ITypeLib *typelib;
667 TLIBATTR *attr;
668 BSTR path;
670 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
671 if(FAILED(hres))
672 return hres;
674 SysFreeString(path);
675 hres = ITypeLib_GetLibAttr(typelib, &attr);
676 if(SUCCEEDED(hres)) {
677 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
678 ITypeLib_ReleaseTLibAttr(typelib, attr);
680 ITypeLib_Release(typelib);
681 if(FAILED(hres))
682 return hres;
685 return S_OK;
687 #else
688 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
690 const struct _ATL_CATMAP_ENTRY *catmap;
691 _ATL_OBJMAP_ENTRY_EX **iter;
692 HRESULT hres;
694 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
696 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
697 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
698 continue;
700 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
702 catmap = (*iter)->pfnGetCategoryMap();
703 if(catmap) {
704 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
705 if(FAILED(hres))
706 return hres;
709 hres = (*iter)->pfnUpdateRegistry(FALSE);
710 if(FAILED(hres))
711 return hres;
714 if(bRegTypeLib) {
715 ITypeLib *typelib;
716 TLIBATTR *attr;
717 BSTR path;
719 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
720 if(FAILED(hres))
721 return hres;
723 SysFreeString(path);
724 hres = ITypeLib_GetLibAttr(typelib, &attr);
725 if(SUCCEEDED(hres)) {
726 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
727 ITypeLib_ReleaseTLibAttr(typelib, attr);
729 ITypeLib_Release(typelib);
730 if(FAILED(hres))
731 return hres;
734 return S_OK;
736 #endif
738 #endif
740 /***********************************************************************
741 * AtlRegisterClassCategoriesHelper [atl100.49]
743 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
745 const struct _ATL_CATMAP_ENTRY *iter;
746 HRESULT hres;
748 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
750 if(!catmap)
751 return S_OK;
753 if(!catreg) {
754 ICatRegister *new_catreg;
756 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
757 &IID_ICatRegister, (void**)&new_catreg);
758 if(FAILED(hres))
759 return hres;
761 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
762 ICatRegister_Release(new_catreg);
765 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
766 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
768 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
769 if(reg)
770 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
771 else
772 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
773 }else {
774 if(reg)
775 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
776 else
777 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
779 if(FAILED(hres))
780 return hres;
783 if(!reg) {
784 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
786 static const WCHAR implemented_catW[] =
787 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
788 static const WCHAR required_catW[] =
789 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
791 ptr += StringFromGUID2(clsid, ptr, 64)-1;
792 *ptr++ = '\\';
794 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
797 memcpy(ptr, required_catW, sizeof(required_catW));
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
801 return S_OK;
804 /***********************************************************************
805 * AtlWaitWithMessageLoop [atl100.24]
807 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
809 MSG msg;
810 DWORD res;
812 TRACE("(%p)\n", handle);
814 while(1) {
815 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
816 switch(res) {
817 case WAIT_OBJECT_0:
818 return TRUE;
819 case WAIT_OBJECT_0+1:
820 if(GetMessageW(&msg, NULL, 0, 0) < 0)
821 return FALSE;
823 TranslateMessage(&msg);
824 DispatchMessageW(&msg);
825 break;
826 default:
827 return FALSE;
832 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
834 ITypeInfo *typeinfo, *src_typeinfo = NULL;
835 TYPEATTR *attr;
836 int type_flags;
837 unsigned i;
838 HRESULT hres;
840 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
841 if(FAILED(hres))
842 return hres;
844 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
845 if(FAILED(hres)) {
846 ITypeInfo_Release(typeinfo);
847 return hres;
850 for(i=0; i < attr->cImplTypes; i++) {
851 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
852 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
853 HREFTYPE ref;
855 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
856 if(SUCCEEDED(hres))
857 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
858 break;
862 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
863 ITypeInfo_Release(typeinfo);
864 if(FAILED(hres))
865 return hres;
867 if(!src_typeinfo) {
868 *iid = IID_NULL;
869 return S_OK;
872 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
873 if(SUCCEEDED(hres)) {
874 *iid = attr->guid;
875 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
877 ITypeInfo_Release(src_typeinfo);
878 return hres;
881 /***********************************************************************
882 * AtlGetObjectSourceInterface [atl100.54]
884 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
886 IProvideClassInfo2 *classinfo;
887 ITypeInfo *typeinfo;
888 ITypeLib *typelib;
889 IPersist *persist;
890 IDispatch *disp;
891 HRESULT hres;
893 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
895 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
896 if(FAILED(hres))
897 return hres;
899 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
900 IDispatch_Release(disp);
901 if(FAILED(hres))
902 return hres;
904 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
905 ITypeInfo_Release(typeinfo);
906 if(SUCCEEDED(hres)) {
907 TLIBATTR *attr;
909 hres = ITypeLib_GetLibAttr(typelib, &attr);
910 if(SUCCEEDED(hres)) {
911 *libid = attr->guid;
912 *major = attr->wMajorVerNum;
913 *minor = attr->wMinorVerNum;
914 ITypeLib_ReleaseTLibAttr(typelib, attr);
915 }else {
916 ITypeLib_Release(typelib);
919 if(FAILED(hres))
920 return hres;
922 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
923 if(SUCCEEDED(hres)) {
924 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
925 IProvideClassInfo2_Release(classinfo);
926 ITypeLib_Release(typelib);
927 return hres;
930 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
931 if(SUCCEEDED(hres)) {
932 CLSID clsid;
934 hres = IPersist_GetClassID(persist, &clsid);
935 if(SUCCEEDED(hres))
936 hres = get_default_source(typelib, &clsid, iid);
937 IPersist_Release(persist);
940 return hres;
943 #if _ATL_VER >= _ATL_VER90
945 /***********************************************************************
946 * AtlSetPerUserRegistration [atl100.67]
948 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
950 FIXME("stub: bEnable: %d\n", bEnable);
951 return E_NOTIMPL;
954 /***********************************************************************
955 * AtlGetPerUserRegistration [atl100.68]
957 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
959 FIXME("stub: returning false\n");
960 *pbEnabled = 0;
961 return S_OK;
964 #endif
966 /***********************************************************************
967 * AtlGetVersion [atl100.@]
969 DWORD WINAPI AtlGetVersion(void *pReserved)
971 TRACE("version %04x (%p)\n", _ATL_VER, pReserved);
972 return _ATL_VER;
975 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
977 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
979 switch(fdwReason) {
980 case DLL_PROCESS_ATTACH:
981 atl_instance = hinstDLL;
982 DisableThreadLibraryCalls(hinstDLL);
983 break;
984 case DLL_PROCESS_DETACH:
985 if (lpvReserved) break;
986 if(catreg)
987 ICatRegister_Release(catreg);
990 return TRUE;