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