advapi32: Avoid signed-unsigned integer comparisons.
[wine] / dlls / 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 #define COBJMACROS
21
22 #include "atlbase.h"
23
24 #include "wine/debug.h"
25 #include "wine/unicode.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(atl100);
28
29 static inline void *heap_alloc(size_t len)
30 {
31     return HeapAlloc(GetProcessHeap(), 0, len);
32 }
33
34 static inline BOOL heap_free(void *mem)
35 {
36     return HeapFree(GetProcessHeap(), 0, mem);
37 }
38
39 static ICatRegister *catreg;
40
41 /***********************************************************************
42  *           AtlAdvise         [atl100.@]
43  */
44 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, LPDWORD pdw)
45 {
46     FIXME("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
47     return E_FAIL;
48 }
49
50 /***********************************************************************
51  *           AtlUnadvise         [atl100.@]
52  */
53 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
54 {
55     FIXME("%p %p %d\n", pUnkCP, iid, dw);
56     return S_OK;
57 }
58
59 /***********************************************************************
60  *           AtlFreeMarshalStream         [atl100.@]
61  */
62 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
63 {
64     FIXME("%p\n", stm);
65     return S_OK;
66 }
67
68 /***********************************************************************
69  *           AtlMarshalPtrInProc         [atl100.@]
70  */
71 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
72 {
73     FIXME("%p %p %p\n", pUnk, iid, pstm);
74     return E_FAIL;
75 }
76
77 /***********************************************************************
78  *           AtlUnmarshalPtr              [atl100.@]
79  */
80 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
81 {
82     FIXME("%p %p %p\n", stm, iid, ppUnk);
83     return E_FAIL;
84 }
85
86 /***********************************************************************
87  *           AtlCreateTargetDC         [atl100.@]
88  */
89 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
90 {
91     static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
92     const WCHAR *driver = NULL, *device = NULL, *port = NULL;
93     DEVMODEW *devmode = NULL;
94
95     TRACE( "(%p, %p)\n", hdc, dv );
96
97     if (dv)
98     {
99         if (dv->tdDriverNameOffset) driver  = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
100         if (dv->tdDeviceNameOffset) device  = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
101         if (dv->tdPortNameOffset)   port    = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
102         if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
103     }
104     else
105     {
106         if (hdc) return hdc;
107         driver = displayW;
108     }
109     return CreateDCW( driver, device, port, devmode );
110 }
111
112 /***********************************************************************
113  *           AtlHiMetricToPixel              [atl100.@]
114  */
115 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
116 {
117     HDC dc = GetDC(NULL);
118     lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
119     lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
120     ReleaseDC( NULL, dc );
121 }
122
123 /***********************************************************************
124  *           AtlPixelToHiMetric              [atl100.@]
125  */
126 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
127 {
128     HDC dc = GetDC(NULL);
129     lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
130     lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
131     ReleaseDC( NULL, dc );
132 }
133
134 /***********************************************************************
135  *           AtlComPtrAssign              [atl100.@]
136  */
137 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
138 {
139     TRACE("(%p %p)\n", pp, p);
140
141     if (p) IUnknown_AddRef(p);
142     if (*pp) IUnknown_Release(*pp);
143     *pp = p;
144     return p;
145 }
146
147 /***********************************************************************
148  *           AtlComQIPtrAssign              [atl100.@]
149  */
150 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
151 {
152     IUnknown *new_p = NULL;
153
154     TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
155
156     if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
157     if (*pp) IUnknown_Release(*pp);
158     *pp = new_p;
159     return new_p;
160 }
161
162 /***********************************************************************
163  *           AtlInternalQueryInterface     [atl100.@]
164  */
165 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries,  REFIID iid, void** ppvObject)
166 {
167     int i = 0;
168     HRESULT rc = E_NOINTERFACE;
169     TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
170
171     if (IsEqualGUID(iid,&IID_IUnknown))
172     {
173         TRACE("Returning IUnknown\n");
174         *ppvObject = ((LPSTR)this+pEntries[0].dw);
175         IUnknown_AddRef((IUnknown*)*ppvObject);
176         return S_OK;
177     }
178
179     while (pEntries[i].pFunc != 0)
180     {
181         TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
182               pEntries[i].dw, pEntries[i].pFunc);
183
184         if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
185         {
186             TRACE("MATCH\n");
187             if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
188             {
189                 TRACE("Offset\n");
190                 *ppvObject = ((LPSTR)this+pEntries[i].dw);
191                 IUnknown_AddRef((IUnknown*)*ppvObject);
192                 return S_OK;
193             }
194             else
195             {
196                 TRACE("Function\n");
197                 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
198                 if(rc==S_OK || pEntries[i].piid)
199                     return rc;
200             }
201         }
202         i++;
203     }
204     TRACE("Done returning (0x%x)\n",rc);
205     return rc;
206 }
207
208 /* FIXME: should be in a header file */
209 typedef struct ATL_PROPMAP_ENTRY
210 {
211     LPCOLESTR szDesc;
212     DISPID dispid;
213     const CLSID* pclsidPropPage;
214     const IID* piidDispatch;
215     DWORD dwOffsetData;
216     DWORD dwSizeData;
217     VARTYPE vt;
218 } ATL_PROPMAP_ENTRY;
219
220 /***********************************************************************
221  *           AtlIPersistStreamInit_Load      [atl100.@]
222  */
223 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
224                                            void *pThis, IUnknown *pUnk)
225 {
226     FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
227
228     return S_OK;
229 }
230
231 /***********************************************************************
232  *           AtlIPersistStreamInit_Save      [atl100.@]
233  */
234 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
235                                           ATL_PROPMAP_ENTRY *pMap, void *pThis,
236                                           IUnknown *pUnk)
237 {
238     FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
239
240     return S_OK;
241 }
242
243 /***********************************************************************
244  *           AtlModuleAddTermFunc            [atl100.@]
245  */
246 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
247 {
248     _ATL_TERMFUNC_ELEM *termfunc_elem;
249
250     TRACE("(%p %p %ld)\n", pM, pFunc, dw);
251
252     termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
253     termfunc_elem->pFunc = pFunc;
254     termfunc_elem->dw = dw;
255     termfunc_elem->pNext = pM->m_pTermFuncs;
256
257     pM->m_pTermFuncs = termfunc_elem;
258
259     return S_OK;
260 }
261
262 /***********************************************************************
263  *           AtlCallTermFunc              [atl100.@]
264  */
265 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
266 {
267     _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
268
269     TRACE("(%p)\n", pM);
270
271     while(iter) {
272         iter->pFunc(iter->dw);
273         tmp = iter;
274         iter = iter->pNext;
275         HeapFree(GetProcessHeap(), 0, tmp);
276     }
277
278     pM->m_pTermFuncs = NULL;
279 }
280
281 /***********************************************************************
282  *           AtlLoadTypeLib             [atl100.56]
283  */
284 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
285         BSTR *pbstrPath, ITypeLib **ppTypeLib)
286 {
287     size_t path_len, index_len;
288     ITypeLib *typelib = NULL;
289     WCHAR *path;
290     HRESULT hres;
291
292     static const WCHAR tlb_extW[] = {'.','t','l','b',0};
293
294     TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
295
296     index_len = lpszIndex ? strlenW(lpszIndex) : 0;
297     path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
298     if(!path)
299         return E_OUTOFMEMORY;
300
301     path_len = GetModuleFileNameW(inst, path, MAX_PATH);
302     if(!path_len)
303         return HRESULT_FROM_WIN32(GetLastError());
304
305     if(index_len)
306         memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
307
308     hres = LoadTypeLib(path, &typelib);
309     if(FAILED(hres)) {
310         WCHAR *ptr;
311
312         for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
313         if(*ptr != '.')
314             ptr = path+path_len;
315         memcpy(ptr, tlb_extW, sizeof(tlb_extW));
316         hres = LoadTypeLib(path, &typelib);
317     }
318
319     if(SUCCEEDED(hres)) {
320         *pbstrPath = SysAllocString(path);
321         if(!*pbstrPath) {
322             ITypeLib_Release(typelib);
323             hres = E_OUTOFMEMORY;
324         }
325     }
326
327     heap_free(path);
328     if(FAILED(hres))
329         return hres;
330
331     *ppTypeLib = typelib;
332     return S_OK;
333 }
334
335 /***********************************************************************
336  *           AtlWinModuleInit                          [atl100.65]
337  */
338 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
339 {
340     TRACE("(%p\n", winmod);
341
342     if(winmod->cbSize != sizeof(*winmod))
343         return E_INVALIDARG;
344
345     InitializeCriticalSection(&winmod->m_csWindowCreate);
346     winmod->m_pCreateWndList = NULL;
347     return S_OK;
348 }
349
350 /***********************************************************************
351  *           AtlWinModuleAddCreateWndData              [atl100.43]
352  */
353 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
354 {
355     TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
356
357     pData->m_pThis = pvObject;
358     pData->m_dwThreadID = GetCurrentThreadId();
359
360     EnterCriticalSection(&pM->m_csWindowCreate);
361     pData->m_pNext = pM->m_pCreateWndList;
362     pM->m_pCreateWndList = pData;
363     LeaveCriticalSection(&pM->m_csWindowCreate);
364 }
365
366 /***********************************************************************
367  *           AtlWinModuleExtractCreateWndData          [atl100.44]
368  */
369 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
370 {
371     _AtlCreateWndData *iter, *prev = NULL;
372     DWORD thread_id;
373
374     TRACE("(%p)\n", winmod);
375
376     thread_id = GetCurrentThreadId();
377
378     EnterCriticalSection(&winmod->m_csWindowCreate);
379
380     for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
381         prev = iter;
382     if(iter) {
383         if(prev)
384             prev->m_pNext = iter->m_pNext;
385         else
386             winmod->m_pCreateWndList = iter->m_pNext;
387     }
388
389     LeaveCriticalSection(&winmod->m_csWindowCreate);
390
391     return iter ? iter->m_pThis : NULL;
392 }
393
394 /***********************************************************************
395  *           AtlComModuleGetClassObject                [atl100.15]
396  */
397 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
398 {
399     _ATL_OBJMAP_ENTRY **iter;
400     HRESULT hres;
401
402     TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
403
404     if(!pm)
405         return E_INVALIDARG;
406
407     for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
408         if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
409             if(!(*iter)->pCF)
410                 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
411             if((*iter)->pCF)
412                 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
413             TRACE("returning %p (%08x)\n", *ppv, hres);
414             return hres;
415         }
416     }
417
418     WARN("Class %s not found\n", debugstr_guid(rclsid));
419     return CLASS_E_CLASSNOTAVAILABLE;
420 }
421
422 /***********************************************************************
423  *           AtlRegisterClassCategoriesHelper          [atl100.49]
424  */
425 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
426 {
427     const struct _ATL_CATMAP_ENTRY *iter;
428     HRESULT hres;
429
430     TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
431
432     if(!catmap)
433         return S_OK;
434
435     if(!catreg) {
436         ICatRegister *new_catreg;
437
438         hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
439                 &IID_ICatRegister, (void**)&new_catreg);
440         if(FAILED(hres))
441             return hres;
442
443         if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
444             ICatRegister_Release(new_catreg);
445     }
446
447     for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
448         CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
449
450         if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
451             if(reg)
452                 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
453             else
454                 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
455         }else {
456             if(reg)
457                 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
458             else
459                 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
460         }
461         if(FAILED(hres))
462             return hres;
463     }
464
465     if(!reg) {
466         WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
467
468         static const WCHAR implemented_catW[] =
469             {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
470         static const WCHAR required_catW[] =
471             {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
472
473         ptr += StringFromGUID2(clsid, ptr, 64)-1;
474         *ptr++ = '\\';
475
476         memcpy(ptr, implemented_catW, sizeof(implemented_catW));
477         RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
478
479         memcpy(ptr, required_catW, sizeof(required_catW));
480         RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
481     }
482
483     return S_OK;
484 }
485
486 /***********************************************************************
487  *           AtlGetVersion              [atl100.@]
488  */
489 DWORD WINAPI AtlGetVersion(void *pReserved)
490 {
491    return _ATL_VER;
492 }
493
494 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
495 {
496     TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
497
498     switch(fdwReason) {
499     case DLL_PROCESS_ATTACH:
500         DisableThreadLibraryCalls(hinstDLL);
501         break;
502     case DLL_PROCESS_DETACH:
503         if(catreg)
504             ICatRegister_Release(catreg);
505     }
506
507     return TRUE;
508 }