janitorial: Remove remaining NULL checks before free() (found by Smatch).
[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 <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "winuser.h"
30 #include "wine/debug.h"
31 #include "objbase.h"
32 #include "objidl.h"
33 #include "ole2.h"
34 #include "atlbase.h"
35 #include "atliface.h"
36 #include "atlwin.h"
37
38 #include "wine/unicode.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(atl);
41
42 HINSTANCE hInst;
43
44 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
45 {
46     TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
47
48     if (fdwReason == DLL_PROCESS_ATTACH) {
49         DisableThreadLibraryCalls(hinstDLL);
50         hInst = hinstDLL;
51     }
52     return TRUE;
53 }
54
55 #define ATLVer1Size 100
56
57 HRESULT WINAPI AtlModuleInit(_ATL_MODULEA* pM, _ATL_OBJMAP_ENTRYA* p, HINSTANCE h)
58 {
59     INT i;
60     UINT size;
61
62     FIXME("SEMI-STUB (%p %p %p)\n",pM,p,h);
63
64     size = pM->cbSize;
65     if  (size != sizeof(_ATL_MODULEA) && size != ATLVer1Size)
66     {
67         FIXME("Unknown structure version (size %i)\n",size);
68         return E_INVALIDARG;
69     }
70     
71     memset(pM,0,pM->cbSize);
72     pM->cbSize = size;
73     pM->m_hInst = h;
74     pM->m_hInstResource = h;
75     pM->m_hInstTypeLib = h;
76     pM->m_pObjMap = p;
77     pM->m_hHeap = GetProcessHeap();
78
79     InitializeCriticalSection(&pM->u.m_csTypeInfoHolder);
80     InitializeCriticalSection(&pM->m_csWindowCreate);
81     InitializeCriticalSection(&pM->m_csObjMap);
82
83     /* call mains */
84     i = 0;
85     if (pM->m_pObjMap != NULL  && size > ATLVer1Size)
86     {
87         while (pM->m_pObjMap[i].pclsid != NULL)
88         {
89             TRACE("Initializing object %i %p\n",i,p[i].pfnObjectMain);
90             if (p[i].pfnObjectMain)
91                 p[i].pfnObjectMain(TRUE);
92             i++;
93         }
94     }
95
96     return S_OK;
97 }
98
99 HRESULT WINAPI AtlModuleLoadTypeLib(_ATL_MODULEA *pM, LPCOLESTR lpszIndex, 
100                                     BSTR *pbstrPath, ITypeLib **ppTypeLib)
101 {
102     FIXME("(%p, %s, %p, %p): stub\n", pM, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
103     return E_FAIL;
104 }
105
106 HRESULT WINAPI AtlModuleTerm(_ATL_MODULEA* pM)
107 {
108     _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
109
110     TRACE("(%p)\n", pM);
111
112     while(iter) {
113         iter->pFunc(iter->dw);
114         tmp = iter;
115         iter = iter->pNext;
116         HeapFree(GetProcessHeap(), 0, tmp);
117     }
118
119     HeapFree(GetProcessHeap(), 0, pM);
120
121     return S_OK;
122 }
123
124 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULEW *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
125 {
126     _ATL_TERMFUNC_ELEM *termfunc_elem;
127
128     TRACE("(%p %p %ld)\n", pM, pFunc, dw);
129
130     termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
131     termfunc_elem->pFunc = pFunc;
132     termfunc_elem->dw = dw;
133     termfunc_elem->pNext = pM->m_pTermFuncs;
134
135     pM->m_pTermFuncs = termfunc_elem;
136
137     return S_OK;
138 }
139
140 HRESULT WINAPI AtlModuleRegisterClassObjects(_ATL_MODULEA *pM, DWORD dwClsContext,
141                                              DWORD dwFlags)
142 {
143     HRESULT hRes = S_OK;
144     int i=0;
145
146     TRACE("(%p %i %i)\n",pM, dwClsContext, dwFlags);
147
148     if (pM == NULL)
149         return E_INVALIDARG;
150
151     while(pM->m_pObjMap[i].pclsid != NULL)
152     {
153         IUnknown* pUnknown;
154         _ATL_OBJMAP_ENTRYA *obj = &(pM->m_pObjMap[i]);
155         HRESULT rc;
156
157         TRACE("Registering object %i\n",i);
158         if (obj->pfnGetClassObject)
159         {
160             rc = obj->pfnGetClassObject(obj->pfnCreateInstance, &IID_IUnknown,
161                                    (LPVOID*)&pUnknown);
162             if (SUCCEEDED (rc) )
163             {
164                 CoRegisterClassObject(obj->pclsid, pUnknown, dwClsContext,
165                                       dwFlags, &obj->dwRegister);
166                 if (pUnknown)
167                     IUnknown_Release(pUnknown);
168             }
169         }
170         i++;
171     }
172
173    return hRes;
174 }
175
176 HRESULT WINAPI AtlModuleUnregisterServerEx(_ATL_MODULEA* pM, BOOL bUnRegTypeLib, const CLSID* pCLSID)
177 {
178     FIXME("(%p, %i, %p) stub\n", pM, bUnRegTypeLib, pCLSID);
179     return S_OK;
180 }
181
182 /***********************************************************************
183  *           AtlAxWinInit          [ATL.@]
184  * Initializes the control-hosting code: registering the AtlAxWin7 and AtlAxWinLic7 window
185  * classes and some messages.
186  *  
187  * RETURNS
188  *  TRUE or FALSE
189  */
190
191 BOOL WINAPI AtlAxWinInit(void)
192 {
193     FIXME("Try use native atl.dll if possible\n");
194     return FALSE;
195 }
196
197
198 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
199 {
200     TRACE("(%p %p)\n", pp, p);
201
202     if (p) IUnknown_AddRef(p);
203     if (*pp) IUnknown_Release(*pp);
204     *pp = p;
205     return p;
206 }
207
208
209 HRESULT WINAPI AtlInternalQueryInterface(LPVOID this, const _ATL_INTMAP_ENTRY* pEntries,  REFIID iid, LPVOID* ppvObject)
210 {
211     int i = 0;
212     HRESULT rc = E_NOINTERFACE;
213     TRACE("(%p, %p, %p, %p)\n",this, pEntries, iid, ppvObject);
214
215     if (IsEqualGUID(iid,&IID_IUnknown))
216     {
217         TRACE("Returning IUnknown\n");
218         *ppvObject = this;
219         IUnknown_AddRef((IUnknown*)this);
220         return S_OK;
221     }
222
223     while (pEntries[i].pFunc != 0)
224     {
225         TRACE("Trying entry %i (%p %i %p)\n",i,pEntries[i].piid,
226               pEntries[i].dw, pEntries[i].pFunc);
227
228         if (pEntries[i].piid && IsEqualGUID(iid,pEntries[i].piid))
229         {
230             TRACE("MATCH\n");
231             if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
232             {
233                 TRACE("Offset\n");
234                 *ppvObject = ((LPSTR)this+pEntries[i].dw);
235                 IUnknown_AddRef((IUnknown*)this);
236                 rc = S_OK;
237             }
238             else
239             {
240                 TRACE("Function\n");
241                 rc = pEntries[i].pFunc(this, iid, ppvObject,0);
242             }
243             break;
244         }
245         i++;
246     }
247     TRACE("Done returning (0x%x)\n",rc);
248     return rc;
249 }
250
251 /***********************************************************************
252  *           AtlModuleRegisterServer         [ATL.@]
253  *
254  */
255 HRESULT WINAPI AtlModuleRegisterServer(_ATL_MODULEW* pM, BOOL bRegTypeLib, const CLSID* clsid) 
256 {
257     FIXME("%p %d %s\n", pM, bRegTypeLib, debugstr_guid(clsid));
258     return S_OK;
259 }
260
261 /***********************************************************************
262  *           AtlAdvise         [ATL.@]
263  */
264 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, LPDWORD pdw)
265 {
266     FIXME("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
267     return E_FAIL;
268 }
269
270 /***********************************************************************
271  *           AtlUnadvise         [ATL.@]
272  */
273 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
274 {
275     FIXME("%p %p %d\n", pUnkCP, iid, dw);
276     return S_OK;
277 }
278
279 /***********************************************************************
280  *           AtlFreeMarshalStream         [ATL.@]
281  */
282 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
283 {
284     FIXME("%p\n", stm);
285     return S_OK;
286 }
287
288 /***********************************************************************
289  *           AtlMarshalPtrInProc         [ATL.@]
290  */
291 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
292 {
293     FIXME("%p %p %p\n", pUnk, iid, pstm);
294     return E_FAIL;
295 }
296
297 /***********************************************************************
298  *           AtlUnmarshalPtr              [ATL.@]
299  */
300 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
301 {
302     FIXME("%p %p %p\n", stm, iid, ppUnk);
303     return E_FAIL;
304 }
305
306 /***********************************************************************
307  *           AtlModuleGetClassObject              [ATL.@]
308  */
309 HRESULT WINAPI AtlModuleGetClassObject(_ATL_MODULEW *pm, REFCLSID rclsid,
310                                        REFIID riid, LPVOID *ppv)
311 {
312     int i;
313
314     TRACE("%p %s %s %p\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
315
316     if (pm == NULL)
317         return E_INVALIDARG;
318
319     for (i = 0; pm->m_pObjMap[i].pclsid != NULL; i++)
320     {
321         if (IsEqualCLSID(pm->m_pObjMap[i].pclsid, rclsid))
322         {
323             _ATL_OBJMAP_ENTRYW *obj = &pm->m_pObjMap[i];
324
325             TRACE("found object %i\n", i);
326             if (obj->pfnGetClassObject)
327                 return obj->pfnGetClassObject(obj->pfnCreateInstance, riid, ppv);
328         }
329     }
330
331     WARN("no class object found for %s\n", debugstr_guid(rclsid));
332
333     return E_FAIL;
334 }
335
336 /***********************************************************************
337  *           AtlModuleGetClassObject              [ATL.@]
338  */
339 HRESULT WINAPI AtlModuleRegisterTypeLib(_ATL_MODULEW *pm, LPCOLESTR lpszIndex)
340 {
341     FIXME("%p %s\n", pm, debugstr_w(lpszIndex));
342     return E_FAIL;
343 }
344
345 /***********************************************************************
346  *           AtlModuleRevokeClassObjects          [ATL.@]
347  */
348 HRESULT WINAPI AtlModuleRevokeClassObjects(_ATL_MODULEW *pm)
349 {
350     FIXME("%p\n", pm);
351     return E_FAIL;
352 }
353
354 /***********************************************************************
355  *           AtlModuleUnregisterServer           [ATL.@]
356  */
357 HRESULT WINAPI AtlModuleUnregisterServer(_ATL_MODULEW *pm, const CLSID *clsid)
358 {
359     FIXME("%p %s\n", pm, debugstr_guid(clsid));
360     return E_FAIL;
361 }
362
363 /***********************************************************************
364  *           AtlAxCreateControl           [ATL.@]
365  */
366 HRESULT WINAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd,
367         IStream *pStream, IUnknown **ppUnkContainer)
368 {
369     FIXME("%s %p %p %p)\n", debugstr_w(lpszName), hWnd, pStream, ppUnkContainer);
370     return E_NOTIMPL;
371 }
372
373 /***********************************************************************
374  *           AtlModuleRegisterWndClassInfoW           [ATL.@]
375  *
376  * PARAMS
377  *  pm   [IO] Information about the module registering the window.
378  *  wci  [IO] Information about the window being registered.
379  *  pProc [O] Window procedure of the registered class.
380  *
381  * RETURNS
382  *  Atom representing the registered class.
383  *
384  * NOTES
385  *  Can be called multiple times without error, unlike RegisterClassEx().
386  *
387  *  If the class name is NULL then it a class with a name of "ATLxxxxxxxx" is
388  *  registered, where the x's represent an unique value.
389  *  
390  */
391 ATOM WINAPI AtlModuleRegisterWndClassInfoW(_ATL_MODULEW *pm, _ATL_WNDCLASSINFOW *wci, WNDPROC *pProc)
392 {
393     ATOM atom;
394
395     FIXME("%p %p %p semi-stub\n", pm, wci, pProc);
396
397     atom = wci->m_atom;
398     if (!atom)
399     {
400         WNDCLASSEXW wc;
401
402         TRACE("wci->m_wc.lpszClassName = %s\n", debugstr_w(wci->m_wc.lpszClassName));
403
404         if (!wci->m_wc.lpszClassName)
405         {
406             static const WCHAR szFormat[] = {'A','T','L','%','0','8','x',0};
407             sprintfW(wci->m_szAutoName, szFormat, (UINT)(UINT_PTR)wci);
408             TRACE("auto-generated class name %s\n", debugstr_w(wci->m_szAutoName));
409             wci->m_wc.lpszClassName = wci->m_szAutoName;
410         }
411
412         atom = GetClassInfoExW(pm->m_hInst, wci->m_wc.lpszClassName, &wc);
413         if (!atom)
414             atom = RegisterClassExW(&wci->m_wc);
415
416         wci->pWndProc = wci->m_wc.lpfnWndProc;
417         wci->m_atom = atom;
418     }
419     *pProc = wci->pWndProc;
420
421     TRACE("returning 0x%04x\n", atom);
422     return atom;
423 }