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