Cleaned up a few inter-dll dependencies. Added a few imports.
[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 HINSTANCE       SHFOLDER_hInstance = 0;
29
30 /* IMAGELIST */
31 BOOL (WINAPI* COMDLG32_ImageList_Draw) (HIMAGELIST himl, int i, HDC hdcDest, int x, int y, UINT fStyle);
32
33 /* ITEMIDLIST */
34 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILClone) (LPCITEMIDLIST);
35 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
36 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILGetNext)(LPITEMIDLIST);
37 BOOL (WINAPI *COMDLG32_PIDL_ILRemoveLastID)(LPCITEMIDLIST);
38 BOOL (WINAPI *COMDLG32_PIDL_ILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
39
40 /* SHELL */
41 BOOL (WINAPI *COMDLG32_SHGetPathFromIDListA) (LPCITEMIDLIST,LPSTR);
42 HRESULT (WINAPI *COMDLG32_SHGetSpecialFolderLocation)(HWND,INT,LPITEMIDLIST *);
43 DWORD (WINAPI *COMDLG32_SHGetDesktopFolder)(IShellFolder **);
44 DWORD (WINAPI *COMDLG32_SHGetFileInfoA)(LPCSTR,DWORD,SHFILEINFOA*,UINT,UINT);
45 LPVOID (WINAPI *COMDLG32_SHAlloc)(DWORD);
46 DWORD (WINAPI *COMDLG32_SHFree)(LPVOID);
47 HRESULT (WINAPI *COMDLG32_SHGetDataFromIDListA)(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, int nFormat, LPVOID dest, int len);
48 HRESULT (WINAPI *COMDLG32_StrRetToBufA)(LPSTRRET,LPITEMIDLIST,LPSTR,DWORD);
49 HRESULT (WINAPI *COMDLG32_StrRetToBufW)(LPSTRRET,LPITEMIDLIST,LPWSTR,DWORD);
50 BOOL (WINAPI *COMDLG32_SHGetFolderPathA)(HWND,int,HANDLE,DWORD,LPSTR);
51
52 /* PATH */
53 BOOL (WINAPI *COMDLG32_PathIsRootA)(LPCSTR x);
54 LPSTR (WINAPI *COMDLG32_PathFindFileNameA)(LPCSTR path);
55 DWORD (WINAPI *COMDLG32_PathRemoveFileSpecA)(LPSTR fn);
56 BOOL (WINAPI *COMDLG32_PathMatchSpecW)(LPCWSTR x, LPCWSTR y);
57 LPSTR (WINAPI *COMDLG32_PathAddBackslashA)(LPSTR path);
58 BOOL (WINAPI *COMDLG32_PathCanonicalizeA)(LPSTR pszBuf, LPCSTR pszPath);
59 int (WINAPI *COMDLG32_PathGetDriveNumberA)(LPCSTR lpszPath);
60 BOOL (WINAPI *COMDLG32_PathIsRelativeA) (LPCSTR lpszPath);
61 LPSTR (WINAPI *COMDLG32_PathFindNextComponentA)(LPCSTR pszPath);
62 LPWSTR (WINAPI *COMDLG32_PathAddBackslashW)(LPWSTR lpszPath);
63 LPSTR (WINAPI *COMDLG32_PathFindExtensionA)(LPCVOID lpszPath);
64 BOOL (WINAPI *COMDLG32_PathAddExtensionA)(LPSTR  pszPath,LPCSTR pszExtension);
65
66 /***********************************************************************
67  *      COMDLG32_DllEntryPoint                  (COMDLG32.entry)
68  *
69  *    Initialization code for the COMDLG32 DLL
70  *
71  * RETURNS:
72  *      FALSE if sibling could not be loaded or instantiated twice, TRUE
73  *      otherwise.
74  */
75 static char * GPA_string = "Failed to get entry point %s for hinst = 0x%08x\n";
76 #define GPA(dest, hinst, name) \
77         if(!(dest = (void*)GetProcAddress(hinst,name)))\
78         { \
79           ERR(GPA_string, debugres_a(name), hinst); \
80           return FALSE; \
81         }
82
83 BOOL WINAPI COMDLG32_DllEntryPoint(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
84 {
85         TRACE("(%08x, %08lx, %p)\n", hInstance, Reason, Reserved);
86
87         switch(Reason)
88         {
89         case DLL_PROCESS_ATTACH:
90                 COMDLG32_Attach++;
91                 if(COMDLG32_hInstance)
92                 {
93                         ERR("comdlg32.dll instantiated twice in one address space!\n");
94                         /*
95                          * We should return FALSE here, but that will break
96                          * most apps that use CreateProcess because we do
97                          * not yet support seperate address spaces.
98                          */
99                         return TRUE;
100                 }
101
102                 COMDLG32_hInstance = hInstance;
103                 DisableThreadLibraryCalls(hInstance);
104
105                 if(!COMDLG32_hInstance16)
106                 {
107                         if(!(COMDLG32_hInstance16 = LoadLibrary16("commdlg.dll")))
108                         {
109                                 ERR("Could not load sibling commdlg.dll\n");
110                                 return FALSE;
111                         }
112                 }
113
114                 COMDLG32_TlsIndex = 0xffffffff;
115
116                 COMCTL32_hInstance = GetModuleHandleA("COMCTL32.DLL");  
117                 SHELL32_hInstance = GetModuleHandleA("SHELL32.DLL");
118                 SHLWAPI_hInstance = GetModuleHandleA("SHLWAPI.DLL");
119                 
120                 if (!COMCTL32_hInstance || !SHELL32_hInstance || !SHLWAPI_hInstance)
121                 {
122                         ERR("loading of comctl32 or shell32 or shlwapi failed\n");
123                         return FALSE;
124                 }
125
126                 /* IMAGELIST */
127                 GPA(COMDLG32_ImageList_Draw, COMCTL32_hInstance,"ImageList_Draw");
128                 
129                 /* ITEMIDLIST */
130                 GPA(COMDLG32_PIDL_ILIsEqual, SHELL32_hInstance, (LPCSTR)21L);
131                 GPA(COMDLG32_PIDL_ILCombine, SHELL32_hInstance, (LPCSTR)25L);
132                 GPA(COMDLG32_PIDL_ILGetNext, SHELL32_hInstance, (LPCSTR)153L);
133                 GPA(COMDLG32_PIDL_ILClone, SHELL32_hInstance, (LPCSTR)18L);
134                 GPA(COMDLG32_PIDL_ILRemoveLastID, SHELL32_hInstance, (LPCSTR)17L);
135                 
136                 /* SHELL */
137                 
138                 GPA(COMDLG32_SHAlloc, SHELL32_hInstance, (LPCSTR)196L);
139                 GPA(COMDLG32_SHFree, SHELL32_hInstance, (LPCSTR)195L);
140                 GPA(COMDLG32_SHGetSpecialFolderLocation, SHELL32_hInstance,"SHGetSpecialFolderLocation");
141                 GPA(COMDLG32_SHGetPathFromIDListA, SHELL32_hInstance,"SHGetPathFromIDListA");
142                 GPA(COMDLG32_SHGetDesktopFolder, SHELL32_hInstance,"SHGetDesktopFolder");
143                 GPA(COMDLG32_SHGetFileInfoA, SHELL32_hInstance,"SHGetFileInfoA");
144                 GPA(COMDLG32_SHGetDataFromIDListA, SHELL32_hInstance,"SHGetDataFromIDListA");
145
146                 /* for the first versions of shell32 SHGetFolderPathA is in SHFOLDER.DLL */
147                 COMDLG32_SHGetFolderPathA = (void*)GetProcAddress(SHELL32_hInstance,"SHGetFolderPathA");
148                 if (!COMDLG32_SHGetFolderPathA)
149                 {
150                   SHFOLDER_hInstance = LoadLibraryA("SHFOLDER.DLL");
151                   GPA(COMDLG32_SHGetFolderPathA, SHFOLDER_hInstance,"SHGetFolderPathA");
152                 }
153
154                 /* ### WARINIG ### 
155                 We can't do a GetProcAddress to link to  StrRetToBuf[A|W] sine not all 
156                 versions of the shlwapi are exporting these functions. When we are 
157                 seperating the dlls then we have to dublicate code from shell32 into comdlg32. 
158                 Till then just call these functions. These functions don't have any side effects 
159                 so it won't break the use of any combination of native and buildin dll's (jsch) */
160
161                 /* PATH */
162                 GPA(COMDLG32_PathMatchSpecW, SHLWAPI_hInstance,"PathMatchSpecW");
163                 GPA(COMDLG32_PathIsRootA, SHLWAPI_hInstance,"PathIsRootA");
164                 GPA(COMDLG32_PathRemoveFileSpecA, SHLWAPI_hInstance,"PathRemoveFileSpecA");
165                 GPA(COMDLG32_PathFindFileNameA, SHLWAPI_hInstance,"PathFindFileNameA");
166                 GPA(COMDLG32_PathAddBackslashA, SHLWAPI_hInstance,"PathAddBackslashA");
167                 GPA(COMDLG32_PathCanonicalizeA, SHLWAPI_hInstance,"PathCanonicalizeA");
168                 GPA(COMDLG32_PathGetDriveNumberA, SHLWAPI_hInstance,"PathGetDriveNumberA");
169                 GPA(COMDLG32_PathIsRelativeA, SHLWAPI_hInstance,"PathIsRelativeA");
170                 GPA(COMDLG32_PathFindNextComponentA, SHLWAPI_hInstance,"PathFindNextComponentA");
171                 GPA(COMDLG32_PathAddBackslashW, SHLWAPI_hInstance,"PathAddBackslashW");
172                 GPA(COMDLG32_PathFindExtensionA, SHLWAPI_hInstance,"PathFindExtensionA");
173                 GPA(COMDLG32_PathAddExtensionA, SHLWAPI_hInstance,"PathAddExtensionA");
174                 break;
175
176         case DLL_PROCESS_DETACH:
177                 if(!--COMDLG32_Attach)
178                 {
179                         if (COMDLG32_TlsIndex != 0xffffffff)
180                           TlsFree(COMDLG32_TlsIndex);
181                         COMDLG32_TlsIndex = 0xffffffff;
182                         COMDLG32_hInstance = 0;
183                         if(COMDLG32_hInstance16)
184                                 FreeLibrary16(COMDLG32_hInstance16);
185                         if(SHFOLDER_hInstance)
186                                 FreeLibrary(SHFOLDER_hInstance);
187
188                 }
189                 break;
190         }
191         return TRUE;
192 }
193 #undef GPA
194
195 /***********************************************************************
196  *      COMDLG32_AllocMem                       (internal)
197  * Get memory for internal datastructure plus stringspace etc.
198  *      RETURNS
199  *              Pointer to a heap block: Succes
200  *              NULL: Failure
201  */
202 LPVOID COMDLG32_AllocMem(
203         int size        /* [in] Block size to allocate */
204 ) {
205         LPVOID ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
206         if(!ptr)
207         {
208                 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
209                 return NULL;
210         }
211         return ptr;
212 }
213
214
215 /***********************************************************************
216  *      COMDLG32_SetCommDlgExtendedError        (internal)
217  *
218  * Used to set the thread's local error value if a comdlg32 function fails.
219  */
220 void COMDLG32_SetCommDlgExtendedError(DWORD err)
221 {
222         TRACE("(%08lx)\n", err);
223         if (COMDLG32_TlsIndex == 0xffffffff)
224           COMDLG32_TlsIndex = TlsAlloc();
225         if (COMDLG32_TlsIndex != 0xffffffff)
226           TlsSetValue(COMDLG32_TlsIndex, (void *)err);
227         else
228           FIXME("No Tls Space\n");
229 }
230
231
232 /***********************************************************************
233  *      CommDlgExtendedError                    (COMDLG32.5)
234  *
235  * Get the thread's local error value if a comdlg32 function fails.
236  *      RETURNS
237  *              Current error value which might not be valid
238  *              if a previous call succeeded.
239  */
240 DWORD WINAPI CommDlgExtendedError(void)
241 {
242         if (COMDLG32_TlsIndex != 0xffffffff) 
243           return (DWORD)TlsGetValue(COMDLG32_TlsIndex);
244         else
245           {
246             FIXME("No Tls Space\n");
247             return 0;
248           }
249 }