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