Implemented SHGetFileInfo better.
[wine] / dlls / shell32 / folders.c
1 /*
2  *      Copyright 1997  Marcus Meissner
3  *      Copyright 1998  Juergen Schmied
4  *
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "wine/obj_base.h"
11 #include "wine/obj_extracticon.h"
12 #include "wine/undocshell.h"
13
14 #include "debugtools.h"
15 #include "winerror.h"
16
17 #include "pidl.h"
18 #include "shell32_main.h"
19
20 DEFAULT_DEBUG_CHANNEL(shell)
21
22
23 /***********************************************************************
24 *   IExtractIconA implementation
25 */
26
27 typedef struct 
28 {       ICOM_VTABLE(IExtractIconA)*     lpvtbl;
29         DWORD   ref;
30         ICOM_VTABLE(IPersistFile)*      lpvtblPersistFile;
31         LPITEMIDLIST    pidl;
32 } IExtractIconAImpl;
33
34 static struct ICOM_VTABLE(IExtractIconA) eivt;
35 static struct ICOM_VTABLE(IPersistFile) pfvt;
36
37 #define _IPersistFile_Offset ((int)(&(((IExtractIconAImpl*)0)->lpvtblPersistFile)))
38 #define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
39
40 /**************************************************************************
41 *  IExtractIconA_Constructor
42 */
43 IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl)
44 {
45         IExtractIconAImpl* ei;
46
47         ei=(IExtractIconAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IExtractIconAImpl));
48         ei->ref=1;
49         ei->lpvtbl = &eivt;
50         ei->lpvtblPersistFile = &pfvt;
51         ei->pidl=ILClone(pidl);
52
53         pdump(pidl);
54
55         TRACE("(%p)\n",ei);
56         shell32_ObjCount++;
57         return (IExtractIconA *)ei;
58 }
59 /**************************************************************************
60  *  IExtractIconA_QueryInterface
61  */
62 static HRESULT WINAPI IExtractIconA_fnQueryInterface( IExtractIconA * iface, REFIID riid, LPVOID *ppvObj)
63 {
64         ICOM_THIS(IExtractIconAImpl,iface);
65
66         char    xriid[50];
67          WINE_StringFromCLSID((LPCLSID)riid,xriid);
68          TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
69
70         *ppvObj = NULL;
71
72         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
73         { *ppvObj = This; 
74         }
75         else if(IsEqualIID(riid, &IID_IPersistFile))    /*IExtractIcon*/
76         {    *ppvObj = (IPersistFile*)&(This->lpvtblPersistFile);
77         }
78         else if(IsEqualIID(riid, &IID_IExtractIconA))   /*IExtractIcon*/
79         {    *ppvObj = (IExtractIconA*)This;
80         }
81
82         if(*ppvObj)
83         { IExtractIconA_AddRef((IExtractIconA*) *ppvObj);       
84           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
85           return S_OK;
86         }
87         TRACE("-- Interface: E_NOINTERFACE\n");
88         return E_NOINTERFACE;
89 }
90
91 /**************************************************************************
92 *  IExtractIconA_AddRef
93 */
94 static ULONG WINAPI IExtractIconA_fnAddRef(IExtractIconA * iface)
95 {
96         ICOM_THIS(IExtractIconAImpl,iface);
97
98         TRACE("(%p)->(count=%lu)\n",This, This->ref );
99
100         shell32_ObjCount++;
101
102         return ++(This->ref);
103 }
104 /**************************************************************************
105 *  IExtractIconA_Release
106 */
107 static ULONG WINAPI IExtractIconA_fnRelease(IExtractIconA * iface)
108 {
109         ICOM_THIS(IExtractIconAImpl,iface);
110
111         TRACE("(%p)->()\n",This);
112
113         shell32_ObjCount--;
114
115         if (!--(This->ref)) 
116         { TRACE(" destroying IExtractIcon(%p)\n",This);
117           SHFree(This->pidl);
118           HeapFree(GetProcessHeap(),0,This);
119           return 0;
120         }
121         return This->ref;
122 }
123 /**************************************************************************
124 *  IExtractIconA_GetIconLocation
125 *
126 * mapping filetype to icon
127 */
128 static HRESULT WINAPI IExtractIconA_fnGetIconLocation(
129         IExtractIconA * iface,
130         UINT uFlags,
131         LPSTR szIconFile,
132         UINT cchMax,
133         int * piIndex,
134         UINT * pwFlags)
135 {
136         ICOM_THIS(IExtractIconAImpl,iface);
137
138         char    sTemp[MAX_PATH];
139         DWORD   dwNr;
140         GUID const * riid;
141         LPITEMIDLIST    pSimplePidl = ILFindLastID(This->pidl);
142                         
143         TRACE("(%p) (flags=%u %p %u %p %p)\n", This, uFlags, szIconFile, cchMax, piIndex, pwFlags);
144
145         if (pwFlags)
146           *pwFlags = 0;
147
148         if (_ILIsDesktop(pSimplePidl))
149         {
150           lstrcpynA(szIconFile, "shell32.dll", cchMax);
151           *piIndex = 34;
152         }
153
154         /* my computer and other shell extensions */
155         else if ( (riid = _ILGetGUIDPointer(pSimplePidl)) )
156         { 
157           char xriid[50];
158           strcpy(xriid,"CLSID\\");
159           WINE_StringFromCLSID((LPCLSID)riid,&xriid[strlen(xriid)]);
160
161           if (HCR_GetDefaultIcon(xriid, sTemp, MAX_PATH, &dwNr))
162           {
163             lstrcpynA(szIconFile, sTemp, cchMax);
164             *piIndex = dwNr;
165           }
166           else
167           {
168             lstrcpynA(szIconFile, "shell32.dll", cchMax);
169             *piIndex = 15;
170           }
171         }
172
173         else if (_ILIsDrive (pSimplePidl))
174         {
175           if (HCR_GetDefaultIcon("Drive", sTemp, MAX_PATH, &dwNr))
176           {
177             lstrcpynA(szIconFile, sTemp, cchMax);
178             *piIndex = dwNr;
179           }
180           else
181           {
182             lstrcpynA(szIconFile, "shell32.dll", cchMax);
183             *piIndex = 8;
184           }
185         }
186         else if (_ILIsFolder (pSimplePidl))
187         {
188           if (HCR_GetDefaultIcon("Folder", sTemp, MAX_PATH, &dwNr))
189           {
190             lstrcpynA(szIconFile, sTemp, cchMax);
191             *piIndex = dwNr;
192           }
193           else
194           {
195             lstrcpynA(szIconFile, "shell32.dll", cchMax);
196             *piIndex = 3;
197           }
198         }
199         else    /* object is file */
200         {
201           if (_ILGetExtension (pSimplePidl, sTemp, MAX_PATH)
202               && HCR_MapTypeToValue(sTemp, sTemp, MAX_PATH)
203               && HCR_GetDefaultIcon(sTemp, sTemp, MAX_PATH, &dwNr))
204           {
205             if (!strcmp("%1",sTemp))            /* icon is in the file */
206             {
207               SHGetPathFromIDListA(This->pidl, sTemp);
208               dwNr = 0;
209             }
210             lstrcpynA(szIconFile, sTemp, cchMax);
211             *piIndex = dwNr;
212           }
213           else                                  /* default icon */
214           {
215             lstrcpynA(szIconFile, "shell32.dll", cchMax);
216             *piIndex = 0;
217           }
218         }
219
220         TRACE("-- %s %x\n", szIconFile, *piIndex);
221         return NOERROR;
222 }
223 /**************************************************************************
224 *  IExtractIconA_Extract
225 */
226 static HRESULT WINAPI IExtractIconA_fnExtract(IExtractIconA * iface, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
227 {
228         ICOM_THIS(IExtractIconAImpl,iface);
229
230         FIXME("(%p) (file=%p index=%u %p %p size=%u) semi-stub\n", This, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
231
232         if (phiconLarge)
233           *phiconLarge = pImageList_GetIcon(ShellBigIconList, nIconIndex, ILD_TRANSPARENT);
234
235         if (phiconSmall)
236           *phiconSmall = pImageList_GetIcon(ShellSmallIconList, nIconIndex, ILD_TRANSPARENT);
237
238         return S_OK;
239 }
240
241 static struct ICOM_VTABLE(IExtractIconA) eivt = 
242 {       
243         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
244         IExtractIconA_fnQueryInterface,
245         IExtractIconA_fnAddRef,
246         IExtractIconA_fnRelease,
247         IExtractIconA_fnGetIconLocation,
248         IExtractIconA_fnExtract
249 };
250
251 /************************************************************************
252  * IEIPersistFile_QueryInterface (IUnknown)
253  */
254 static HRESULT WINAPI IEIPersistFile_fnQueryInterface(
255         IPersistFile    *iface,
256         REFIID          iid,
257         LPVOID          *ppvObj)
258 {
259         _ICOM_THIS_From_IPersistFile(IExtractIconA, iface);
260
261         return IShellFolder_QueryInterface((IExtractIconA*)This, iid, ppvObj);
262 }
263
264 /************************************************************************
265  * IEIPersistFile_AddRef (IUnknown)
266  */
267 static ULONG WINAPI IEIPersistFile_fnAddRef(
268         IPersistFile    *iface)
269 {
270         _ICOM_THIS_From_IPersistFile(IExtractIconA, iface);
271
272         return IExtractIconA_AddRef((IExtractIconA*)This);
273 }
274
275 /************************************************************************
276  * IEIPersistFile_Release (IUnknown)
277  */
278 static ULONG WINAPI IEIPersistFile_fnRelease(
279         IPersistFile    *iface)
280 {
281         _ICOM_THIS_From_IPersistFile(IExtractIconA, iface);
282
283         return IExtractIconA_Release((IExtractIconA*)This);
284 }
285
286 /************************************************************************
287  * IEIPersistFile_GetClassID (IPersist)
288  */
289 static HRESULT WINAPI IEIPersistFile_fnGetClassID(
290         IPersistFile    *iface,
291         LPCLSID         lpClassId)
292 {
293         CLSID StdFolderID = { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
294
295         if (lpClassId==NULL)
296           return E_POINTER;
297
298         memcpy(lpClassId, &StdFolderID, sizeof(StdFolderID));
299
300         return S_OK;
301 }
302
303 /************************************************************************
304  * IEIPersistFile_Load (IPersistFile)
305  */
306 static HRESULT WINAPI IEIPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
307 {
308         _ICOM_THIS_From_IPersistFile(IExtractIconA, iface);
309         FIXME("%p\n", This);
310         return E_NOTIMPL;
311
312 }
313
314 static struct ICOM_VTABLE(IPersistFile) pfvt =
315 {
316         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
317         IEIPersistFile_fnQueryInterface,
318         IEIPersistFile_fnAddRef,
319         IEIPersistFile_fnRelease,
320         IEIPersistFile_fnGetClassID,
321         (void *) 0xdeadbeef /* IEIPersistFile_fnIsDirty */,
322         IEIPersistFile_fnLoad,
323         (void *) 0xdeadbeef /* IEIPersistFile_fnSave */,
324         (void *) 0xdeadbeef /* IEIPersistFile_fnSaveCompleted */,
325         (void *) 0xdeadbeef /* IEIPersistFile_fnGetCurFile */
326 };
327