Prevent possible NULL pointer access.
[wine] / dlls / commdlg / cdlg32.c
1 /*
2  *  Common Dialog Boxes interface (32 bit)
3  *  Find/Replace
4  *
5  * Copyright 1999 Bertho A. Stultiens
6  */
7
8 #include "winbase.h"
9 #include "wine/winbase16.h"
10 #include "commdlg.h"
11 #include "cderr.h"
12 #include "debugtools.h"
13
14 DEFAULT_DEBUG_CHANNEL(commdlg);
15
16 #include "cdlg.h"
17
18
19 HINSTANCE       COMDLG32_hInstance = 0;
20 HINSTANCE16     COMDLG32_hInstance16 = 0;
21
22 static DWORD    COMDLG32_TlsIndex;
23 static int      COMDLG32_Attach = 0;
24
25 HINSTANCE       COMCTL32_hInstance = 0;
26 HINSTANCE       SHELL32_hInstance = 0;
27 HINSTANCE       SHLWAPI_hInstance = 0;
28
29 /* IMAGELIST */
30 BOOL    (WINAPI* COMDLG32_ImageList_Draw) (HIMAGELIST himl, int i, HDC hdcDest, int x, int y, UINT fStyle);
31
32 /* ITEMIDLIST */
33 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILClone) (LPCITEMIDLIST);
34 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
35 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILGetNext)(LPITEMIDLIST);
36 BOOL (WINAPI *COMDLG32_PIDL_ILRemoveLastID)(LPCITEMIDLIST);
37 BOOL (WINAPI *COMDLG32_PIDL_ILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
38
39 /* SHELL */
40 BOOL (WINAPI *COMDLG32_SHGetPathFromIDListA) (LPCITEMIDLIST,LPSTR);
41 HRESULT (WINAPI *COMDLG32_SHGetSpecialFolderLocation)(HWND,INT,LPITEMIDLIST *);
42 DWORD (WINAPI *COMDLG32_SHGetDesktopFolder)(IShellFolder **);
43 DWORD   (WINAPI *COMDLG32_SHGetFileInfoA)(LPCSTR,DWORD,SHFILEINFOA*,UINT,UINT);
44 LPVOID (WINAPI *COMDLG32_SHAlloc)(DWORD);
45 DWORD (WINAPI *COMDLG32_SHFree)(LPVOID);
46 HRESULT (WINAPI *COMDLG32_StrRetToBufA)(LPSTRRET,LPITEMIDLIST,LPSTR,DWORD);
47 HRESULT (WINAPI *COMDLG32_StrRetToBufW)(LPSTRRET,LPITEMIDLIST,LPWSTR,DWORD);
48
49 /* PATH */
50 BOOL (WINAPI *COMDLG32_PathIsRootA)(LPCSTR x);
51 LPCSTR (WINAPI *COMDLG32_PathFindFilenameA)(LPCSTR path);
52 DWORD (WINAPI *COMDLG32_PathRemoveFileSpecA)(LPSTR fn);
53 BOOL (WINAPI *COMDLG32_PathMatchSpecW)(LPCWSTR x, LPCWSTR y);
54 LPSTR (WINAPI *COMDLG32_PathAddBackslashA)(LPSTR path);
55
56 /***********************************************************************
57  *      COMDLG32_DllEntryPoint                  (COMDLG32.entry)
58  *
59  *    Initialization code for the COMDLG32 DLL
60  *
61  * RETURNS:
62  *      FALSE if sibling could not be loaded or instantiated twice, TRUE
63  *      otherwise.
64  */
65 BOOL WINAPI COMDLG32_DllEntryPoint(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
66 {
67         TRACE("(%08x, %08lx, %p)\n", hInstance, Reason, Reserved);
68
69         switch(Reason)
70         {
71         case DLL_PROCESS_ATTACH:
72                 COMDLG32_Attach++;
73                 if(COMDLG32_hInstance)
74                 {
75                         ERR("comdlg32.dll instantiated twice in one address space!\n");
76                         /*
77                          * We should return FALSE here, but that will break
78                          * most apps that use CreateProcess because we do
79                          * not yet support seperate address spaces.
80                          */
81                         return TRUE;
82                 }
83
84                 COMDLG32_hInstance = hInstance;
85                 DisableThreadLibraryCalls(hInstance);
86
87                 if(!COMDLG32_hInstance16)
88                 {
89                         if(!(COMDLG32_hInstance16 = LoadLibrary16("commdlg.dll")))
90                         {
91                                 ERR("Could not load sibling commdlg.dll\n");
92                                 return FALSE;
93                         }
94                 }
95
96                 COMDLG32_TlsIndex = 0xffffffff;
97
98                 COMCTL32_hInstance = LoadLibraryA("COMCTL32.DLL");      
99                 SHELL32_hInstance = LoadLibraryA("SHELL32.DLL");
100                 SHLWAPI_hInstance = LoadLibraryA("SHLWAPI.DLL");
101                 
102                 if (!COMCTL32_hInstance || !SHELL32_hInstance || !SHLWAPI_hInstance)
103                 {
104                         ERR("loading of comctl32 or shell32 or shlwapi failed\n");
105                         return FALSE;
106                 }
107
108                 /* IMAGELIST */
109                 COMDLG32_ImageList_Draw=(void*)GetProcAddress(COMCTL32_hInstance,"ImageList_Draw");
110                 
111                 /* ITEMISLIST */
112                 
113                 COMDLG32_PIDL_ILIsEqual =(void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)21L);
114                 COMDLG32_PIDL_ILCombine =(void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)25L);
115                 COMDLG32_PIDL_ILGetNext =(void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)153L);
116                 COMDLG32_PIDL_ILClone =(void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)18L);
117                 COMDLG32_PIDL_ILRemoveLastID =(void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)17L);
118                 
119                 /* SHELL */
120                 
121                 COMDLG32_SHAlloc = (void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)196L);
122                 COMDLG32_SHFree = (void*)GetProcAddress(SHELL32_hInstance, (LPCSTR)195L);
123                 COMDLG32_SHGetSpecialFolderLocation = (void*)GetProcAddress(SHELL32_hInstance,"SHGetSpecialFolderLocation");
124                 COMDLG32_SHGetPathFromIDListA = (void*)GetProcAddress(SHELL32_hInstance,"SHGetPathFromIDListA");
125                 COMDLG32_SHGetDesktopFolder = (void*)GetProcAddress(SHELL32_hInstance,"SHGetDesktopFolder");
126                 COMDLG32_SHGetFileInfoA = (void*)GetProcAddress(SHELL32_hInstance,"SHGetFileInfoA");
127
128                 /* ### WARINIG ### 
129                 We can't do a GetProcAddress to link to  StrRetToBuf[A|W] sine not all 
130                 versions of the shlwapi are exporting these functions. When we are 
131                 seperating the dlls then we have to dublicate code from shell32 into comdlg32. 
132                 Till then just call these functions. These functions don't have any side effects 
133                 so it won't break the use of any combination of native and buildin dll's (jsch) */
134
135                 /* PATH */
136                 COMDLG32_PathMatchSpecW = (void*)GetProcAddress(SHLWAPI_hInstance,"PathMatchSpecW");
137                 COMDLG32_PathIsRootA = (void*)GetProcAddress(SHLWAPI_hInstance,"PathIsRootA");
138                 COMDLG32_PathRemoveFileSpecA = (void*)GetProcAddress(SHLWAPI_hInstance,"PathRemoveFileSpecA");
139                 COMDLG32_PathFindFilenameA = (void*)GetProcAddress(SHLWAPI_hInstance,"PathFindFileNameA");
140                 COMDLG32_PathAddBackslashA = (void*)GetProcAddress(SHLWAPI_hInstance,"PathAddBackslashA");
141                 break;
142
143         case DLL_PROCESS_DETACH:
144                 if(!--COMDLG32_Attach)
145                 {
146                         if (COMDLG32_TlsIndex != 0xffffffff)
147                           TlsFree(COMDLG32_TlsIndex);
148                         COMDLG32_TlsIndex = 0xffffffff;
149                         COMDLG32_hInstance = 0;
150                         if(COMDLG32_hInstance16)
151                                 FreeLibrary16(COMDLG32_hInstance16);
152
153                 }
154                 FreeLibrary(COMCTL32_hInstance);
155                 FreeLibrary(SHELL32_hInstance);
156                 FreeLibrary(SHLWAPI_hInstance);
157                 break;
158         }
159         return TRUE;
160 }
161
162
163 /***********************************************************************
164  *      COMDLG32_AllocMem                       (internal)
165  * Get memory for internal datastructure plus stringspace etc.
166  *      RETURNS
167  *              Pointer to a heap block: Succes
168  *              NULL: Failure
169  */
170 LPVOID COMDLG32_AllocMem(
171         int size        /* [in] Block size to allocate */
172 ) {
173         LPVOID ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
174         if(!ptr)
175         {
176                 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
177                 return NULL;
178         }
179         return ptr;
180 }
181
182
183 /***********************************************************************
184  *      COMDLG32_SetCommDlgExtendedError        (internal)
185  *
186  * Used to set the thread's local error value if a comdlg32 function fails.
187  */
188 void COMDLG32_SetCommDlgExtendedError(DWORD err)
189 {
190         TRACE("(%08lx)\n", err);
191         if (COMDLG32_TlsIndex == 0xffffffff)
192           COMDLG32_TlsIndex = TlsAlloc();
193         if (COMDLG32_TlsIndex != 0xffffffff)
194           TlsSetValue(COMDLG32_TlsIndex, (void *)err);
195         else
196           FIXME("No Tls Space\n");
197 }
198
199
200 /***********************************************************************
201  *      CommDlgExtendedError                    (COMDLG32.5)
202  *
203  * Get the thread's local error value if a comdlg32 function fails.
204  *      RETURNS
205  *              Current error value which might not be valid
206  *              if a previous call succeeded.
207  */
208 DWORD WINAPI CommDlgExtendedError(void)
209 {
210         if (COMDLG32_TlsIndex != 0xffffffff) 
211           return (DWORD)TlsGetValue(COMDLG32_TlsIndex);
212         else
213           {
214             FIXME("No Tls Space\n");
215             return 0;
216           }
217 }