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