explorerframe: Avoid signed-unsigned integer comparisons.
[wine] / dlls / atl / atl_main.c
1 /*
2  * Implementation of Active Template Library (atl.dll)
3  *
4  * Copyright 2004 Aric Stewart for CodeWeavers
5  * Copyright 2005 Jacek Caban
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "objidl.h"
27 #include "rpcproxy.h"
28 #include "atlbase.h"
29 #include "atlwin.h"
30
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(atl);
35
36 static HINSTANCE hInst;
37
38 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
39 {
40     TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
41
42     if (fdwReason == DLL_PROCESS_ATTACH) {
43         DisableThreadLibraryCalls(hinstDLL);
44         hInst = hinstDLL;
45     }
46     return TRUE;
47 }
48
49 #define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer)
50
51 HRESULT WINAPI AtlModuleInit(_ATL_MODULEW* pM, _ATL_OBJMAP_ENTRYW* p, HINSTANCE h)
52 {
53     INT i;
54     UINT size;
55
56     TRACE("(%p %p %p)\n", pM, p, h);
57
58     size = pM->cbSize;
59     switch (size)
60     {
61     case ATLVer1Size:
62     case sizeof(_ATL_MODULEW):
63 #ifdef _WIN64
64     case sizeof(_ATL_MODULEW) + sizeof(void *):
65 #endif
66         break;
67     default:
68         WARN("Unknown structure version (size %i)\n",size);
69         return E_INVALIDARG;
70     }
71
72     memset(pM,0,pM->cbSize);
73     pM->cbSize = size;
74     pM->m_hInst = h;
75     pM->m_hInstResource = h;
76     pM->m_hInstTypeLib = h;
77     pM->m_pObjMap = p;
78     pM->m_hHeap = GetProcessHeap();
79
80     InitializeCriticalSection(&pM->u.m_csTypeInfoHolder);
81     InitializeCriticalSection(&pM->m_csWindowCreate);
82     InitializeCriticalSection(&pM->m_csObjMap);
83
84     /* call mains */
85     i = 0;
86     if (pM->m_pObjMap != NULL  && size > ATLVer1Size)
87     {
88         while (pM->m_pObjMap[i].pclsid != NULL)
89         {
90             TRACE("Initializing object %i %p\n",i,p[i].pfnObjectMain);
91             if (p[i].pfnObjectMain)
92                 p[i].pfnObjectMain(TRUE);
93             i++;
94         }
95     }
96
97     return S_OK;
98 }
99
100 static _ATL_OBJMAP_ENTRYW_V1 *get_objmap_entry( _ATL_MODULEW *mod, unsigned int index )
101 {
102     _ATL_OBJMAP_ENTRYW_V1 *ret;
103
104     if (mod->cbSize == ATLVer1Size)
105         ret = (_ATL_OBJMAP_ENTRYW_V1 *)mod->m_pObjMap + index;
106     else
107         ret = (_ATL_OBJMAP_ENTRYW_V1 *)(mod->m_pObjMap + index);
108
109     if (!ret->pclsid) ret = NULL;
110     return ret;
111 }
112
113 HRESULT WINAPI AtlModuleLoadTypeLib(_ATL_MODULEW *pM, LPCOLESTR lpszIndex,
114                                     BSTR *pbstrPath, ITypeLib **ppTypeLib)
115 {
116     TRACE("(%p, %s, %p, %p)\n", pM, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
117
118     if (!pM)
119         return E_INVALIDARG;
120
121     return AtlLoadTypeLib(pM->m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib);
122 }
123
124 HRESULT WINAPI AtlModuleTerm(_ATL_MODULE *pM)
125 {
126     _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
127
128     TRACE("(%p)\n", pM);
129
130     while(iter) {
131         iter->pFunc(iter->dw);
132         tmp = iter;
133         iter = iter->pNext;
134         HeapFree(GetProcessHeap(), 0, tmp);
135     }
136
137     return S_OK;
138 }
139
140 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULEW *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
141 {
142     _ATL_TERMFUNC_ELEM *termfunc_elem;
143
144     TRACE("(%p %p %ld)\n", pM, pFunc, dw);
145
146     termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
147     termfunc_elem->pFunc = pFunc;
148     termfunc_elem->dw = dw;
149     termfunc_elem->pNext = pM->m_pTermFuncs;
150
151     pM->m_pTermFuncs = termfunc_elem;
152
153     return S_OK;
154 }
155
156 HRESULT WINAPI AtlModuleRegisterClassObjects(_ATL_MODULEW *pM, DWORD dwClsContext,
157                                              DWORD dwFlags)
158 {
159     _ATL_OBJMAP_ENTRYW_V1 *obj;
160     int i=0;
161
162     TRACE("(%p %i %i)\n",pM, dwClsContext, dwFlags);
163
164     if (pM == NULL)
165         return E_INVALIDARG;
166
167     while ((obj = get_objmap_entry( pM, i++ )))
168     {
169         IUnknown* pUnknown;
170         HRESULT rc;
171
172         TRACE("Registering object %i\n",i);
173         if (obj->pfnGetClassObject)
174         {
175             rc = obj->pfnGetClassObject(obj->pfnCreateInstance, &IID_IUnknown,
176                                    (LPVOID*)&pUnknown);
177             if (SUCCEEDED (rc) )
178             {
179                 rc = CoRegisterClassObject(obj->pclsid, pUnknown, dwClsContext,
180                                            dwFlags, &obj->dwRegister);
181
182                 if (FAILED (rc) )
183                     WARN("Failed to register object %i: 0x%08x\n", i, rc);
184
185                 if (pUnknown)
186                     IUnknown_Release(pUnknown);
187             }
188         }
189     }
190
191    return S_OK;
192 }
193
194 HRESULT WINAPI AtlModuleUnregisterServerEx(_ATL_MODULEW* pM, BOOL bUnRegTypeLib, const CLSID* pCLSID)
195 {
196     FIXME("(%p, %i, %p) stub\n", pM, bUnRegTypeLib, pCLSID);
197     return S_OK;
198 }
199
200 /***********************************************************************
201  *           AtlModuleRegisterServer         [ATL.@]
202  *
203  */
204 HRESULT WINAPI AtlModuleRegisterServer(_ATL_MODULEW* pM, BOOL bRegTypeLib, const CLSID* clsid)
205 {
206     const _ATL_OBJMAP_ENTRYW_V1 *obj;
207     int i;
208     HRESULT hRes;
209
210     TRACE("%p %d %s\n", pM, bRegTypeLib, debugstr_guid(clsid));
211
212     if (pM == NULL)
213         return E_INVALIDARG;
214
215     for (i = 0; (obj = get_objmap_entry( pM, i )) != NULL; i++) /* register CLSIDs */
216     {
217         if (!clsid || IsEqualCLSID(obj->pclsid, clsid))
218         {
219             TRACE("Registering clsid %s\n", debugstr_guid(obj->pclsid));
220             hRes = obj->pfnUpdateRegistry(TRUE); /* register */
221             if (FAILED(hRes))
222                 return hRes;
223
224             if(pM->cbSize > ATLVer1Size) {
225                 const struct _ATL_CATMAP_ENTRY *catmap;
226
227                 catmap = ((const _ATL_OBJMAP_ENTRYW*)obj)->pfnGetCategoryMap();
228                 if(catmap) {
229                     hRes = AtlRegisterClassCategoriesHelper(obj->pclsid, catmap, TRUE);
230                     if(FAILED(hRes))
231                         return hRes;
232                 }
233             }
234         }
235     }
236
237     if (bRegTypeLib)
238     {
239         hRes = AtlRegisterTypeLib(pM->m_hInstTypeLib, NULL);
240         if (FAILED(hRes))
241             return hRes;
242     }
243
244     return S_OK;
245 }
246
247 /***********************************************************************
248  *           AtlModuleGetClassObject              [ATL.@]
249  */
250 HRESULT WINAPI AtlModuleGetClassObject(_ATL_MODULEW *pm, REFCLSID rclsid,
251                                        REFIID riid, LPVOID *ppv)
252 {
253     _ATL_OBJMAP_ENTRYW_V1 *obj;
254     int i;
255     HRESULT hres = CLASS_E_CLASSNOTAVAILABLE;
256
257     TRACE("%p %s %s %p\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
258
259     if (pm == NULL)
260         return E_INVALIDARG;
261
262     for (i = 0; (obj = get_objmap_entry( pm, i )) != NULL; i++)
263     {
264         if (IsEqualCLSID(obj->pclsid, rclsid))
265         {
266             TRACE("found object %i\n", i);
267             if (obj->pfnGetClassObject)
268             {
269                 if (!obj->pCF)
270                     hres = obj->pfnGetClassObject(obj->pfnCreateInstance,
271                                                   &IID_IUnknown,
272                                                   (void **)&obj->pCF);
273                 if (obj->pCF)
274                     hres = IUnknown_QueryInterface(obj->pCF, riid, ppv);
275                 break;
276             }
277         }
278     }
279
280     WARN("no class object found for %s\n", debugstr_guid(rclsid));
281
282     return hres;
283 }
284
285 /***********************************************************************
286  *           AtlModuleGetClassObject              [ATL.@]
287  */
288 HRESULT WINAPI AtlModuleRegisterTypeLib(_ATL_MODULEW *pm, LPCOLESTR lpszIndex)
289 {
290     TRACE("%p %s\n", pm, debugstr_w(lpszIndex));
291
292     if (!pm)
293         return E_INVALIDARG;
294
295     return AtlRegisterTypeLib(pm->m_hInstTypeLib, lpszIndex);
296 }
297
298 /***********************************************************************
299  *           AtlModuleRevokeClassObjects          [ATL.@]
300  */
301 HRESULT WINAPI AtlModuleRevokeClassObjects(_ATL_MODULEW *pm)
302 {
303     FIXME("%p\n", pm);
304     return E_FAIL;
305 }
306
307 /***********************************************************************
308  *           AtlModuleUnregisterServer           [ATL.@]
309  */
310 HRESULT WINAPI AtlModuleUnregisterServer(_ATL_MODULEW *pm, const CLSID *clsid)
311 {
312     FIXME("%p %s\n", pm, debugstr_guid(clsid));
313     return E_FAIL;
314 }
315
316 /***********************************************************************
317  *           AtlModuleRegisterWndClassInfoA           [ATL.@]
318  *
319  * See AtlModuleRegisterWndClassInfoW.
320  */
321 ATOM WINAPI AtlModuleRegisterWndClassInfoA(_ATL_MODULEA *pm, _ATL_WNDCLASSINFOA *wci, WNDPROC *pProc)
322 {
323     ATOM atom;
324
325     FIXME("%p %p %p semi-stub\n", pm, wci, pProc);
326
327     atom = wci->m_atom;
328     if (!atom)
329     {
330         WNDCLASSEXA wc;
331
332         TRACE("wci->m_wc.lpszClassName = %s\n", wci->m_wc.lpszClassName);
333
334         if (wci->m_lpszOrigName)
335             FIXME( "subclassing %s not implemented\n", debugstr_a(wci->m_lpszOrigName));
336
337         if (!wci->m_wc.lpszClassName)
338         {
339             snprintf(wci->m_szAutoName, sizeof(wci->m_szAutoName), "ATL%08lx", (UINT_PTR)wci);
340             TRACE("auto-generated class name %s\n", wci->m_szAutoName);
341             wci->m_wc.lpszClassName = wci->m_szAutoName;
342         }
343
344         atom = GetClassInfoExA(pm->m_hInst, wci->m_wc.lpszClassName, &wc);
345         if (!atom)
346         {
347             wci->m_wc.hInstance = pm->m_hInst;
348             wci->m_wc.hCursor   = LoadCursorA( wci->m_bSystemCursor ? NULL : pm->m_hInst,
349                                                wci->m_lpszCursorID );
350             atom = RegisterClassExA(&wci->m_wc);
351         }
352         wci->pWndProc = wci->m_wc.lpfnWndProc;
353         wci->m_atom = atom;
354     }
355
356     if (wci->m_lpszOrigName) *pProc = wci->pWndProc;
357
358     TRACE("returning 0x%04x\n", atom);
359     return atom;
360 }
361
362 /***********************************************************************
363  *           AtlModuleRegisterWndClassInfoW           [ATL.@]
364  *
365  * PARAMS
366  *  pm   [IO] Information about the module registering the window.
367  *  wci  [IO] Information about the window being registered.
368  *  pProc [O] Window procedure of the registered class.
369  *
370  * RETURNS
371  *  Atom representing the registered class.
372  *
373  * NOTES
374  *  Can be called multiple times without error, unlike RegisterClassEx().
375  *
376  *  If the class name is NULL, then a class with a name of "ATLxxxxxxxx" is
377  *  registered, where the 'x's represent a unique value.
378  *
379  */
380 ATOM WINAPI AtlModuleRegisterWndClassInfoW(_ATL_MODULEW *pm, _ATL_WNDCLASSINFOW *wci, WNDPROC *pProc)
381 {
382     ATOM atom;
383
384     FIXME("%p %p %p semi-stub\n", pm, wci, pProc);
385
386     atom = wci->m_atom;
387     if (!atom)
388     {
389         WNDCLASSEXW wc;
390
391         TRACE("wci->m_wc.lpszClassName = %s\n", debugstr_w(wci->m_wc.lpszClassName));
392
393         if (wci->m_lpszOrigName)
394             FIXME( "subclassing %s not implemented\n", debugstr_w(wci->m_lpszOrigName));
395
396         if (!wci->m_wc.lpszClassName)
397         {
398             static const WCHAR szFormat[] = {'A','T','L','%','0','8','l','x',0};
399             snprintfW(wci->m_szAutoName, sizeof(wci->m_szAutoName)/sizeof(WCHAR), szFormat, (UINT_PTR)wci);
400             TRACE("auto-generated class name %s\n", debugstr_w(wci->m_szAutoName));
401             wci->m_wc.lpszClassName = wci->m_szAutoName;
402         }
403
404         atom = GetClassInfoExW(pm->m_hInst, wci->m_wc.lpszClassName, &wc);
405         if (!atom)
406         {
407             wci->m_wc.hInstance = pm->m_hInst;
408             wci->m_wc.hCursor   = LoadCursorW( wci->m_bSystemCursor ? NULL : pm->m_hInst,
409                                                wci->m_lpszCursorID );
410             atom = RegisterClassExW(&wci->m_wc);
411         }
412         wci->pWndProc = wci->m_wc.lpfnWndProc;
413         wci->m_atom = atom;
414     }
415
416     if (wci->m_lpszOrigName) *pProc = wci->pWndProc;
417
418     TRACE("returning 0x%04x\n", atom);
419     return atom;
420 }
421
422 /***********************************************************************
423  *           AtlModuleAddCreateWndData          [ATL.@]
424  */
425 void WINAPI AtlModuleAddCreateWndData(_ATL_MODULEW *pM, _AtlCreateWndData *pData, void* pvObject)
426 {
427     TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
428
429     pData->m_pThis = pvObject;
430     pData->m_dwThreadID = GetCurrentThreadId();
431
432     EnterCriticalSection(&pM->m_csWindowCreate);
433     pData->m_pNext = pM->m_pCreateWndList;
434     pM->m_pCreateWndList = pData;
435     LeaveCriticalSection(&pM->m_csWindowCreate);
436 }
437
438 /***********************************************************************
439  *           AtlModuleExtractCreateWndData      [ATL.@]
440  *
441  *  NOTE: Tests show that this function extracts one of _AtlCreateWndData
442  *        records from the current thread from a list
443  *
444  */
445 void* WINAPI AtlModuleExtractCreateWndData(_ATL_MODULEW *pM)
446 {
447     _AtlCreateWndData **ppData;
448     void *ret = NULL;
449
450     TRACE("(%p)\n", pM);
451
452     EnterCriticalSection(&pM->m_csWindowCreate);
453
454     for(ppData = &pM->m_pCreateWndList; *ppData!=NULL; ppData = &(*ppData)->m_pNext)
455     {
456         if ((*ppData)->m_dwThreadID == GetCurrentThreadId())
457         {
458             _AtlCreateWndData *pData = *ppData;
459             *ppData = pData->m_pNext;
460             ret = pData->m_pThis;
461             break;
462         }
463     }
464
465     LeaveCriticalSection(&pM->m_csWindowCreate);
466     return ret;
467 }
468
469 /***********************************************************************
470  *           AtlModuleUpdateRegistryFromResourceD         [ATL.@]
471  *
472  */
473 HRESULT WINAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULEW* pM, LPCOLESTR lpszRes,
474         BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg)
475 {
476     TRACE("(%p %s %d %p %p)\n", pM, debugstr_w(lpszRes), bRegister, pMapEntries, pReg);
477
478     return AtlUpdateRegistryFromResourceD(pM->m_hInst, lpszRes, bRegister, pMapEntries, pReg);
479 }
480
481 static HRESULT WINAPI RegistrarCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppvObject)
482 {
483     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
484
485     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
486         *ppvObject = iface;
487         IClassFactory_AddRef( iface );
488         return S_OK;
489     }
490
491     return E_NOINTERFACE;
492 }
493
494 static ULONG WINAPI RegistrarCF_AddRef(IClassFactory *iface)
495 {
496     return 2;
497 }
498
499 static ULONG WINAPI RegistrarCF_Release(IClassFactory *iface)
500 {
501     return 1;
502 }
503
504 static HRESULT WINAPI RegistrarCF_CreateInstance(IClassFactory *iface, LPUNKNOWN pUnkOuter,
505                                                 REFIID riid, void **ppv)
506 {
507     IRegistrar *registrar;
508     HRESULT hres;
509
510     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
511
512     if(pUnkOuter) {
513         *ppv = NULL;
514         return CLASS_E_NOAGGREGATION;
515     }
516
517     hres = AtlCreateRegistrar(&registrar);
518     if(FAILED(hres))
519         return hres;
520
521     hres = IRegistrar_QueryInterface(registrar, riid, ppv);
522     IRegistrar_Release(registrar);
523     return hres;
524 }
525
526 static HRESULT WINAPI RegistrarCF_LockServer(IClassFactory *iface, BOOL lock)
527 {
528     TRACE("(%p)->(%x)\n", iface, lock);
529     return S_OK;
530 }
531
532 static const IClassFactoryVtbl IRegistrarCFVtbl = {
533     RegistrarCF_QueryInterface,
534     RegistrarCF_AddRef,
535     RegistrarCF_Release,
536     RegistrarCF_CreateInstance,
537     RegistrarCF_LockServer
538 };
539
540 static IClassFactory RegistrarCF = { &IRegistrarCFVtbl };
541
542 /**************************************************************
543  * DllGetClassObject (ATL.2)
544  */
545 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, LPVOID *ppvObject)
546 {
547     TRACE("(%s %s %p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppvObject);
548
549     if(IsEqualGUID(&CLSID_Registrar, clsid))
550         return IClassFactory_QueryInterface( &RegistrarCF, riid, ppvObject );
551
552     FIXME("Not supported class %s\n", debugstr_guid(clsid));
553     return CLASS_E_CLASSNOTAVAILABLE;
554 }
555
556 /***********************************************************************
557  *              DllRegisterServer (ATL.@)
558  */
559 HRESULT WINAPI DllRegisterServer(void)
560 {
561     return __wine_register_resources( hInst );
562 }
563
564 /***********************************************************************
565  *              DllUnRegisterServer (ATL.@)
566  */
567 HRESULT WINAPI DllUnregisterServer(void)
568 {
569     return __wine_unregister_resources( hInst );
570 }
571
572 /***********************************************************************
573  *              DllCanUnloadNow (ATL.@)
574  */
575 HRESULT WINAPI DllCanUnloadNow(void)
576 {
577     return S_FALSE;
578 }
579
580 /***********************************************************************
581  *           AtlGetVersion              [ATL.@]
582  */
583 DWORD WINAPI AtlGetVersion(void *pReserved)
584 {
585    return _ATL_VER;
586 }