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