Better color-keying support.
[wine] / dlls / shell32 / shfldr_mycomp.c
1
2 /*
3  *      Virtual Workplace folder
4  *
5  *      Copyright 1997                  Marcus Meissner
6  *      Copyright 1998, 1999, 2002      Juergen Schmied
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "winerror.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
37
38 #include "wingdi.h"
39 #include "pidl.h"
40 #include "shlguid.h"
41
42 #include "undocshell.h"
43 #include "shell32_main.h"
44 #include "shresdef.h"
45 #include "shlwapi.h"
46 #include "shellfolder.h"
47 #include "wine/debug.h"
48 #include "debughlp.h"
49 #include "shfldr.h"
50
51 WINE_DEFAULT_DEBUG_CHANNEL (shell);
52
53 /***********************************************************************
54 *   IShellFolder implementation
55 */
56
57 typedef struct {
58     ICOM_VFIELD (IShellFolder2);
59     DWORD ref;
60       ICOM_VTABLE (IPersistFolder2) * lpVtblPersistFolder2;
61
62     /* both paths are parsible from the desktop */
63     LPITEMIDLIST pidlRoot;      /* absolute pidl */
64     int dwAttributes;           /* attributes returned by GetAttributesOf FIXME: use it */
65 } IGenericSFImpl;
66
67 static struct ICOM_VTABLE (IShellFolder2) vt_ShellFolder2;
68 static struct ICOM_VTABLE (IPersistFolder2) vt_PersistFolder2;
69
70 HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
71
72 #define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
73 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
74
75 /*
76   converts This to a interface pointer
77 */
78 #define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
79 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpVtbl)
80 #define _IShellFolder2_(This)   (IShellFolder2*)&(This->lpVtbl)
81
82 #define _IPersist_(This)        (IPersist*)&(This->lpVtblPersistFolder2)
83 #define _IPersistFolder_(This)  (IPersistFolder*)&(This->lpVtblPersistFolder2)
84 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2)
85
86 /***********************************************************************
87 *   IShellFolder [MyComputer] implementation
88 */
89
90 static shvheader MyComputerSFHeader[] = {
91     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
92     {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
93     {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
94     {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
95 };
96
97 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
98
99 /**************************************************************************
100 *       ISF_MyComputer_Constructor
101 */
102 HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
103 {
104     IGenericSFImpl *sf;
105
106     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
107
108     if (!ppv)
109         return E_POINTER;
110     if (pUnkOuter)
111         return CLASS_E_NOAGGREGATION;
112
113     sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
114     if (!sf)
115         return E_OUTOFMEMORY;
116
117     sf->ref = 0;
118     sf->lpVtbl = &vt_ShellFolder2;
119     sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
120     sf->pidlRoot = _ILCreateMyComputer ();      /* my qualified pidl */
121
122     if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
123         IUnknown_Release (_IUnknown_ (sf));
124         return E_NOINTERFACE;
125     }
126
127     TRACE ("--(%p)\n", sf);
128     return S_OK;
129 }
130
131 /**************************************************************************
132  *      ISF_MyComputer_fnQueryInterface
133  *
134  * NOTES supports not IPersist/IPersistFolder
135  */
136 static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
137 {
138     ICOM_THIS (IGenericSFImpl, iface);
139
140     TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
141
142     *ppvObj = NULL;
143
144     if (IsEqualIID (riid, &IID_IUnknown) ||
145         IsEqualIID (riid, &IID_IShellFolder) || IsEqualIID (riid, &IID_IShellFolder2)) {
146         *ppvObj = This;
147     } else if (IsEqualIID (riid, &IID_IPersist) ||
148                IsEqualIID (riid, &IID_IPersistFolder) || IsEqualIID (riid, &IID_IPersistFolder2)) {
149         *ppvObj = _IPersistFolder2_ (This);
150     }
151
152     if (*ppvObj) {
153         IUnknown_AddRef ((IUnknown *) (*ppvObj));
154         TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
155         return S_OK;
156     }
157     TRACE ("-- Interface: E_NOINTERFACE\n");
158     return E_NOINTERFACE;
159 }
160
161 static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface)
162 {
163     ICOM_THIS (IGenericSFImpl, iface);
164
165     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
166
167     return ++(This->ref);
168 }
169
170 static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface)
171 {
172     ICOM_THIS (IGenericSFImpl, iface);
173
174     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
175
176     if (!--(This->ref)) {
177         TRACE ("-- destroying IShellFolder(%p)\n", This);
178         if (This->pidlRoot)
179             SHFree (This->pidlRoot);
180         LocalFree ((HLOCAL) This);
181         return 0;
182     }
183     return This->ref;
184 }
185
186 /**************************************************************************
187 *       ISF_MyComputer_fnParseDisplayName
188 */
189 static HRESULT WINAPI
190 ISF_MyComputer_fnParseDisplayName (IShellFolder2 * iface,
191                                    HWND hwndOwner,
192                                    LPBC pbc,
193                                    LPOLESTR lpszDisplayName,
194                                    DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
195 {
196     ICOM_THIS (IGenericSFImpl, iface);
197
198     HRESULT hr = E_OUTOFMEMORY;
199     LPCWSTR szNext = NULL;
200     WCHAR szElement[MAX_PATH];
201     CHAR szTempA[MAX_PATH];
202     LPITEMIDLIST pidlTemp;
203
204     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
205            This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
206
207     *ppidl = 0;
208     if (pchEaten)
209         *pchEaten = 0;          /* strange but like the original */
210
211     /* do we have an absolute path name ? */
212     if (PathGetDriveNumberW (lpszDisplayName) >= 0 && lpszDisplayName[2] == (WCHAR) '\\') {
213         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
214         WideCharToMultiByte (CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL);
215         pidlTemp = _ILCreateDrive (szTempA);
216
217         if (szNext && *szNext) {
218             hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
219         } else {
220             if (pdwAttributes && *pdwAttributes) {
221                 SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
222             }
223             hr = S_OK;
224         }
225         *ppidl = pidlTemp;
226     }
227
228     TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
229
230     return hr;
231 }
232
233 /**************************************************************************
234 *               ISF_MyComputer_fnEnumObjects
235 */
236 static HRESULT WINAPI
237 ISF_MyComputer_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
238 {
239     ICOM_THIS (IGenericSFImpl, iface);
240
241     TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
242
243     *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
244
245     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
246
247     return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
248 }
249
250 /**************************************************************************
251 *               ISF_MyComputer_fnBindToObject
252 */
253 static HRESULT WINAPI
254 ISF_MyComputer_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl,
255                                LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
256 {
257     ICOM_THIS (IGenericSFImpl, iface);
258
259     TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
260
261     return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
262 }
263
264 /**************************************************************************
265 *       ISF_MyComputer_fnBindToStorage
266 */
267 static HRESULT WINAPI
268 ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface,
269                                 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
270 {
271     ICOM_THIS (IGenericSFImpl, iface);
272
273     FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
274
275     *ppvOut = NULL;
276     return E_NOTIMPL;
277 }
278
279 /**************************************************************************
280 *       ISF_MyComputer_fnCompareIDs
281 */
282
283 static HRESULT WINAPI
284 ISF_MyComputer_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
285 {
286     ICOM_THIS (IGenericSFImpl, iface);
287
288     int nReturn;
289
290     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
291     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
292     TRACE ("-- %i\n", nReturn);
293     return nReturn;
294 }
295
296 /**************************************************************************
297 *       ISF_MyComputer_fnCreateViewObject
298 */
299 static HRESULT WINAPI
300 ISF_MyComputer_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
301 {
302     ICOM_THIS (IGenericSFImpl, iface);
303
304     LPSHELLVIEW pShellView;
305     HRESULT hr = E_INVALIDARG;
306
307     TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
308
309     if (ppvOut) {
310         *ppvOut = NULL;
311
312         if (IsEqualIID (riid, &IID_IDropTarget)) {
313             WARN ("IDropTarget not implemented\n");
314             hr = E_NOTIMPL;
315         } else if (IsEqualIID (riid, &IID_IContextMenu)) {
316             WARN ("IContextMenu not implemented\n");
317             hr = E_NOTIMPL;
318         } else if (IsEqualIID (riid, &IID_IShellView)) {
319             pShellView = IShellView_Constructor ((IShellFolder *) iface);
320             if (pShellView) {
321                 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
322                 IShellView_Release (pShellView);
323             }
324         }
325     }
326     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
327     return hr;
328 }
329
330 /**************************************************************************
331 *  ISF_MyComputer_fnGetAttributesOf
332 */
333 static HRESULT WINAPI
334 ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
335 {
336     ICOM_THIS (IGenericSFImpl, iface);
337
338     HRESULT hr = S_OK;
339
340     TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
341
342     if ((!cidl) || (!apidl) || (!rgfInOut))
343         return E_INVALIDARG;
344
345     while (cidl > 0 && *apidl) {
346         pdump (*apidl);
347         SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
348         apidl++;
349         cidl--;
350     }
351
352     TRACE ("-- result=0x%08lx\n", *rgfInOut);
353     return hr;
354 }
355
356 /**************************************************************************
357 *       ISF_MyComputer_fnGetUIObjectOf
358 *
359 * PARAMETERS
360 *  HWND           hwndOwner, //[in ] Parent window for any output
361 *  UINT           cidl,      //[in ] array size
362 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
363 *  REFIID         riid,      //[in ] Requested Interface
364 *  UINT*          prgfInOut, //[   ] reserved
365 *  LPVOID*        ppvObject) //[out] Resulting Interface
366 *
367 */
368 static HRESULT WINAPI
369 ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
370                                 HWND hwndOwner,
371                                 UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
372 {
373     ICOM_THIS (IGenericSFImpl, iface);
374
375     LPITEMIDLIST pidl;
376     IUnknown *pObj = NULL;
377     HRESULT hr = E_INVALIDARG;
378
379     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
380            This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
381
382     if (ppvOut) {
383         *ppvOut = NULL;
384
385         if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
386             pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
387             hr = S_OK;
388         } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
389             pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
390             hr = S_OK;
391         } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
392             pidl = ILCombine (This->pidlRoot, apidl[0]);
393             pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
394             SHFree (pidl);
395             hr = S_OK;
396         } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) {
397             pidl = ILCombine (This->pidlRoot, apidl[0]);
398             pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
399             SHFree (pidl);
400             hr = S_OK;
401         } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
402             hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
403         } else {
404             hr = E_NOINTERFACE;
405         }
406
407         if (!pObj)
408             hr = E_OUTOFMEMORY;
409
410         *ppvOut = pObj;
411     }
412     TRACE ("(%p)->hr=0x%08lx\n", This, hr);
413     return hr;
414 }
415
416 /**************************************************************************
417 *       ISF_MyComputer_fnGetDisplayNameOf
418 *
419 * NOTES
420 *       The desktopfolder creates only complete paths (SHGDN_FORPARSING).
421 *       SHGDN_INFOLDER makes no sense.
422 */
423 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
424 {
425     ICOM_THIS (IGenericSFImpl, iface);
426
427     char szPath[MAX_PATH],
428       szDrive[18];
429     int len = 0;
430     BOOL bSimplePidl;
431
432     TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
433     pdump (pidl);
434
435     if (!strRet)
436         return E_INVALIDARG;
437
438     szPath[0] = 0x00;
439     szDrive[0] = 0x00;
440
441     bSimplePidl = _ILIsPidlSimple (pidl);
442
443     if (_ILIsSpecialFolder (pidl)) {
444         /* take names of special folders only if its only this folder */
445         if (bSimplePidl) {
446             _ILSimpleGetText (pidl, szPath, MAX_PATH);  /* append my own path */
447         } else {
448             FIXME ("special folder\n");
449         }
450     } else {
451         if (!_ILIsDrive (pidl)) {
452             ERR ("Wrong pidl type\n");
453             return E_INVALIDARG;
454         }
455
456         _ILSimpleGetText (pidl, szPath, MAX_PATH);      /* append my own path */
457
458         /* long view "lw_name (C:)" */
459         if (bSimplePidl && !(dwFlags & SHGDN_FORPARSING)) {
460             DWORD dwVolumeSerialNumber,
461               dwMaximumComponetLength,
462               dwFileSystemFlags;
463
464             GetVolumeInformationA (szPath, szDrive, sizeof (szDrive) - 6, &dwVolumeSerialNumber,
465                                    &dwMaximumComponetLength, &dwFileSystemFlags, NULL, 0);
466             strcat (szDrive, " (");
467             strncat (szDrive, szPath, 2);
468             strcat (szDrive, ")");
469             strcpy (szPath, szDrive);
470         }
471     }
472
473     if (!bSimplePidl) {         /* go deeper if needed */
474         PathAddBackslashA (szPath);
475         len = strlen (szPath);
476
477         if (!SUCCEEDED
478             (SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len)))
479             return E_OUTOFMEMORY;
480     }
481     strRet->uType = STRRET_CSTR;
482     lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
483
484     TRACE ("-- (%p)->(%s)\n", This, szPath);
485     return S_OK;
486 }
487
488 /**************************************************************************
489 *  ISF_MyComputer_fnSetNameOf
490 *  Changes the name of a file object or subfolder, possibly changing its item
491 *  identifier in the process.
492 *
493 * PARAMETERS
494 *  HWND          hwndOwner,  //[in ] Owner window for output
495 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
496 *  LPCOLESTR     lpszName,   //[in ] the items new display name
497 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
498 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
499 */
500 static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,    /*simple pidl */
501                                                   LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
502 {
503     ICOM_THIS (IGenericSFImpl, iface);
504     FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
505     return E_FAIL;
506 }
507
508 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
509 {
510     ICOM_THIS (IGenericSFImpl, iface);
511     FIXME ("(%p)\n", This);
512     return E_NOTIMPL;
513 }
514 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
515 {
516     ICOM_THIS (IGenericSFImpl, iface);
517     FIXME ("(%p)\n", This);
518     return E_NOTIMPL;
519 }
520 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
521 {
522     ICOM_THIS (IGenericSFImpl, iface);
523
524     TRACE ("(%p)\n", This);
525
526     if (pSort) *pSort = 0;
527     if (pDisplay) *pDisplay = 0;
528     return S_OK;
529 }
530 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
531 {
532     ICOM_THIS (IGenericSFImpl, iface);
533
534     TRACE ("(%p)\n", This);
535
536     if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS) return E_INVALIDARG;
537     *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
538     return S_OK;
539 }
540 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
541 {
542     ICOM_THIS (IGenericSFImpl, iface);
543     FIXME ("(%p)\n", This);
544     return E_NOTIMPL;
545 }
546
547 /* FIXME: drive size >4GB is rolling over */
548 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
549 {
550     ICOM_THIS (IGenericSFImpl, iface);
551     HRESULT hr;
552
553     TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
554
555     if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
556         return E_INVALIDARG;
557
558     if (!pidl) {
559         psd->fmt = MyComputerSFHeader[iColumn].fmt;
560         psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
561         psd->str.uType = STRRET_CSTR;
562         LoadStringA (shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
563         return S_OK;
564     } else {
565         char szPath[MAX_PATH];
566         ULARGE_INTEGER ulBytes;
567
568         psd->str.u.cStr[0] = 0x00;
569         psd->str.uType = STRRET_CSTR;
570         switch (iColumn) {
571         case 0:         /* name */
572             hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
573             break;
574         case 1:         /* type */
575             _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
576             break;
577         case 2:         /* total size */
578             if (_ILIsDrive (pidl)) {
579                 _ILSimpleGetText (pidl, szPath, MAX_PATH);
580                 GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
581                 StrFormatByteSizeA (ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
582             }
583             break;
584         case 3:         /* free size */
585             if (_ILIsDrive (pidl)) {
586                 _ILSimpleGetText (pidl, szPath, MAX_PATH);
587                 GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
588                 StrFormatByteSizeA (ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
589             }
590             break;
591         }
592         hr = S_OK;
593     }
594
595     return hr;
596 }
597 static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
598 {
599     ICOM_THIS (IGenericSFImpl, iface);
600     FIXME ("(%p)\n", This);
601     return E_NOTIMPL;
602 }
603
604 static ICOM_VTABLE (IShellFolder2) vt_ShellFolder2 =
605 {
606         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
607         ISF_MyComputer_fnQueryInterface,
608         ISF_MyComputer_fnAddRef,
609         ISF_MyComputer_fnRelease,
610         ISF_MyComputer_fnParseDisplayName,
611         ISF_MyComputer_fnEnumObjects,
612         ISF_MyComputer_fnBindToObject,
613         ISF_MyComputer_fnBindToStorage,
614         ISF_MyComputer_fnCompareIDs,
615         ISF_MyComputer_fnCreateViewObject,
616         ISF_MyComputer_fnGetAttributesOf,
617         ISF_MyComputer_fnGetUIObjectOf,
618         ISF_MyComputer_fnGetDisplayNameOf,
619         ISF_MyComputer_fnSetNameOf,
620         /* ShellFolder2 */
621         ISF_MyComputer_fnGetDefaultSearchGUID,
622         ISF_MyComputer_fnEnumSearches,
623         ISF_MyComputer_fnGetDefaultColumn,
624         ISF_MyComputer_fnGetDefaultColumnState,
625         ISF_MyComputer_fnGetDetailsEx,
626         ISF_MyComputer_fnGetDetailsOf,
627         ISF_MyComputer_fnMapColumnToSCID
628 };
629
630 /************************************************************************
631  *      IMCFldr_PersistFolder2_QueryInterface
632  */
633 static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
634 {
635     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
636
637     TRACE ("(%p)\n", This);
638
639     return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
640 }
641
642 /************************************************************************
643  *      IMCFldr_PersistFolder2_AddRef
644  */
645 static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
646 {
647     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
648
649     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
650
651     return IUnknown_AddRef (_IUnknown_ (This));
652 }
653
654 /************************************************************************
655  *      ISFPersistFolder_Release
656  */
657 static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface)
658 {
659     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
660
661     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
662
663     return IUnknown_Release (_IUnknown_ (This));
664 }
665
666 /************************************************************************
667  *      IMCFldr_PersistFolder2_GetClassID
668  */
669 static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (IPersistFolder2 * iface, CLSID * lpClassId)
670 {
671     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
672
673     TRACE ("(%p)\n", This);
674
675     if (!lpClassId)
676         return E_POINTER;
677     *lpClassId = CLSID_MyComputer;
678
679     return S_OK;
680 }
681
682 /************************************************************************
683  *      IMCFldr_PersistFolder2_Initialize
684  *
685  * NOTES: it makes no sense to change the pidl
686  */
687 static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (IPersistFolder2 * iface, LPCITEMIDLIST pidl)
688 {
689     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
690     TRACE ("(%p)->(%p)\n", This, pidl);
691     return E_NOTIMPL;
692 }
693
694 /**************************************************************************
695  *      IPersistFolder2_fnGetCurFolder
696  */
697 static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (IPersistFolder2 * iface, LPITEMIDLIST * pidl)
698 {
699     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
700
701     TRACE ("(%p)->(%p)\n", This, pidl);
702
703     if (!pidl)
704         return E_POINTER;
705     *pidl = ILClone (This->pidlRoot);
706     return S_OK;
707 }
708
709 static ICOM_VTABLE (IPersistFolder2) vt_PersistFolder2 =
710 {
711 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
712         IMCFldr_PersistFolder2_QueryInterface,
713         IMCFldr_PersistFolder2_AddRef,
714         IMCFldr_PersistFolder2_Release,
715         IMCFldr_PersistFolder2_GetClassID,
716         IMCFldr_PersistFolder2_Initialize,
717         IMCFldr_PersistFolder2_GetCurFolder
718 };