Sync to trunk revision 61757.
[reactos.git] / dll / win32 / atl100 / atl.c
1 /*
2 * Copyright 2012 Stefan Leichter
3 * Copyright 2012 Jacek Caban for CodeWeavers
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include "precomp.h"
21
22 #include <wingdi.h>
23
24 WINE_DEFAULT_DEBUG_CHANNEL(atl100);
25
26 typedef unsigned char cpp_bool;
27
28 static inline void *heap_alloc(size_t len)
29 {
30 return HeapAlloc(GetProcessHeap(), 0, len);
31 }
32
33 static inline BOOL heap_free(void *mem)
34 {
35 return HeapFree(GetProcessHeap(), 0, mem);
36 }
37
38 static ICatRegister *catreg;
39
40 /***********************************************************************
41 * AtlAdvise [atl100.@]
42 */
43 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, DWORD *pdw)
44 {
45 IConnectionPointContainer *container;
46 IConnectionPoint *cp;
47 HRESULT hres;
48
49 TRACE("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
50
51 if(!pUnkCP)
52 return E_INVALIDARG;
53
54 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
55 if(FAILED(hres))
56 return hres;
57
58 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
59 IConnectionPointContainer_Release(container);
60 if(FAILED(hres))
61 return hres;
62
63 hres = IConnectionPoint_Advise(cp, pUnk, pdw);
64 IConnectionPoint_Release(cp);
65 return hres;
66 }
67
68 /***********************************************************************
69 * AtlUnadvise [atl100.@]
70 */
71 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
72 {
73 IConnectionPointContainer *container;
74 IConnectionPoint *cp;
75 HRESULT hres;
76
77 TRACE("%p %p %d\n", pUnkCP, iid, dw);
78
79 if(!pUnkCP)
80 return E_INVALIDARG;
81
82 hres = IUnknown_QueryInterface(pUnkCP, &IID_IConnectionPointContainer, (void**)&container);
83 if(FAILED(hres))
84 return hres;
85
86 hres = IConnectionPointContainer_FindConnectionPoint(container, iid, &cp);
87 IConnectionPointContainer_Release(container);
88 if(FAILED(hres))
89 return hres;
90
91 hres = IConnectionPoint_Unadvise(cp, dw);
92 IConnectionPoint_Release(cp);
93 return hres;
94 }
95
96 /***********************************************************************
97 * AtlFreeMarshalStream [atl100.@]
98 */
99 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
100 {
101 FIXME("%p\n", stm);
102 return S_OK;
103 }
104
105 /***********************************************************************
106 * AtlMarshalPtrInProc [atl100.@]
107 */
108 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
109 {
110 FIXME("%p %p %p\n", pUnk, iid, pstm);
111 return E_FAIL;
112 }
113
114 /***********************************************************************
115 * AtlUnmarshalPtr [atl100.@]
116 */
117 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
118 {
119 FIXME("%p %p %p\n", stm, iid, ppUnk);
120 return E_FAIL;
121 }
122
123 /***********************************************************************
124 * AtlCreateTargetDC [atl100.@]
125 */
126 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
127 {
128 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
129 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
130 DEVMODEW *devmode = NULL;
131
132 TRACE( "(%p, %p)\n", hdc, dv );
133
134 if (dv)
135 {
136 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
137 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
138 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
139 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
140 }
141 else
142 {
143 if (hdc) return hdc;
144 driver = displayW;
145 }
146 return CreateDCW( driver, device, port, devmode );
147 }
148
149 /***********************************************************************
150 * AtlHiMetricToPixel [atl100.@]
151 */
152 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
153 {
154 HDC dc = GetDC(NULL);
155 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
156 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
157 ReleaseDC( NULL, dc );
158 }
159
160 /***********************************************************************
161 * AtlPixelToHiMetric [atl100.@]
162 */
163 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
164 {
165 HDC dc = GetDC(NULL);
166 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
167 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
168 ReleaseDC( NULL, dc );
169 }
170
171 /***********************************************************************
172 * AtlComPtrAssign [atl100.@]
173 */
174 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
175 {
176 TRACE("(%p %p)\n", pp, p);
177
178 if (p) IUnknown_AddRef(p);
179 if (*pp) IUnknown_Release(*pp);
180 *pp = p;
181 return p;
182 }
183
184 /***********************************************************************
185 * AtlComQIPtrAssign [atl100.@]
186 */
187 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
188 {
189 IUnknown *new_p = NULL;
190
191 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
192
193 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
194 if (*pp) IUnknown_Release(*pp);
195 *pp = new_p;
196 return new_p;
197 }
198
199 /***********************************************************************
200 * AtlInternalQueryInterface [atl100.@]
201 */
202 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
203 {
204 int i = 0;
205 HRESULT rc = E_NOINTERFACE;
206 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
207
208 if (IsEqualGUID(iid,&IID_IUnknown))
209 {
210 TRACE("Returning IUnknown\n");
211 *ppvObject = ((LPSTR)this+pEntries[0].dw);
212 IUnknown_AddRef((IUnknown*)*ppvObject);
213 return S_OK;
214 }
215
216 while (pEntries[i].pFunc != 0)
217 {
218 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
219 pEntries[i].dw, pEntries[i].pFunc);
220
221 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
222 {
223 TRACE("MATCH\n");
224 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
225 {
226 TRACE("Offset\n");
227 *ppvObject = ((LPSTR)this+pEntries[i].dw);
228 IUnknown_AddRef((IUnknown*)*ppvObject);
229 return S_OK;
230 }
231 else
232 {
233 TRACE("Function\n");
234 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
235 if(rc==S_OK || pEntries[i].piid)
236 return rc;
237 }
238 }
239 i++;
240 }
241 TRACE("Done returning (0x%x)\n",rc);
242 return rc;
243 }
244
245 /* FIXME: should be in a header file */
246 typedef struct ATL_PROPMAP_ENTRY
247 {
248 LPCOLESTR szDesc;
249 DISPID dispid;
250 const CLSID* pclsidPropPage;
251 const IID* piidDispatch;
252 DWORD dwOffsetData;
253 DWORD dwSizeData;
254 VARTYPE vt;
255 } ATL_PROPMAP_ENTRY;
256
257 /***********************************************************************
258 * AtlIPersistStreamInit_Load [atl100.@]
259 */
260 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
261 void *pThis, IUnknown *pUnk)
262 {
263 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
264
265 return S_OK;
266 }
267
268 /***********************************************************************
269 * AtlIPersistStreamInit_Save [atl100.@]
270 */
271 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
272 ATL_PROPMAP_ENTRY *pMap, void *pThis,
273 IUnknown *pUnk)
274 {
275 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
276
277 return S_OK;
278 }
279
280 /***********************************************************************
281 * AtlIPersistPropertyBag_Load [atl100.@]
282 */
283 HRESULT WINAPI AtlIPersistPropertyBag_Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog,
284 ATL_PROPMAP_ENTRY *pMap, void *pThis,
285 IUnknown *pUnk)
286 {
287 FIXME("(%p, %p, %p, %p, %p)\n", pPropBag, pErrorLog, pMap, pThis, pUnk);
288
289 return S_OK;
290 }
291
292 /***********************************************************************
293 * AtlModuleAddTermFunc [atl100.@]
294 */
295 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
296 {
297 _ATL_TERMFUNC_ELEM *termfunc_elem;
298
299 TRACE("(%p %p %ld)\n", pM, pFunc, dw);
300
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;
305
306 pM->m_pTermFuncs = termfunc_elem;
307
308 return S_OK;
309 }
310
311 /***********************************************************************
312 * AtlCallTermFunc [atl100.@]
313 */
314 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
315 {
316 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
317
318 TRACE("(%p)\n", pM);
319
320 while(iter) {
321 iter->pFunc(iter->dw);
322 tmp = iter;
323 iter = iter->pNext;
324 HeapFree(GetProcessHeap(), 0, tmp);
325 }
326
327 pM->m_pTermFuncs = NULL;
328 }
329
330 /***********************************************************************
331 * AtlLoadTypeLib [atl100.56]
332 */
333 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
334 BSTR *pbstrPath, ITypeLib **ppTypeLib)
335 {
336 size_t path_len, index_len;
337 ITypeLib *typelib = NULL;
338 WCHAR *path;
339 HRESULT hres;
340
341 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
342
343 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
344
345 index_len = lpszIndex ? strlenW(lpszIndex) : 0;
346 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
347 if(!path)
348 return E_OUTOFMEMORY;
349
350 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
351 if(!path_len) {
352 heap_free(path);
353 return HRESULT_FROM_WIN32(GetLastError());
354 }
355
356 if(index_len)
357 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
358
359 hres = LoadTypeLib(path, &typelib);
360 if(FAILED(hres)) {
361 WCHAR *ptr;
362
363 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
364 if(*ptr != '.')
365 ptr = path+path_len;
366 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
367 hres = LoadTypeLib(path, &typelib);
368 }
369
370 if(SUCCEEDED(hres)) {
371 *pbstrPath = SysAllocString(path);
372 if(!*pbstrPath) {
373 ITypeLib_Release(typelib);
374 hres = E_OUTOFMEMORY;
375 }
376 }
377
378 heap_free(path);
379 if(FAILED(hres))
380 return hres;
381
382 *ppTypeLib = typelib;
383 return S_OK;
384 }
385
386 /***********************************************************************
387 * AtlWinModuleInit [atl100.65]
388 */
389 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
390 {
391 TRACE("(%p\n", winmod);
392
393 if(winmod->cbSize != sizeof(*winmod))
394 return E_INVALIDARG;
395
396 InitializeCriticalSection(&winmod->m_csWindowCreate);
397 winmod->m_pCreateWndList = NULL;
398 return S_OK;
399 }
400
401 /***********************************************************************
402 * AtlWinModuleAddCreateWndData [atl100.43]
403 */
404 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
405 {
406 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
407
408 pData->m_pThis = pvObject;
409 pData->m_dwThreadID = GetCurrentThreadId();
410
411 EnterCriticalSection(&pM->m_csWindowCreate);
412 pData->m_pNext = pM->m_pCreateWndList;
413 pM->m_pCreateWndList = pData;
414 LeaveCriticalSection(&pM->m_csWindowCreate);
415 }
416
417 /***********************************************************************
418 * AtlWinModuleExtractCreateWndData [atl100.44]
419 */
420 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
421 {
422 _AtlCreateWndData *iter, *prev = NULL;
423 DWORD thread_id;
424
425 TRACE("(%p)\n", winmod);
426
427 thread_id = GetCurrentThreadId();
428
429 EnterCriticalSection(&winmod->m_csWindowCreate);
430
431 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
432 prev = iter;
433 if(iter) {
434 if(prev)
435 prev->m_pNext = iter->m_pNext;
436 else
437 winmod->m_pCreateWndList = iter->m_pNext;
438 }
439
440 LeaveCriticalSection(&winmod->m_csWindowCreate);
441
442 return iter ? iter->m_pThis : NULL;
443 }
444
445 /***********************************************************************
446 * AtlComModuleGetClassObject [atl100.15]
447 */
448 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
449 {
450 _ATL_OBJMAP_ENTRY **iter;
451 HRESULT hres;
452
453 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
454
455 if(!pm)
456 return E_INVALIDARG;
457
458 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
459 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
460 if(!(*iter)->pCF)
461 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
462 if((*iter)->pCF)
463 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
464 TRACE("returning %p (%08x)\n", *ppv, hres);
465 return hres;
466 }
467 }
468
469 WARN("Class %s not found\n", debugstr_guid(rclsid));
470 return CLASS_E_CLASSNOTAVAILABLE;
471 }
472
473 /***********************************************************************
474 * AtlComModuleRegisterClassObjects [atl100.17]
475 */
476 HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags)
477 {
478 _ATL_OBJMAP_ENTRY **iter;
479 IUnknown *unk;
480 HRESULT hres;
481
482 TRACE("(%p %x %x)\n", module, context, flags);
483
484 if(!module)
485 return E_INVALIDARG;
486
487 for(iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) {
488 if(!(*iter)->pfnGetClassObject)
489 continue;
490
491 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&unk);
492 if(FAILED(hres))
493 return hres;
494
495 hres = CoRegisterClassObject((*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister);
496 IUnknown_Release(unk);
497 if(FAILED(hres))
498 return hres;
499 }
500
501 return S_OK;
502
503 }
504
505 /***********************************************************************
506 * AtlComModuleUnregisterServer [atl100.22]
507 */
508 HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid)
509 {
510 const struct _ATL_CATMAP_ENTRY *catmap;
511 _ATL_OBJMAP_ENTRY **iter;
512 HRESULT hres;
513
514 TRACE("(%p %x %s)\n", mod, bRegTypeLib, debugstr_guid(clsid));
515
516 for(iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) {
517 if(!*iter || (clsid && !IsEqualCLSID((*iter)->pclsid, clsid)))
518 continue;
519
520 TRACE("Unregistering clsid %s\n", debugstr_guid((*iter)->pclsid));
521
522 catmap = (*iter)->pfnGetCategoryMap();
523 if(catmap) {
524 hres = AtlRegisterClassCategoriesHelper((*iter)->pclsid, catmap, FALSE);
525 if(FAILED(hres))
526 return hres;
527 }
528
529 hres = (*iter)->pfnUpdateRegistry(FALSE);
530 if(FAILED(hres))
531 return hres;
532 }
533
534 if(bRegTypeLib) {
535 ITypeLib *typelib;
536 TLIBATTR *attr;
537 BSTR path;
538
539 hres = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib);
540 if(FAILED(hres))
541 return hres;
542
543 SysFreeString(path);
544 hres = ITypeLib_GetLibAttr(typelib, &attr);
545 if(SUCCEEDED(hres)) {
546 hres = UnRegisterTypeLib(&attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind);
547 ITypeLib_ReleaseTLibAttr(typelib, attr);
548 }
549 ITypeLib_Release(typelib);
550 if(FAILED(hres))
551 return hres;
552 }
553
554 return S_OK;
555 }
556
557 /***********************************************************************
558 * AtlRegisterClassCategoriesHelper [atl100.49]
559 */
560 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
561 {
562 const struct _ATL_CATMAP_ENTRY *iter;
563 HRESULT hres;
564
565 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
566
567 if(!catmap)
568 return S_OK;
569
570 if(!catreg) {
571 ICatRegister *new_catreg;
572
573 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
574 &IID_ICatRegister, (void**)&new_catreg);
575 if(FAILED(hres))
576 return hres;
577
578 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
579 ICatRegister_Release(new_catreg);
580 }
581
582 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
583 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
584
585 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
586 if(reg)
587 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
588 else
589 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
590 }else {
591 if(reg)
592 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
593 else
594 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
595 }
596 if(FAILED(hres))
597 return hres;
598 }
599
600 if(!reg) {
601 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
602
603 static const WCHAR implemented_catW[] =
604 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
605 static const WCHAR required_catW[] =
606 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
607
608 ptr += StringFromGUID2(clsid, ptr, 64)-1;
609 *ptr++ = '\\';
610
611 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
612 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
613
614 memcpy(ptr, required_catW, sizeof(required_catW));
615 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
616 }
617
618 return S_OK;
619 }
620
621 /***********************************************************************
622 * AtlWaitWithMessageLoop [atl100.24]
623 */
624 BOOL WINAPI AtlWaitWithMessageLoop(HANDLE handle)
625 {
626 MSG msg;
627 DWORD res;
628
629 TRACE("(%p)\n", handle);
630
631 while(1) {
632 res = MsgWaitForMultipleObjects(1, &handle, FALSE, INFINITE, QS_ALLINPUT);
633 switch(res) {
634 case WAIT_OBJECT_0:
635 return TRUE;
636 case WAIT_OBJECT_0+1:
637 if(GetMessageW(&msg, NULL, 0, 0) < 0)
638 return FALSE;
639
640 TranslateMessage(&msg);
641 DispatchMessageW(&msg);
642 break;
643 default:
644 return FALSE;
645 }
646 }
647 }
648
649 static HRESULT get_default_source(ITypeLib *typelib, const CLSID *clsid, IID *iid)
650 {
651 ITypeInfo *typeinfo, *src_typeinfo = NULL;
652 TYPEATTR *attr;
653 int type_flags;
654 unsigned i;
655 HRESULT hres;
656
657 hres = ITypeLib_GetTypeInfoOfGuid(typelib, clsid, &typeinfo);
658 if(FAILED(hres))
659 return hres;
660
661 hres = ITypeInfo_GetTypeAttr(typeinfo, &attr);
662 if(FAILED(hres)) {
663 ITypeInfo_Release(typeinfo);
664 return hres;
665 }
666
667 for(i=0; i < attr->cImplTypes; i++) {
668 hres = ITypeInfo_GetImplTypeFlags(typeinfo, i, &type_flags);
669 if(SUCCEEDED(hres) && type_flags == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) {
670 HREFTYPE ref;
671
672 hres = ITypeInfo_GetRefTypeOfImplType(typeinfo, i, &ref);
673 if(SUCCEEDED(hres))
674 hres = ITypeInfo_GetRefTypeInfo(typeinfo, ref, &src_typeinfo);
675 break;
676 }
677 }
678
679 ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
680 ITypeInfo_Release(typeinfo);
681 if(FAILED(hres))
682 return hres;
683
684 if(!src_typeinfo) {
685 *iid = IID_NULL;
686 return S_OK;
687 }
688
689 hres = ITypeInfo_GetTypeAttr(src_typeinfo, &attr);
690 if(SUCCEEDED(hres)) {
691 *iid = attr->guid;
692 ITypeInfo_ReleaseTypeAttr(src_typeinfo, attr);
693 }
694 ITypeInfo_Release(src_typeinfo);
695 return hres;
696 }
697
698 /***********************************************************************
699 * AtlGetObjectSourceInterface [atl100.54]
700 */
701 HRESULT WINAPI AtlGetObjectSourceInterface(IUnknown *unk, GUID *libid, IID *iid, unsigned short *major, unsigned short *minor)
702 {
703 IProvideClassInfo2 *classinfo;
704 ITypeInfo *typeinfo;
705 ITypeLib *typelib;
706 IPersist *persist;
707 IDispatch *disp;
708 HRESULT hres;
709
710 TRACE("(%p %p %p %p %p)\n", unk, libid, iid, major, minor);
711
712 hres = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
713 if(FAILED(hres))
714 return hres;
715
716 hres = IDispatch_GetTypeInfo(disp, 0, 0, &typeinfo);
717 IDispatch_Release(disp);
718 if(FAILED(hres))
719 return hres;
720
721 hres = ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, 0);
722 ITypeInfo_Release(typeinfo);
723 if(SUCCEEDED(hres)) {
724 TLIBATTR *attr;
725
726 hres = ITypeLib_GetLibAttr(typelib, &attr);
727 if(SUCCEEDED(hres)) {
728 *libid = attr->guid;
729 *major = attr->wMajorVerNum;
730 *minor = attr->wMinorVerNum;
731 ITypeLib_ReleaseTLibAttr(typelib, attr);
732 }else {
733 ITypeLib_Release(typelib);
734 }
735 }
736 if(FAILED(hres))
737 return hres;
738
739 hres = IUnknown_QueryInterface(unk, &IID_IProvideClassInfo2, (void**)&classinfo);
740 if(SUCCEEDED(hres)) {
741 hres = IProvideClassInfo2_GetGUID(classinfo, GUIDKIND_DEFAULT_SOURCE_DISP_IID, iid);
742 IProvideClassInfo2_Release(classinfo);
743 ITypeLib_Release(typelib);
744 return hres;
745 }
746
747 hres = IUnknown_QueryInterface(unk, &IID_IPersist, (void**)&persist);
748 if(SUCCEEDED(hres)) {
749 CLSID clsid;
750
751 hres = IPersist_GetClassID(persist, &clsid);
752 if(SUCCEEDED(hres))
753 hres = get_default_source(typelib, &clsid, iid);
754 IPersist_Release(persist);
755 }
756
757 return hres;
758 }
759
760 /***********************************************************************
761 * AtlSetPerUserRegistration [atl100.67]
762 */
763 HRESULT WINAPI AtlSetPerUserRegistration(cpp_bool bEnable)
764 {
765 FIXME("stub: bEnable: %d\n", bEnable);
766 return E_NOTIMPL;
767 }
768
769 /***********************************************************************
770 * AtlGetPerUserRegistration [atl100.68]
771 */
772 HRESULT WINAPI AtlGetPerUserRegistration(cpp_bool *pbEnabled)
773 {
774 FIXME("stub: returning false\n");
775 *pbEnabled = 0;
776 return S_OK;
777 }
778
779 /***********************************************************************
780 * AtlGetVersion [atl100.@]
781 */
782 DWORD WINAPI AtlGetVersion(void *pReserved)
783 {
784 return _ATL_VER;
785 }
786
787 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
788 {
789 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
790
791 switch(fdwReason) {
792 case DLL_PROCESS_ATTACH:
793 DisableThreadLibraryCalls(hinstDLL);
794 break;
795 case DLL_PROCESS_DETACH:
796 if (lpvReserved) break;
797 if(catreg)
798 ICatRegister_Release(catreg);
799 }
800
801 return TRUE;
802 }