Fix recent Unicode-ification patch.
[wine] / dlls / shell32 / folders.c
1 /*
2  *      Copyright 1997  Marcus Meissner
3  *      Copyright 1998  Juergen Schmied
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "undocshell.h"
32 #include "shlguid.h"
33
34 #include "wine/debug.h"
35 #include "winerror.h"
36
37 #include "pidl.h"
38 #include "shell32_main.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41
42 /***********************************************************************
43 *   IExtractIconW implementation
44 */
45 typedef struct
46 {
47         ICOM_VFIELD(IExtractIconW);
48         DWORD   ref;
49         ICOM_VTABLE(IPersistFile)*      lpvtblPersistFile;
50         ICOM_VTABLE(IExtractIconA)*     lpvtblExtractIconA;
51         LPITEMIDLIST    pidl;
52 } IExtractIconWImpl;
53
54 static struct ICOM_VTABLE(IExtractIconA) eiavt;
55 static struct ICOM_VTABLE(IExtractIconW) eivt;
56 static struct ICOM_VTABLE(IPersistFile) pfvt;
57
58 #define _IPersistFile_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblPersistFile)))
59 #define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
60
61 #define _IExtractIconA_Offset ((int)(&(((IExtractIconWImpl*)0)->lpvtblExtractIconA)))
62 #define _ICOM_THIS_From_IExtractIconA(class, name) class* This = (class*)(((char*)name)-_IExtractIconA_Offset);
63
64 /**************************************************************************
65 *  IExtractIconW_Constructor
66 */
67 IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl)
68 {
69         IExtractIconWImpl* ei;
70         
71         TRACE("%p\n", pidl);
72
73         ei = (IExtractIconWImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IExtractIconWImpl));
74         ei->ref=1;
75         ei->lpVtbl = &eivt;
76         ei->lpvtblPersistFile = &pfvt;
77         ei->lpvtblExtractIconA = &eiavt;
78         ei->pidl=ILClone(pidl);
79
80         pdump(pidl);
81
82         TRACE("(%p)\n", ei);
83         return (IExtractIconW *)ei;
84 }
85 /**************************************************************************
86  *  IExtractIconW_QueryInterface
87  */
88 static HRESULT WINAPI IExtractIconW_fnQueryInterface(IExtractIconW *iface, REFIID riid, LPVOID *ppvObj)
89 {
90         ICOM_THIS(IExtractIconWImpl, iface);
91
92         TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, debugstr_guid(riid), ppvObj);
93
94         *ppvObj = NULL;
95
96         if (IsEqualIID(riid, &IID_IUnknown))                            /*IUnknown*/
97         {
98           *ppvObj = This;
99         }
100         else if (IsEqualIID(riid, &IID_IPersistFile))   /*IExtractIcon*/
101         {
102           *ppvObj = (IPersistFile*)&(This->lpvtblPersistFile);
103         }
104         else if (IsEqualIID(riid, &IID_IExtractIconA))  /*IExtractIcon*/
105         {
106           *ppvObj = (IExtractIconA*)&(This->lpvtblExtractIconA);
107         }
108         else if (IsEqualIID(riid, &IID_IExtractIconW))  /*IExtractIcon*/
109         {
110           *ppvObj = (IExtractIconW*)This;
111         }
112
113         if(*ppvObj)
114         {
115           IExtractIconW_AddRef((IExtractIconW*) *ppvObj);
116           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
117           return S_OK;
118         }
119         TRACE("-- Interface: E_NOINTERFACE\n");
120         return E_NOINTERFACE;
121 }
122
123 /**************************************************************************
124 *  IExtractIconW_AddRef
125 */
126 static ULONG WINAPI IExtractIconW_fnAddRef(IExtractIconW * iface)
127 {
128         ICOM_THIS(IExtractIconWImpl, iface);
129
130         TRACE("(%p)->(count=%lu)\n",This, This->ref );
131
132         return ++(This->ref);
133 }
134 /**************************************************************************
135 *  IExtractIconW_Release
136 */
137 static ULONG WINAPI IExtractIconW_fnRelease(IExtractIconW * iface)
138 {
139         ICOM_THIS(IExtractIconWImpl, iface);
140
141         TRACE("(%p)->()\n",This);
142
143         if (!--(This->ref))
144         {
145           TRACE(" destroying IExtractIcon(%p)\n",This);
146           SHFree(This->pidl);
147           HeapFree(GetProcessHeap(),0,This);
148           return 0;
149         }
150         return This->ref;
151 }
152
153 WCHAR swShell32Name[MAX_PATH];
154
155 /**************************************************************************
156 *  IExtractIconW_GetIconLocation
157 *
158 * mapping filetype to icon
159 */
160 static HRESULT WINAPI IExtractIconW_fnGetIconLocation(
161         IExtractIconW * iface,
162         UINT uFlags,            /* GIL_ flags */
163         LPWSTR szIconFile,
164         UINT cchMax,
165         int * piIndex,
166         UINT * pwFlags)         /* returned GIL_ flags */
167 {
168         ICOM_THIS(IExtractIconWImpl, iface);
169
170         char    sTemp[MAX_PATH];
171         DWORD   dwNr;
172         GUID const * riid;
173         LPITEMIDLIST    pSimplePidl = ILFindLastID(This->pidl);
174
175         TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags);
176
177         if (pwFlags)
178           *pwFlags = 0;
179
180         if (_ILIsDesktop(pSimplePidl))
181         {
182           lstrcpynW(szIconFile, swShell32Name, cchMax);
183           *piIndex = 34;
184         }
185
186         /* my computer and other shell extensions */
187         else if ((riid = _ILGetGUIDPointer(pSimplePidl)))
188         {
189           char xriid[50];
190
191           sprintf(xriid, "CLSID\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
192                   riid->Data1, riid->Data2, riid->Data3,
193                   riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
194                   riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]);
195
196           if (HCR_GetDefaultIconA(xriid, sTemp, MAX_PATH, &dwNr))
197           {
198             MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax);
199             *piIndex = dwNr;
200           }
201           else
202           {
203             lstrcpynW(szIconFile, swShell32Name, cchMax);
204             *piIndex = 15;
205           }
206         }
207
208         else if (_ILIsDrive (pSimplePidl))
209         {
210           if (HCR_GetDefaultIconA("Drive", sTemp, MAX_PATH, &dwNr))
211           {
212             MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax);
213             *piIndex = dwNr;
214           }
215           else
216           {
217             lstrcpynW(szIconFile, swShell32Name, cchMax);
218             *piIndex = 8;
219           }
220         }
221         else if (_ILIsFolder (pSimplePidl))
222         {
223           if (HCR_GetDefaultIconA("Folder", sTemp, MAX_PATH, &dwNr))
224           {
225             MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax);
226           }
227           else
228           {
229             lstrcpynW(szIconFile, swShell32Name, cchMax);
230             dwNr = 3;
231           }
232           *piIndex = (uFlags & GIL_OPENICON) ? dwNr + 1 : dwNr;
233         }
234         else    /* object is file */
235         {
236           if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH)
237               && HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE)
238               && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &dwNr))
239           {
240             if (!lstrcmpA("%1", sTemp))         /* icon is in the file */
241             {
242               SHGetPathFromIDListW(This->pidl, szIconFile);
243               *piIndex = 0;
244             }
245             else
246             {
247               MultiByteToWideChar(CP_ACP, 0, sTemp, -1, szIconFile, cchMax);
248               *piIndex = dwNr;
249             }
250           }
251           else                                  /* default icon */
252           {
253             lstrcpynW(szIconFile, swShell32Name, cchMax);
254             *piIndex = 0;
255           }
256         }
257
258         TRACE("-- %s %x\n", debugstr_w(szIconFile), *piIndex);
259         return NOERROR;
260 }
261 /**************************************************************************
262 *  IExtractIconW_Extract
263 */
264 static HRESULT WINAPI IExtractIconW_fnExtract(IExtractIconW * iface, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
265 {
266         ICOM_THIS(IExtractIconWImpl, iface);
267
268         FIXME("(%p) (file=%p index=%u %p %p size=%u) semi-stub\n", This, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize);
269
270         if (phiconLarge)
271           *phiconLarge = ImageList_GetIcon(ShellBigIconList, nIconIndex, ILD_TRANSPARENT);
272
273         if (phiconSmall)
274           *phiconSmall = ImageList_GetIcon(ShellSmallIconList, nIconIndex, ILD_TRANSPARENT);
275
276         return S_OK;
277 }
278
279 static struct ICOM_VTABLE(IExtractIconW) eivt =
280 {
281         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
282         IExtractIconW_fnQueryInterface,
283         IExtractIconW_fnAddRef,
284         IExtractIconW_fnRelease,
285         IExtractIconW_fnGetIconLocation,
286         IExtractIconW_fnExtract
287 };
288
289 /**************************************************************************
290 *  IExtractIconA_Constructor
291 */
292 IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl)
293 {
294         ICOM_THIS(IExtractIconWImpl, IExtractIconW_Constructor(pidl));
295         IExtractIconA *eia = (IExtractIconA *)&This->lpvtblExtractIconA;
296         
297         TRACE("(%p)->(%p)\n", This, eia);
298         return eia;
299 }
300 /**************************************************************************
301  *  IExtractIconA_QueryInterface
302  */
303 static HRESULT WINAPI IExtractIconA_fnQueryInterface(IExtractIconA * iface, REFIID riid, LPVOID *ppvObj)
304 {
305         _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
306
307         return IExtractIconW_QueryInterface(This, riid, ppvObj);
308 }
309
310 /**************************************************************************
311 *  IExtractIconA_AddRef
312 */
313 static ULONG WINAPI IExtractIconA_fnAddRef(IExtractIconA * iface)
314 {
315         _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
316
317         return IExtractIconW_AddRef(This);
318 }
319 /**************************************************************************
320 *  IExtractIconA_Release
321 */
322 static ULONG WINAPI IExtractIconA_fnRelease(IExtractIconA * iface)
323 {
324         _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
325
326         return IExtractIconW_AddRef(This);
327 }
328 /**************************************************************************
329 *  IExtractIconA_GetIconLocation
330 *
331 * mapping filetype to icon
332 */
333 static HRESULT WINAPI IExtractIconA_fnGetIconLocation(
334         IExtractIconA * iface,
335         UINT uFlags,
336         LPSTR szIconFile,
337         UINT cchMax,
338         int * piIndex,
339         UINT * pwFlags)
340 {
341         HRESULT ret;
342         LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR));
343         _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
344         
345         TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags);
346
347         ret = IExtractIconW_GetIconLocation(This, uFlags, lpwstrFile, cchMax, piIndex, pwFlags);
348         WideCharToMultiByte(CP_ACP, 0, lpwstrFile, -1, szIconFile, cchMax, NULL, NULL);
349         HeapFree(GetProcessHeap(), 0, lpwstrFile);
350
351         TRACE("-- %s %x\n", szIconFile, *piIndex);
352         return ret;
353 }
354 /**************************************************************************
355 *  IExtractIconA_Extract
356 */
357 static HRESULT WINAPI IExtractIconA_fnExtract(IExtractIconA * iface, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
358 {
359         HRESULT ret;
360         INT len = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0);
361         LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
362         _ICOM_THIS_From_IExtractIconA(IExtractIconW, iface);
363
364         TRACE("(%p) (file=%p index=%u %p %p size=%u)\n", This, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
365
366         MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwstrFile, len);
367         ret = IExtractIconW_Extract(This, lpwstrFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
368         HeapFree(GetProcessHeap(), 0, lpwstrFile);
369         return ret;
370 }
371
372 static struct ICOM_VTABLE(IExtractIconA) eiavt =
373 {
374         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
375         IExtractIconA_fnQueryInterface,
376         IExtractIconA_fnAddRef,
377         IExtractIconA_fnRelease,
378         IExtractIconA_fnGetIconLocation,
379         IExtractIconA_fnExtract
380 };
381
382 /************************************************************************
383  * IEIPersistFile_QueryInterface (IUnknown)
384  */
385 static HRESULT WINAPI IEIPersistFile_fnQueryInterface(
386         IPersistFile    *iface,
387         REFIID          iid,
388         LPVOID          *ppvObj)
389 {
390         _ICOM_THIS_From_IPersistFile(IExtractIconW, iface);
391
392         return IExtractIconW_QueryInterface(This, iid, ppvObj);
393 }
394
395 /************************************************************************
396  * IEIPersistFile_AddRef (IUnknown)
397  */
398 static ULONG WINAPI IEIPersistFile_fnAddRef(
399         IPersistFile    *iface)
400 {
401         _ICOM_THIS_From_IPersistFile(IExtractIconW, iface);
402
403         return IExtractIconW_AddRef(This);
404 }
405
406 /************************************************************************
407  * IEIPersistFile_Release (IUnknown)
408  */
409 static ULONG WINAPI IEIPersistFile_fnRelease(
410         IPersistFile    *iface)
411 {
412         _ICOM_THIS_From_IPersistFile(IExtractIconW, iface);
413
414         return IExtractIconW_Release(This);
415 }
416
417 /************************************************************************
418  * IEIPersistFile_GetClassID (IPersist)
419  */
420 static HRESULT WINAPI IEIPersistFile_fnGetClassID(
421         IPersistFile    *iface,
422         LPCLSID         lpClassId)
423 {
424         CLSID StdFolderID = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
425
426         if (lpClassId==NULL)
427           return E_POINTER;
428
429         memcpy(lpClassId, &StdFolderID, sizeof(StdFolderID));
430
431         return S_OK;
432 }
433
434 /************************************************************************
435  * IEIPersistFile_Load (IPersistFile)
436  */
437 static HRESULT WINAPI IEIPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
438 {
439         _ICOM_THIS_From_IPersistFile(IExtractIconW, iface);
440         FIXME("%p\n", This);
441         return E_NOTIMPL;
442
443 }
444
445 static struct ICOM_VTABLE(IPersistFile) pfvt =
446 {
447         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
448         IEIPersistFile_fnQueryInterface,
449         IEIPersistFile_fnAddRef,
450         IEIPersistFile_fnRelease,
451         IEIPersistFile_fnGetClassID,
452         (void *) 0xdeadbeef /* IEIPersistFile_fnIsDirty */,
453         IEIPersistFile_fnLoad,
454         (void *) 0xdeadbeef /* IEIPersistFile_fnSave */,
455         (void *) 0xdeadbeef /* IEIPersistFile_fnSaveCompleted */,
456         (void *) 0xdeadbeef /* IEIPersistFile_fnGetCurFile */
457 };