windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / atl / atl.c
blob32e0c722f8bd59a2168be55de4e76f80aea110bd
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"
27 WINE_DEFAULT_DEBUG_CHANNEL(atl);
29 #define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer)
31 typedef unsigned char cpp_bool;
33 static ICatRegister *catreg;
35 /***********************************************************************
36 * AtlAdvise [atl100.@]
38 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
40 IConnectionPointContainer *container;
41 IConnectionPoint *cp;
42 HRESULT hres;
44 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
46 if(!pUnkCP)
47 return E_INVALIDARG;
49 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
50 if(FAILED(hres))
51 return hres;
53 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
54 IConnectionPointContainer_Release(container);
55 if(FAILED(hres))
56 return hres;
58 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
59 IConnectionPoint_Release(cp);
60 return hres;
63 /***********************************************************************
64 * AtlUnadvise [atl100.@]
66 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
68 IConnectionPointContainer *container;
69 IConnectionPoint *cp;
70 HRESULT hres;
72 TRACE("%p %p %ld\n", pUnkCP, iid, dw);
74 if(!pUnkCP)
75 return E_INVALIDARG;
77 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
78 if(FAILED(hres))
79 return hres;
81 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
82 IConnectionPointContainer_Release(container);
83 if(FAILED(hres))
84 return hres;
86 hres = IConnectionPoint_Unadvise(cp, dw);
87 IConnectionPoint_Release(cp);
88 return hres;
91 /***********************************************************************
92 * AtlFreeMarshalStream [atl100.@]
94 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
96 FIXME("%p\n", stm);
97 return S_OK;
100 /***********************************************************************
101 * AtlMarshalPtrInProc [atl100.@]
103 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
105 FIXME("%p %p %p\n", pUnk, iid, pstm);
106 return E_FAIL;
109 /***********************************************************************
110 * AtlUnmarshalPtr [atl100.@]
112 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
114 FIXME("%p %p %p\n", stm, iid, ppUnk);
115 return E_FAIL;
118 /***********************************************************************
119 * AtlCreateTargetDC [atl100.@]
121 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
123 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
124 DEVMODEW *devmode = NULL;
126 TRACE( "(%p, %p)\n", hdc, dv );
128 if (dv)
130 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
131 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
132 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
133 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
135 else
137 if (hdc) return hdc;
138 driver = L"display";
140 return CreateDCW( driver, device, port, devmode );
143 /***********************************************************************
144 * AtlHiMetricToPixel [atl100.@]
146 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
148 HDC dc = GetDC(NULL);
149 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
150 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
151 ReleaseDC( NULL, dc );
154 /***********************************************************************
155 * AtlPixelToHiMetric [atl100.@]
157 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
159 HDC dc = GetDC(NULL);
160 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
161 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
162 ReleaseDC( NULL, dc );
165 /***********************************************************************
166 * AtlComPtrAssign [atl100.@]
168 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
170 TRACE("(%p %p)\n", pp, p);
172 if (p) IUnknown_AddRef(p);
173 if (*pp) IUnknown_Release(*pp);
174 *pp = p;
175 return p;
178 /***********************************************************************
179 * AtlComQIPtrAssign [atl100.@]
181 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
183 IUnknown *new_p = NULL;
185 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
187 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
188 if (*pp) IUnknown_Release(*pp);
189 *pp = new_p;
190 return new_p;
193 /***********************************************************************
194 * AtlInternalQueryInterface [atl100.@]
196 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
198 int i = 0;
199 HRESULT rc = E_NOINTERFACE;
200 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
202 if (IsEqualGUID(iid,&IID_IUnknown))
204 TRACE("Returning IUnknown\n");
205 *ppvObject = ((LPSTR)this+pEntries[0].dw);
206 IUnknown_AddRef((IUnknown*)*ppvObject);
207 return S_OK;
210 while (pEntries[i].pFunc != 0)
212 TRACE("Trying entry %i (%s %Ix %p)\n",i,debugstr_guid(pEntries[i].piid),
213 pEntries[i].dw, pEntries[i].pFunc);
215 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
217 TRACE("MATCH\n");
218 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
220 TRACE("Offset\n");
221 *ppvObject = ((LPSTR)this+pEntries[i].dw);
222 IUnknown_AddRef((IUnknown*)*ppvObject);
223 return S_OK;
225 else
227 TRACE("Function\n");
228 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
229 if(rc==S_OK || pEntries[i].piid)
230 return rc;
233 i++;
235 TRACE("Done returning (0x%lx)\n",rc);
236 return rc;
239 /***********************************************************************
240 * AtlIPersistStreamInit_Load [atl100.@]
242 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
243 void *pThis, IUnknown *pUnk)
245 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
247 return S_OK;
250 /***********************************************************************
251 * AtlIPersistStreamInit_Save [atl100.@]
253 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
254 ATL_PROPMAP_ENTRY *pMap, void *pThis,
255 IUnknown *pUnk)
257 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
259 return S_OK;
262 /***********************************************************************
263 * AtlIPersistPropertyBag_Load [atl100.@]
265 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
266 ATL_PROPMAP_ENTRY *pMap, void *pThis,
267 IUnknown *pUnk)
269 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
271 return S_OK;
274 /***********************************************************************
275 * AtlIPersistPropertyBag_Save [atl100.@]
277 HRESULT WINAPI AtlIPersistPropertyBag_Save(LPPROPERTYBAG pPropBag, BOOL fClearDirty,
278 BOOL fSaveAll, ATL_PROPMAP_ENTRY *pMap,
279 void *pThis, IUnknown *pUnk)
281 FIXME("(%p, %d, %d, %p, %p, %p)\n", pPropBag, fClearDirty, fSaveAll, pMap, pThis, pUnk);
283 return S_OK;
286 /***********************************************************************
287 * AtlModuleAddTermFunc [atl100.@]
289 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
291 _ATL_TERMFUNC_ELEM *termfunc_elem;
293 TRACE("version %04x (%p %p %Id)\n", _ATL_VER, pM, pFunc, dw);
295 if (_ATL_VER > _ATL_VER_30 || pM->cbSize > ATLVer1Size) {
296 termfunc_elem = malloc(sizeof(*termfunc_elem));
297 termfunc_elem->pFunc = pFunc;
298 termfunc_elem->dw = dw;
299 termfunc_elem->pNext = pM->m_pTermFuncs;
301 pM->m_pTermFuncs = termfunc_elem;
304 return S_OK;
307 #if _ATL_VER > _ATL_VER_30
309 /***********************************************************************
310 * AtlCallTermFunc [atl100.@]
312 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
314 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
316 TRACE("(%p)\n", pM);
318 while(iter) {
319 iter->pFunc(iter->dw);
320 tmp = iter;
321 iter = iter->pNext;
322 free(tmp);
325 pM->m_pTermFuncs = NULL;
328 #endif
330 /***********************************************************************
331 * AtlLoadTypeLib [atl100.56]
333 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
334 BSTR *pbstrPath, ITypeLib **ppTypeLib)
336 size_t path_len, index_len;
337 ITypeLib *typelib = NULL;
338 WCHAR *path;
339 HRESULT hres;
341 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
343 index_len = lpszIndex ? lstrlenW(lpszIndex) : 0;
344 path = malloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(L".tlb"));
345 if(!path)
346 return E_OUTOFMEMORY;
348 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
349 if(!path_len) {
350 free(path);
351 return HRESULT_FROM_WIN32(GetLastError());
354 if(index_len)
355 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
357 hres = LoadTypeLib(path, &typelib);
358 if(FAILED(hres)) {
359 WCHAR *ptr;
361 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
362 if(*ptr != '.')
363 ptr = path+path_len;
364 lstrcpyW(ptr, L".tlb");
365 hres = LoadTypeLib(path, &typelib);
368 if(SUCCEEDED(hres)) {
369 *pbstrPath = SysAllocString(path);
370 if(!*pbstrPath) {
371 ITypeLib_Release(typelib);
372 hres = E_OUTOFMEMORY;
376 free(path);
377 if(FAILED(hres))
378 return hres;
380 *ppTypeLib = typelib;
381 return S_OK;
384 #if _ATL_VER <= _ATL_VER_80
386 /***********************************************************************
387 * AtlRegisterTypeLib [atl80.19]
389 HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index)
391 ITypeLib *typelib;
392 BSTR path;
393 HRESULT hres;
395 TRACE("(%p %s)\n", inst, debugstr_w(index));
397 hres = AtlLoadTypeLib(inst, index, &path, &typelib);
398 if(FAILED(hres))
399 return hres;
401 hres = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
402 ITypeLib_Release(typelib);
403 SysFreeString(path);
404 return hres;
407 #endif
409 #if _ATL_VER > _ATL_VER_30
411 /***********************************************************************
412 * AtlWinModuleInit [atl100.65]
414 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
416 TRACE("(%p)\n", winmod);
418 if(winmod->cbSize != sizeof(*winmod))
419 return E_INVALIDARG;
421 InitializeCriticalSection(&winmod->m_csWindowCreate);
422 winmod->m_pCreateWndList = NULL;
423 return S_OK;
426 /***********************************************************************
427 * AtlWinModuleAddCreateWndData [atl100.43]
429 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
431 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
433 pData->m_pThis = pvObject;
434 pData->m_dwThreadID = GetCurrentThreadId();
436 EnterCriticalSection(&pM->m_csWindowCreate);
437 pData->m_pNext = pM->m_pCreateWndList;
438 pM->m_pCreateWndList = pData;
439 LeaveCriticalSection(&pM->m_csWindowCreate);
442 /***********************************************************************
443 * AtlWinModuleExtractCreateWndData [atl100.44]
445 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
447 _AtlCreateWndData *iter, *prev = NULL;
448 DWORD thread_id;
450 TRACE("(%p)\n", winmod);
452 thread_id = GetCurrentThreadId();
454 EnterCriticalSection(&winmod->m_csWindowCreate);
456 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
457 prev = iter;
458 if(iter) {
459 if(prev)
460 prev->m_pNext = iter->m_pNext;
461 else
462 winmod->m_pCreateWndList = iter->m_pNext;
465 LeaveCriticalSection(&winmod->m_csWindowCreate);
467 return iter ? iter->m_pThis : NULL;
470 /***********************************************************************
471 * AtlComModuleGetClassObject [atl100.15]
473 #if _ATL_VER < _ATL_VER_110
474 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
476 _ATL_OBJMAP_ENTRY **iter;
477 HRESULT hres;
479 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
481 if(!pm)
482 return E_INVALIDARG;
484 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
485 if(*iter && IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
486 if(!(*iter)->pCF)
487 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
488 if((*iter)->pCF)
489 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
490 TRACE("returning %p (%08lx)\n", *ppv, hres);
491 return hres;
495 WARN("Class %s not found\n", debugstr_guid(rclsid));
496 return CLASS_E_CLASSNOTAVAILABLE;
498 #else
499 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
501 _ATL_OBJMAP_ENTRY_EX **iter;
502 HRESULT hres;
504 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
506 if(!pm)
507 return E_INVALIDARG;
509 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
510 if(*iter && IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
511 if(!(*iter)->pCache->pCF)
512 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCache->pCF);
513 if((*iter)->pCache->pCF)
514 hres = IUnknown_QueryInterface((*iter)->pCache->pCF, riid, ppv);
515 TRACE("returning %p (%08lx)\n", *ppv, hres);
516 return hres;
520 WARN("Class %s not found\n", debugstr_guid(rclsid));
521 return CLASS_E_CLASSNOTAVAILABLE;
523 #endif
525 /***********************************************************************
526 * AtlComModuleRegisterClassObjects [atl100.17]
528 #if _ATL_VER < _ATL_VER_110
529 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
531 _ATL_OBJMAP_ENTRY **iter;
532 IUnknown *unk;
533 HRESULT hres;
535 TRACE("(%p %lx %lx)\n", module, context, flags);
537 if(!module)
538 return E_INVALIDARG;
540 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
541 if(!(*iter) || !(*iter)->pfnGetClassObject)
542 continue;
544 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
545 if(FAILED(hres))
546 return hres;
548 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
549 IUnknown_Release(unk);
550 if(FAILED(hres))
551 return hres;
554 return S_OK;
556 #else
557 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
559 _ATL_OBJMAP_ENTRY_EX **iter;
560 IUnknown *unk;
561 HRESULT hres;
563 TRACE("(%p %lx %lx)\n", module, context, flags);
565 if(!module)
566 return E_INVALIDARG;
568 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
569 if(!(*iter) || !(*iter)->pfnGetClassObject)
570 continue;
572 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
573 if(FAILED(hres))
574 return hres;
576 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->pCache->dwRegister);
577 IUnknown_Release(unk);
578 if(FAILED(hres))
579 return hres;
582 return S_OK;
584 #endif
586 /***********************************************************************
587 * AtlComModuleRevokeClassObjects [atl100.20]
589 #if _ATL_VER < _ATL_VER_110
590 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
592 _ATL_OBJMAP_ENTRY **iter;
593 HRESULT hres;
595 TRACE("(%p)\n", module);
597 if(!module)
598 return E_INVALIDARG;
600 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
601 if(!(*iter))
602 continue;
604 hres = CoRevokeClassObject((*iter)->dwRegister);
605 if(FAILED(hres))
606 return hres;
609 return S_OK;
611 #else
612 HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module)
614 _ATL_OBJMAP_ENTRY_EX **iter;
615 HRESULT hres;
617 TRACE("(%p)\n", module);
619 if(!module)
620 return E_INVALIDARG;
622 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
623 if(!(*iter))
624 continue;
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] = L"CLSID\\", *ptr = reg_path+6;
786 ptr += StringFromGUID2(clsid, ptr, 64)-1;
787 *ptr++ = '\\';
789 lstrcpyW(ptr, L"Implemented Categories");
790 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
792 lstrcpyW(ptr, L"Required Categories");
793 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
796 return S_OK;
799 /***********************************************************************
800 * AtlWaitWithMessageLoop [atl100.24]
802 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
804 MSG msg;
805 DWORD res;
807 TRACE("(%p)\n", handle);
809 while(1) {
810 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
811 switch(res) {
812 case WAIT_OBJECT_0:
813 return TRUE;
814 case WAIT_OBJECT_0+1:
815 if(GetMessageW(&msg, NULL, 0, 0) < 0)
816 return FALSE;
818 TranslateMessage(&msg);
819 DispatchMessageW(&msg);
820 break;
821 default:
822 return FALSE;
827 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
829 ITypeInfo *typeinfo, *src_typeinfo = NULL;
830 TYPEATTR *attr;
831 int type_flags;
832 unsigned i;
833 HRESULT hres;
835 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
836 if(FAILED(hres))
837 return hres;
839 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
840 if(FAILED(hres)) {
841 ITypeInfo_Release(typeinfo);
842 return hres;
845 for(i=0; i < attr->cImplTypes; i++) {
846 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
847 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
848 HREFTYPE ref;
850 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
851 if(SUCCEEDED(hres))
852 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
853 break;
857 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
858 ITypeInfo_Release(typeinfo);
859 if(FAILED(hres))
860 return hres;
862 if(!src_typeinfo) {
863 *iid = IID_NULL;
864 return S_OK;
867 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
868 if(SUCCEEDED(hres)) {
869 *iid = attr->guid;
870 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
872 ITypeInfo_Release(src_typeinfo);
873 return hres;
876 /***********************************************************************
877 * AtlGetObjectSourceInterface [atl100.54]
879 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
881 IProvideClassInfo2 *classinfo;
882 ITypeInfo *typeinfo;
883 ITypeLib *typelib;
884 IPersist *persist;
885 IDispatch *disp;
886 HRESULT hres;
888 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
890 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
891 if(FAILED(hres))
892 return hres;
894 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
895 IDispatch_Release(disp);
896 if(FAILED(hres))
897 return hres;
899 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
900 ITypeInfo_Release(typeinfo);
901 if(SUCCEEDED(hres)) {
902 TLIBATTR *attr;
904 hres = ITypeLib_GetLibAttr(typelib, &attr);
905 if(SUCCEEDED(hres)) {
906 *libid = attr->guid;
907 *major = attr->wMajorVerNum;
908 *minor = attr->wMinorVerNum;
909 ITypeLib_ReleaseTLibAttr(typelib, attr);
910 }else {
911 ITypeLib_Release(typelib);
914 if(FAILED(hres))
915 return hres;
917 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
918 if(SUCCEEDED(hres)) {
919 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
920 IProvideClassInfo2_Release(classinfo);
921 ITypeLib_Release(typelib);
922 return hres;
925 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
926 if(SUCCEEDED(hres)) {
927 CLSID clsid;
929 hres = IPersist_GetClassID(persist, &clsid);
930 if(SUCCEEDED(hres))
931 hres = get_default_source(typelib, &clsid, iid);
932 IPersist_Release(persist);
935 return hres;
938 #if _ATL_VER >= _ATL_VER90
940 /***********************************************************************
941 * AtlSetPerUserRegistration [atl100.67]
943 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
945 FIXME("stub: bEnable: %d\n", bEnable);
946 return E_NOTIMPL;
949 /***********************************************************************
950 * AtlGetPerUserRegistration [atl100.68]
952 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
954 FIXME("stub: returning false\n");
955 *pbEnabled = 0;
956 return S_OK;
959 #endif
961 /***********************************************************************
962 * AtlGetVersion [atl100.@]
964 DWORD WINAPI AtlGetVersion(void *pReserved)
966 TRACE("version %04x (%p)\n", _ATL_VER, pReserved);
967 return _ATL_VER;
970 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
972 TRACE("(0x%p, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
974 switch(fdwReason) {
975 case DLL_PROCESS_ATTACH:
976 DisableThreadLibraryCalls(hinstDLL);
977 break;
978 case DLL_PROCESS_DETACH:
979 if (lpvReserved) break;
980 if(catreg)
981 ICatRegister_Release(catreg);
984 return TRUE;