Sync with trunk.
[reactos.git] / dll / win32 / comdlg32 / cdlg32.c
1 /*
2 * Common Dialog Boxes interface (32 bit)
3 * Find/Replace
4 *
5 * Copyright 1999 Bertho A. Stultiens
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #include <stdarg.h>
27
28 #define COBJMACROS
29
30 #include <windef.h>
31 //#include "winbase.h"
32 #include <wingdi.h>
33 #include <winuser.h>
34 //#include "objbase.h"
35 //#include "rpcproxy.h"
36 #include <commdlg.h>
37 #include <cderr.h>
38 #include <wine/debug.h>
39
40 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
41
42 #include "cdlg.h"
43
44
45 DECLSPEC_HIDDEN HINSTANCE COMDLG32_hInstance = 0;
46
47 static DWORD COMDLG32_TlsIndex = TLS_OUT_OF_INDEXES;
48
49 static HINSTANCE SHELL32_hInstance;
50 static HINSTANCE SHFOLDER_hInstance;
51
52 /* ITEMIDLIST */
53 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILClone) (LPCITEMIDLIST) DECLSPEC_HIDDEN;
54 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILCombine)(LPCITEMIDLIST,LPCITEMIDLIST) DECLSPEC_HIDDEN;
55 LPITEMIDLIST (WINAPI *COMDLG32_PIDL_ILGetNext)(LPITEMIDLIST) DECLSPEC_HIDDEN;
56 BOOL (WINAPI *COMDLG32_PIDL_ILRemoveLastID)(LPCITEMIDLIST) DECLSPEC_HIDDEN;
57 BOOL (WINAPI *COMDLG32_PIDL_ILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST) DECLSPEC_HIDDEN;
58 UINT (WINAPI *COMDLG32_PIDL_ILGetSize)(LPCITEMIDLIST) DECLSPEC_HIDDEN;
59
60 /* SHELL */
61 LPVOID (WINAPI *COMDLG32_SHAlloc)(DWORD) DECLSPEC_HIDDEN;
62 DWORD (WINAPI *COMDLG32_SHFree)(LPVOID) DECLSPEC_HIDDEN;
63 BOOL (WINAPI *COMDLG32_SHGetFolderPathW)(HWND,int,HANDLE,DWORD,LPWSTR) DECLSPEC_HIDDEN;
64 LPITEMIDLIST (WINAPI *COMDLG32_SHSimpleIDListFromPathAW)(LPCVOID) DECLSPEC_HIDDEN;
65
66 /***********************************************************************
67 * DllMain (COMDLG32.init)
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 const char GPA_string[] = "Failed to get entry point %s for hinst = %p\n";
76 #define GPA(dest, hinst, name) \
77 if(!(dest = (void*)GetProcAddress(hinst,name)))\
78 { \
79 ERR(GPA_string, debugstr_a(name), hinst); \
80 return FALSE; \
81 }
82
83 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
84 {
85 TRACE("(%p, %d, %p)\n", hInstance, Reason, Reserved);
86
87 switch(Reason)
88 {
89 case DLL_PROCESS_ATTACH:
90 COMDLG32_hInstance = hInstance;
91 DisableThreadLibraryCalls(hInstance);
92
93 SHELL32_hInstance = GetModuleHandleA("SHELL32.DLL");
94
95 /* ITEMIDLIST */
96 GPA(COMDLG32_PIDL_ILIsEqual, SHELL32_hInstance, (LPCSTR)21L);
97 GPA(COMDLG32_PIDL_ILCombine, SHELL32_hInstance, (LPCSTR)25L);
98 GPA(COMDLG32_PIDL_ILGetNext, SHELL32_hInstance, (LPCSTR)153L);
99 GPA(COMDLG32_PIDL_ILClone, SHELL32_hInstance, (LPCSTR)18L);
100 GPA(COMDLG32_PIDL_ILRemoveLastID, SHELL32_hInstance, (LPCSTR)17L);
101 GPA(COMDLG32_PIDL_ILGetSize, SHELL32_hInstance, (LPCSTR)152L);
102
103 /* SHELL */
104 GPA(COMDLG32_SHSimpleIDListFromPathAW, SHELL32_hInstance, (LPCSTR)162);
105 GPA(COMDLG32_SHAlloc, SHELL32_hInstance, (LPCSTR)196L);
106 GPA(COMDLG32_SHFree, SHELL32_hInstance, (LPCSTR)195L);
107
108 /* for the first versions of shell32 SHGetFolderPathW is in SHFOLDER.DLL */
109 COMDLG32_SHGetFolderPathW = (void*)GetProcAddress(SHELL32_hInstance,"SHGetFolderPathW");
110 if (!COMDLG32_SHGetFolderPathW)
111 {
112 SHFOLDER_hInstance = LoadLibraryA("SHFOLDER.DLL");
113 GPA(COMDLG32_SHGetFolderPathW, SHFOLDER_hInstance,"SHGetFolderPathW");
114 }
115
116 break;
117
118 case DLL_PROCESS_DETACH:
119 if (COMDLG32_TlsIndex != TLS_OUT_OF_INDEXES) TlsFree(COMDLG32_TlsIndex);
120 if(SHFOLDER_hInstance) FreeLibrary(SHFOLDER_hInstance);
121 break;
122 }
123 return TRUE;
124 }
125 #undef GPA
126
127 /***********************************************************************
128 * COMDLG32_AllocMem (internal)
129 * Get memory for internal datastructure plus stringspace etc.
130 * RETURNS
131 * Success: Pointer to a heap block
132 * Failure: null
133 */
134 LPVOID COMDLG32_AllocMem(
135 int size /* [in] Block size to allocate */
136 ) {
137 LPVOID ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
138 if(!ptr)
139 {
140 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
141 return NULL;
142 }
143 return ptr;
144 }
145
146
147 /***********************************************************************
148 * COMDLG32_SetCommDlgExtendedError (internal)
149 *
150 * Used to set the thread's local error value if a comdlg32 function fails.
151 */
152 void COMDLG32_SetCommDlgExtendedError(DWORD err)
153 {
154 TRACE("(%08x)\n", err);
155 if (COMDLG32_TlsIndex == TLS_OUT_OF_INDEXES)
156 COMDLG32_TlsIndex = TlsAlloc();
157 if (COMDLG32_TlsIndex != TLS_OUT_OF_INDEXES)
158 TlsSetValue(COMDLG32_TlsIndex, (LPVOID)(DWORD_PTR)err);
159 else
160 FIXME("No Tls Space\n");
161 }
162
163
164 /***********************************************************************
165 * CommDlgExtendedError (COMDLG32.@)
166 *
167 * Get the thread's local error value if a comdlg32 function fails.
168 * RETURNS
169 * Current error value which might not be valid
170 * if a previous call succeeded.
171 */
172 DWORD WINAPI CommDlgExtendedError(void)
173 {
174 if (COMDLG32_TlsIndex != TLS_OUT_OF_INDEXES)
175 return (DWORD_PTR)TlsGetValue(COMDLG32_TlsIndex);
176 else
177 return 0; /* we never set an error, so there isn't one */
178 }
179
180 #if 0 // Win 7
181
182 /*************************************************************************
183 * Implement the CommDlg32 class factory
184 *
185 * (Taken from shdocvw/factory.c; based on implementation in
186 * ddraw/main.c)
187 */
188 typedef struct
189 {
190 IClassFactory IClassFactory_iface;
191 HRESULT (*cf)(IUnknown*, REFIID, void**);
192 } IClassFactoryImpl;
193
194 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
195 {
196 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
197 }
198
199 /*************************************************************************
200 * CDLGCF_QueryInterface (IUnknown)
201 */
202 static HRESULT WINAPI CDLGCF_QueryInterface(IClassFactory* iface,
203 REFIID riid, void **ppobj)
204 {
205 TRACE("%p (%s %p)\n", iface, debugstr_guid(riid), ppobj);
206
207 if(!ppobj)
208 return E_POINTER;
209
210 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid))
211 {
212 *ppobj = iface;
213 IClassFactory_AddRef(iface);
214 return S_OK;
215 }
216
217 WARN("Interface not supported.\n");
218
219 *ppobj = NULL;
220 return E_NOINTERFACE;
221 }
222
223 /*************************************************************************
224 * CDLGCF_AddRef (IUnknown)
225 */
226 static ULONG WINAPI CDLGCF_AddRef(IClassFactory *iface)
227 {
228 return 2; /* non-heap based object */
229 }
230
231 /*************************************************************************
232 * CDLGCF_Release (IUnknown)
233 */
234 static ULONG WINAPI CDLGCF_Release(IClassFactory *iface)
235 {
236 return 1; /* non-heap based object */
237 }
238
239 /*************************************************************************
240 * CDLGCF_CreateInstance (IClassFactory)
241 */
242 static HRESULT WINAPI CDLGCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
243 REFIID riid, void **ppobj)
244 {
245 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
246 return This->cf(pOuter, riid, ppobj);
247 }
248
249 /*************************************************************************
250 * CDLGCF_LockServer (IClassFactory)
251 */
252 static HRESULT WINAPI CDLGCF_LockServer(IClassFactory *iface, BOOL dolock)
253 {
254 TRACE("%p (%d)\n", iface, dolock);
255 return S_OK;
256 }
257
258 static const IClassFactoryVtbl CDLGCF_Vtbl =
259 {
260 CDLGCF_QueryInterface,
261 CDLGCF_AddRef,
262 CDLGCF_Release,
263 CDLGCF_CreateInstance,
264 CDLGCF_LockServer
265 };
266
267 /*************************************************************************
268 * DllGetClassObject (COMMDLG32.@)
269 */
270 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
271 {
272 static IClassFactoryImpl FileOpenDlgClassFactory = {{&CDLGCF_Vtbl}, FileOpenDialog_Constructor};
273 static IClassFactoryImpl FileSaveDlgClassFactory = {{&CDLGCF_Vtbl}, FileSaveDialog_Constructor};
274
275 TRACE("%s, %s, %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
276
277 if(IsEqualGUID(&CLSID_FileOpenDialog, rclsid))
278 return IClassFactory_QueryInterface(&FileOpenDlgClassFactory.IClassFactory_iface, riid, ppv);
279
280 if(IsEqualGUID(&CLSID_FileSaveDialog, rclsid))
281 return IClassFactory_QueryInterface(&FileSaveDlgClassFactory.IClassFactory_iface, riid, ppv);
282
283 return CLASS_E_CLASSNOTAVAILABLE;
284 }
285
286 /***********************************************************************
287 * DllRegisterServer (COMMDLG32.@)
288 */
289 HRESULT WINAPI DllRegisterServer(void)
290 {
291 return E_FAIL; // FIXME: __wine_register_resources(COMDLG32_hInstance);
292 }
293
294 /***********************************************************************
295 * DllUnregisterServer (COMMDLG32.@)
296 */
297 HRESULT WINAPI DllUnregisterServer(void)
298 {
299 return E_FAIL; // FIXME: __wine_unregister_resources(COMDLG32_hInstance);
300 }
301
302 #endif // Win 7