atl100: Fixed AtlAdvise and AtlUnadvise crashing with NULL pUnkCP.
[wine.git] / dlls / atl100 / atl.c
blob0aae80b944dedfe0b450d1c57e1a26d4d550cfe9
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"
24 #include "wine/debug.h"
25 #include "wine/unicode.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(atl100);
29 typedef unsigned char cpp_bool;
31 static inline void *heap_alloc(size_t len)
33 return HeapAlloc(GetProcessHeap(), 0, len);
36 static inline BOOL heap_free(void *mem)
38 return HeapFree(GetProcessHeap(), 0, mem);
41 static ICatRegister *catreg;
43 /***********************************************************************
44 * AtlAdvise [atl100.@]
46 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
48 IConnectionPointContainer *container;
49 IConnectionPoint *cp;
50 HRESULT hres;
52 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
54 if(!pUnkCP)
55 return E_INVALIDARG;
57 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
58 if(FAILED(hres))
59 return hres;
61 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
62 IConnectionPointContainer_Release(container);
63 if(FAILED(hres))
64 return hres;
66 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
67 IConnectionPoint_Release(cp);
68 return hres;
71 /***********************************************************************
72 * AtlUnadvise [atl100.@]
74 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
76 IConnectionPointContainer *container;
77 IConnectionPoint *cp;
78 HRESULT hres;
80 TRACE("%p %p %d\n", pUnkCP, iid, dw);
82 if(!pUnkCP)
83 return E_INVALIDARG;
85 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
86 if(FAILED(hres))
87 return hres;
89 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
90 IConnectionPointContainer_Release(container);
91 if(FAILED(hres))
92 return hres;
94 hres = IConnectionPoint_Unadvise(cp, dw);
95 IConnectionPoint_Release(cp);
96 return hres;
99 /***********************************************************************
100 * AtlFreeMarshalStream [atl100.@]
102 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
104 FIXME("%p\n", stm);
105 return S_OK;
108 /***********************************************************************
109 * AtlMarshalPtrInProc [atl100.@]
111 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
113 FIXME("%p %p %p\n", pUnk, iid, pstm);
114 return E_FAIL;
117 /***********************************************************************
118 * AtlUnmarshalPtr [atl100.@]
120 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
122 FIXME("%p %p %p\n", stm, iid, ppUnk);
123 return E_FAIL;
126 /***********************************************************************
127 * AtlCreateTargetDC [atl100.@]
129 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
131 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
132 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
133 DEVMODEW *devmode = NULL;
135 TRACE( "(%p, %p)\n", hdc, dv );
137 if (dv)
139 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
140 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
141 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
142 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
144 else
146 if (hdc) return hdc;
147 driver = displayW;
149 return CreateDCW( driver, device, port, devmode );
152 /***********************************************************************
153 * AtlHiMetricToPixel [atl100.@]
155 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
157 HDC dc = GetDC(NULL);
158 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
159 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
160 ReleaseDC( NULL, dc );
163 /***********************************************************************
164 * AtlPixelToHiMetric [atl100.@]
166 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
168 HDC dc = GetDC(NULL);
169 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
170 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
171 ReleaseDC( NULL, dc );
174 /***********************************************************************
175 * AtlComPtrAssign [atl100.@]
177 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
179 TRACE("(%p %p)\n", pp, p);
181 if (p) IUnknown_AddRef(p);
182 if (*pp) IUnknown_Release(*pp);
183 *pp = p;
184 return p;
187 /***********************************************************************
188 * AtlComQIPtrAssign [atl100.@]
190 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
192 IUnknown *new_p = NULL;
194 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
196 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
197 if (*pp) IUnknown_Release(*pp);
198 *pp = new_p;
199 return new_p;
202 /***********************************************************************
203 * AtlInternalQueryInterface [atl100.@]
205 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
207 int i = 0;
208 HRESULT rc = E_NOINTERFACE;
209 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
211 if (IsEqualGUID(iid,&IID_IUnknown))
213 TRACE("Returning IUnknown\n");
214 *ppvObject = ((LPSTR)this+pEntries[0].dw);
215 IUnknown_AddRef((IUnknown*)*ppvObject);
216 return S_OK;
219 while (pEntries[i].pFunc != 0)
221 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
222 pEntries[i].dw, pEntries[i].pFunc);
224 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
226 TRACE("MATCH\n");
227 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
229 TRACE("Offset\n");
230 *ppvObject = ((LPSTR)this+pEntries[i].dw);
231 IUnknown_AddRef((IUnknown*)*ppvObject);
232 return S_OK;
234 else
236 TRACE("Function\n");
237 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
238 if(rc==S_OK || pEntries[i].piid)
239 return rc;
242 i++;
244 TRACE("Done returning (0x%x)\n",rc);
245 return rc;
248 /* FIXME: should be in a header file */
249 typedef struct ATL_PROPMAP_ENTRY
251 LPCOLESTR szDesc;
252 DISPID dispid;
253 const CLSID* pclsidPropPage;
254 const IID* piidDispatch;
255 DWORD dwOffsetData;
256 DWORD dwSizeData;
257 VARTYPE vt;
258 } ATL_PROPMAP_ENTRY;
260 /***********************************************************************
261 * AtlIPersistStreamInit_Load [atl100.@]
263 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
264 void *pThis, IUnknown *pUnk)
266 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
268 return S_OK;
271 /***********************************************************************
272 * AtlIPersistStreamInit_Save [atl100.@]
274 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
275 ATL_PROPMAP_ENTRY *pMap, void *pThis,
276 IUnknown *pUnk)
278 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
280 return S_OK;
283 /***********************************************************************
284 * AtlIPersistPropertyBag_Load [atl100.@]
286 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
287 ATL_PROPMAP_ENTRY *pMap, void *pThis,
288 IUnknown *pUnk)
290 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
292 return S_OK;
295 /***********************************************************************
296 * AtlModuleAddTermFunc [atl100.@]
298 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
300 _ATL_TERMFUNC_ELEM *termfunc_elem;
302 TRACE("(%p %p %ld)\n", pM, pFunc, dw);
304 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
305 termfunc_elem->pFunc = pFunc;
306 termfunc_elem->dw = dw;
307 termfunc_elem->pNext = pM->m_pTermFuncs;
309 pM->m_pTermFuncs = termfunc_elem;
311 return S_OK;
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 /***********************************************************************
334 * AtlLoadTypeLib [atl100.56]
336 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
337 BSTR *pbstrPath, ITypeLib **ppTypeLib)
339 size_t path_len, index_len;
340 ITypeLib *typelib = NULL;
341 WCHAR *path;
342 HRESULT hres;
344 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
346 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
348 index_len = lpszIndex ? strlenW(lpszIndex) : 0;
349 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
350 if(!path)
351 return E_OUTOFMEMORY;
353 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
354 if(!path_len) {
355 heap_free(path);
356 return HRESULT_FROM_WIN32(GetLastError());
359 if(index_len)
360 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
362 hres = LoadTypeLib(path, &typelib);
363 if(FAILED(hres)) {
364 WCHAR *ptr;
366 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
367 if(*ptr != '.')
368 ptr = path+path_len;
369 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
370 hres = LoadTypeLib(path, &typelib);
373 if(SUCCEEDED(hres)) {
374 *pbstrPath = SysAllocString(path);
375 if(!*pbstrPath) {
376 ITypeLib_Release(typelib);
377 hres = E_OUTOFMEMORY;
381 heap_free(path);
382 if(FAILED(hres))
383 return hres;
385 *ppTypeLib = typelib;
386 return S_OK;
389 /***********************************************************************
390 * AtlWinModuleInit [atl100.65]
392 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
394 TRACE("(%p\n", winmod);
396 if(winmod->cbSize != sizeof(*winmod))
397 return E_INVALIDARG;
399 InitializeCriticalSection(&winmod->m_csWindowCreate);
400 winmod->m_pCreateWndList = NULL;
401 return S_OK;
404 /***********************************************************************
405 * AtlWinModuleAddCreateWndData [atl100.43]
407 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
409 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
411 pData->m_pThis = pvObject;
412 pData->m_dwThreadID = GetCurrentThreadId();
414 EnterCriticalSection(&pM->m_csWindowCreate);
415 pData->m_pNext = pM->m_pCreateWndList;
416 pM->m_pCreateWndList = pData;
417 LeaveCriticalSection(&pM->m_csWindowCreate);
420 /***********************************************************************
421 * AtlWinModuleExtractCreateWndData [atl100.44]
423 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
425 _AtlCreateWndData *iter, *prev = NULL;
426 DWORD thread_id;
428 TRACE("(%p)\n", winmod);
430 thread_id = GetCurrentThreadId();
432 EnterCriticalSection(&winmod->m_csWindowCreate);
434 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
435 prev = iter;
436 if(iter) {
437 if(prev)
438 prev->m_pNext = iter->m_pNext;
439 else
440 winmod->m_pCreateWndList = iter->m_pNext;
443 LeaveCriticalSection(&winmod->m_csWindowCreate);
445 return iter ? iter->m_pThis : NULL;
448 /***********************************************************************
449 * AtlComModuleGetClassObject [atl100.15]
451 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
453 _ATL_OBJMAP_ENTRY **iter;
454 HRESULT hres;
456 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
458 if(!pm)
459 return E_INVALIDARG;
461 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
462 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
463 if(!(*iter)->pCF)
464 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
465 if((*iter)->pCF)
466 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
467 TRACE("returning %p (%08x)\n", *ppv, hres);
468 return hres;
472 WARN("Class %s not found\n", debugstr_guid(rclsid));
473 return CLASS_E_CLASSNOTAVAILABLE;
476 /***********************************************************************
477 * AtlComModuleRegisterClassObjects [atl100.17]
479 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
481 _ATL_OBJMAP_ENTRY **iter;
482 IUnknown *unk;
483 HRESULT hres;
485 TRACE("(%p %x %x)\n", module, context, flags);
487 if(!module)
488 return E_INVALIDARG;
490 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
491 if(!(*iter)->pfnGetClassObject)
492 continue;
494 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
495 if(FAILED(hres))
496 return hres;
498 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
499 IUnknown_Release(unk);
500 if(FAILED(hres))
501 return hres;
504 return S_OK;
508 /***********************************************************************
509 * AtlComModuleUnregisterServer [atl100.22]
511 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
513 const struct _ATL_CATMAP_ENTRY *catmap;
514 _ATL_OBJMAP_ENTRY **iter;
515 HRESULT hres;
517 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
519 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
520 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
521 continue;
523 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
525 catmap = (*iter)->pfnGetCategoryMap();
526 if(catmap) {
527 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
528 if(FAILED(hres))
529 return hres;
532 hres = (*iter)->pfnUpdateRegistry(FALSE);
533 if(FAILED(hres))
534 return hres;
537 if(bRegTypeLib) {
538 ITypeLib *typelib;
539 TLIBATTR *attr;
540 BSTR path;
542 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
543 if(FAILED(hres))
544 return hres;
546 SysFreeString(path);
547 hres = ITypeLib_GetLibAttr(typelib, &attr);
548 if(SUCCEEDED(hres)) {
549 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
550 ITypeLib_ReleaseTLibAttr(typelib, attr);
552 ITypeLib_Release(typelib);
553 if(FAILED(hres))
554 return hres;
557 return S_OK;
560 /***********************************************************************
561 * AtlRegisterClassCategoriesHelper [atl100.49]
563 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
565 const struct _ATL_CATMAP_ENTRY *iter;
566 HRESULT hres;
568 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
570 if(!catmap)
571 return S_OK;
573 if(!catreg) {
574 ICatRegister *new_catreg;
576 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
577 &IID_ICatRegister, (void**)&new_catreg);
578 if(FAILED(hres))
579 return hres;
581 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
582 ICatRegister_Release(new_catreg);
585 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
586 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
588 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
589 if(reg)
590 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
591 else
592 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
593 }else {
594 if(reg)
595 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
596 else
597 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
599 if(FAILED(hres))
600 return hres;
603 if(!reg) {
604 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
606 static const WCHAR implemented_catW[] =
607 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
608 static const WCHAR required_catW[] =
609 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
611 ptr += StringFromGUID2(clsid, ptr, 64)-1;
612 *ptr++ = '\\';
614 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
615 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
617 memcpy(ptr, required_catW, sizeof(required_catW));
618 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
621 return S_OK;
624 /***********************************************************************
625 * AtlWaitWithMessageLoop [atl100.24]
627 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
629 MSG msg;
630 DWORD res;
632 TRACE("(%p)\n", handle);
634 while(1) {
635 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
636 switch(res) {
637 case WAIT_OBJECT_0:
638 return TRUE;
639 case WAIT_OBJECT_0+1:
640 if(GetMessageW(&msg, NULL, 0, 0) < 0)
641 return FALSE;
643 TranslateMessage(&msg);
644 DispatchMessageW(&msg);
645 break;
646 default:
647 return FALSE;
652 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
654 ITypeInfo *typeinfo, *src_typeinfo = NULL;
655 TYPEATTR *attr;
656 int type_flags;
657 unsigned i;
658 HRESULT hres;
660 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
661 if(FAILED(hres))
662 return hres;
664 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
665 if(FAILED(hres)) {
666 ITypeInfo_Release(typeinfo);
667 return hres;
670 for(i=0; i < attr->cImplTypes; i++) {
671 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
672 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
673 HREFTYPE ref;
675 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
676 if(SUCCEEDED(hres))
677 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
678 break;
682 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
683 ITypeInfo_Release(typeinfo);
684 if(FAILED(hres))
685 return hres;
687 if(!src_typeinfo) {
688 *iid = IID_NULL;
689 return S_OK;
692 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
693 if(SUCCEEDED(hres)) {
694 *iid = attr->guid;
695 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
697 ITypeInfo_Release(src_typeinfo);
698 return hres;
701 /***********************************************************************
702 * AtlGetObjectSourceInterface [atl100.54]
704 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
706 IProvideClassInfo2 *classinfo;
707 ITypeInfo *typeinfo;
708 ITypeLib *typelib;
709 IPersist *persist;
710 IDispatch *disp;
711 HRESULT hres;
713 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
715 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
716 if(FAILED(hres))
717 return hres;
719 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
720 IDispatch_Release(disp);
721 if(FAILED(hres))
722 return hres;
724 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
725 ITypeInfo_Release(typeinfo);
726 if(SUCCEEDED(hres)) {
727 TLIBATTR *attr;
729 hres = ITypeLib_GetLibAttr(typelib, &attr);
730 if(SUCCEEDED(hres)) {
731 *libid = attr->guid;
732 *major = attr->wMajorVerNum;
733 *minor = attr->wMinorVerNum;
734 ITypeLib_ReleaseTLibAttr(typelib, attr);
735 }else {
736 ITypeLib_Release(typelib);
739 if(FAILED(hres))
740 return hres;
742 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
743 if(SUCCEEDED(hres)) {
744 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
745 IProvideClassInfo2_Release(classinfo);
746 ITypeLib_Release(typelib);
747 return hres;
750 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
751 if(SUCCEEDED(hres)) {
752 CLSID clsid;
754 hres = IPersist_GetClassID(persist, &clsid);
755 if(SUCCEEDED(hres))
756 hres = get_default_source(typelib, &clsid, iid);
757 IPersist_Release(persist);
760 return hres;
763 /***********************************************************************
764 * AtlSetPerUserRegistration [atl100.67]
766 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
768 FIXME("stub: bEnable: %d\n", bEnable);
769 return E_NOTIMPL;
772 /***********************************************************************
773 * AtlGetPerUserRegistration [atl100.68]
775 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
777 FIXME("stub: returning false\n");
778 *pbEnabled = 0;
779 return S_OK;
782 /***********************************************************************
783 * AtlGetVersion [atl100.@]
785 DWORD WINAPI AtlGetVersion(void *pReserved)
787 return _ATL_VER;
790 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
792 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
794 switch(fdwReason) {
795 case DLL_PROCESS_ATTACH:
796 DisableThreadLibraryCalls(hinstDLL);
797 break;
798 case DLL_PROCESS_DETACH:
799 if (lpvReserved) break;
800 if(catreg)
801 ICatRegister_Release(catreg);
804 return TRUE;