include: Assorted spelling fixes.
[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     TRACE("(%p, %s, %p, %p)\n", pM, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
115
116     if (!pM)
117         return E_INVALIDARG;
118
119     return AtlLoadTypeLib(pM->m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib);
120 }
121
122 HRESULT WINAPI AtlModuleTerm(_ATL_MODULE *pM)
123 {
124     _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
125
126     TRACE("(%p)\n", pM);
127
128     while(iter) {
129         iter->pFunc(iter->dw);
130         tmp = iter;
131         iter = iter->pNext;
132         HeapFree(GetProcessHeap(), 0, tmp);
133     }
134
135     return S_OK;
136 }
137
138 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULEW *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
139 {
140     _ATL_TERMFUNC_ELEM *termfunc_elem;
141
142     TRACE("(%p %p %ld)\n", pM, pFunc, dw);
143
144     termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
145     termfunc_elem->pFunc = pFunc;
146     termfunc_elem->dw = dw;
147     termfunc_elem->pNext = pM->m_pTermFuncs;
148
149     pM->m_pTermFuncs = termfunc_elem;
150
151     return S_OK;
152 }
153
154 HRESULT WINAPI AtlModuleRegisterClassObjects(_ATL_MODULEW *pM, DWORD dwClsContext,
155                                              DWORD dwFlags)
156 {
157     _ATL_OBJMAP_ENTRYW_V1 *obj;
158     int i=0;
159
160     TRACE("(%p %i %i)\n",pM, dwClsContext, dwFlags);
161
162     if (pM == NULL)
163         return E_INVALIDARG;
164
165     while ((obj = get_objmap_entry( pM, i++ )))
166     {
167         IUnknown* pUnknown;
168         HRESULT rc;
169
170         TRACE("Registering object %i\n",i);
171         if (obj->pfnGetClassObject)
172         {
173             rc = obj->pfnGetClassObject(obj->pfnCreateInstance, &IID_IUnknown,
174                                    (LPVOID*)&pUnknown);
175             if (SUCCEEDED (rc) )
176             {
177                 rc = CoRegisterClassObject(obj->pclsid, pUnknown, dwClsContext,
178                                            dwFlags, &obj->dwRegister);
179
180                 if (FAILED (rc) )
181                     WARN("Failed to register object %i: 0x%08x\n", i, rc);
182
183                 if (pUnknown)
184                     IUnknown_Release(pUnknown);
185             }
186         }
187     }
188
189    return S_OK;
190 }
191
192 HRESULT WINAPI AtlModuleUnregisterServerEx(_ATL_MODULEW* pM, BOOL bUnRegTypeLib, const CLSID* pCLSID)
193 {
194     FIXME("(%p, %i, %p) stub\n", pM, bUnRegTypeLib, pCLSID);
195     return S_OK;
196 }
197
198 /***********************************************************************
199  *           AtlModuleRegisterServer         [ATL.@]
200  *
201  */
202 HRESULT WINAPI AtlModuleRegisterServer(_ATL_MODULEW* pM, BOOL bRegTypeLib, const CLSID* clsid)
203 {
204     const _ATL_OBJMAP_ENTRYW_V1 *obj;
205     int i;
206     HRESULT hRes;
207
208     TRACE("%p %d %s\n", pM, bRegTypeLib, debugstr_guid(clsid));
209
210     if (pM == NULL)
211         return E_INVALIDARG;
212
213     for (i = 0; (obj = get_objmap_entry( pM, i )) != NULL; i++) /* register CLSIDs */
214     {
215         if (!clsid || IsEqualCLSID(obj->pclsid, clsid))
216         {
217             TRACE("Registering clsid %s\n", debugstr_guid(obj->pclsid));
218             hRes = obj->pfnUpdateRegistry(TRUE); /* register */
219             if (FAILED(hRes))
220                 return hRes;
221         }
222     }
223
224     if (bRegTypeLib)
225     {
226         hRes = AtlModuleRegisterTypeLib(pM, NULL);
227         if (FAILED(hRes))
228             return hRes;
229     }
230
231     return S_OK;
232 }
233
234 /***********************************************************************
235  *           AtlModuleGetClassObject              [ATL.@]
236  */
237 HRESULT WINAPI AtlModuleGetClassObject(_ATL_MODULEW *pm, REFCLSID rclsid,
238                                        REFIID riid, LPVOID *ppv)
239 {
240     _ATL_OBJMAP_ENTRYW_V1 *obj;
241     int i;
242     HRESULT hres = CLASS_E_CLASSNOTAVAILABLE;
243
244     TRACE("%p %s %s %p\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
245
246     if (pm == NULL)
247         return E_INVALIDARG;
248
249     for (i = 0; (obj = get_objmap_entry( pm, i )) != NULL; i++)
250     {
251         if (IsEqualCLSID(obj->pclsid, rclsid))
252         {
253             TRACE("found object %i\n", i);
254             if (obj->pfnGetClassObject)
255             {
256                 if (!obj->pCF)
257                     hres = obj->pfnGetClassObject(obj->pfnCreateInstance,
258                                                   &IID_IUnknown,
259                                                   (void **)&obj->pCF);
260                 if (obj->pCF)
261                     hres = IUnknown_QueryInterface(obj->pCF, riid, ppv);
262                 break;
263             }
264         }
265     }
266
267     WARN("no class object found for %s\n", debugstr_guid(rclsid));
268
269     return hres;
270 }
271
272 /***********************************************************************
273  *           AtlModuleGetClassObject              [ATL.@]
274  */
275 HRESULT WINAPI AtlModuleRegisterTypeLib(_ATL_MODULEW *pm, LPCOLESTR lpszIndex)
276 {
277     HRESULT hRes;
278     BSTR path;
279     ITypeLib *typelib;
280
281     TRACE("%p %s\n", pm, debugstr_w(lpszIndex));
282
283     if (!pm)
284         return E_INVALIDARG;
285
286     hRes = AtlModuleLoadTypeLib(pm, lpszIndex, &path, &typelib);
287
288     if (SUCCEEDED(hRes))
289     {
290         hRes = RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */
291         ITypeLib_Release(typelib);
292         SysFreeString(path);
293     }
294
295     return hRes;
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     pData->m_pNext = pM->m_pCreateWndList;
432     pM->m_pCreateWndList = pData;
433 }
434
435 /***********************************************************************
436  *           AtlModuleExtractCreateWndData      [ATL.@]
437  *
438  *  NOTE: I failed to find any good description of this function.
439  *        Tests show that this function extracts one of _AtlCreateWndData
440  *        records from the current thread from a list
441  *
442  */
443 void* WINAPI AtlModuleExtractCreateWndData(_ATL_MODULEW *pM)
444 {
445     _AtlCreateWndData **ppData;
446
447     TRACE("(%p)\n", pM);
448
449     for(ppData = &pM->m_pCreateWndList; *ppData!=NULL; ppData = &(*ppData)->m_pNext)
450     {
451         if ((*ppData)->m_dwThreadID == GetCurrentThreadId())
452         {
453             _AtlCreateWndData *pData = *ppData;
454             *ppData = pData->m_pNext;
455             return pData->m_pThis;
456         }
457     }
458     return NULL;
459 }
460
461 /***********************************************************************
462  *           AtlGetVersion              [ATL.@]
463  */
464 DWORD WINAPI AtlGetVersion(void *pReserved)
465 {
466    return _ATL_VER;
467 }