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