Handle wParam in WM_PAINT properly: if non-null, it is the hdc we are
[wine] / dlls / shell32 / shfldr_mycomp.c
1 /*
2  *    Virtual Workplace folder
3  *
4  *    Copyright 1997            Marcus Meissner
5  *    Copyright 1998, 1999, 2002    Juergen Schmied
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33
34 #include "winerror.h"
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winreg.h"
38
39 #include "wingdi.h"
40 #include "pidl.h"
41 #include "shlguid.h"
42 #include "enumidlist.h"
43 #include "undocshell.h"
44 #include "shell32_main.h"
45 #include "shresdef.h"
46 #include "shlwapi.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     IShellFolder2Vtbl   *lpVtbl;
59     DWORD                ref;
60     IPersistFolder2Vtbl *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 IShellFolder2Vtbl vt_ShellFolder2;
68 static struct IPersistFolder2Vtbl vt_PersistFolder2;
69
70 #define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
71 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
72
73 /*
74   converts This to an interface pointer
75 */
76 #define _IUnknown_(This)    (IUnknown*)&(This->lpVtbl)
77 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpVtbl)
78 #define _IShellFolder2_(This)    (IShellFolder2*)&(This->lpVtbl)
79
80 #define _IPersist_(This)    (IPersist*)&(This->lpVtblPersistFolder2)
81 #define _IPersistFolder_(This)    (IPersistFolder*)&(This->lpVtblPersistFolder2)
82 #define _IPersistFolder2_(This)    (IPersistFolder2*)&(This->lpVtblPersistFolder2)
83
84 /***********************************************************************
85 *   IShellFolder [MyComputer] implementation
86 */
87
88 static shvheader MyComputerSFHeader[] = {
89     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
90     {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
91     {IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
92     {IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
93 };
94
95 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
96
97 /**************************************************************************
98 *    ISF_MyComputer_Constructor
99 */
100 HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
101 {
102     IGenericSFImpl *sf;
103
104     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
105
106     if (!ppv)
107         return E_POINTER;
108     if (pUnkOuter)
109         return CLASS_E_NOAGGREGATION;
110
111     sf = LocalAlloc (LMEM_ZEROINIT, sizeof (IGenericSFImpl));
112     if (!sf)
113         return E_OUTOFMEMORY;
114
115     sf->ref = 0;
116     sf->lpVtbl = &vt_ShellFolder2;
117     sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
118     sf->pidlRoot = _ILCreateMyComputer ();    /* my qualified pidl */
119
120     if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv)))
121     {
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,
136                REFIID riid, LPVOID *ppvObj)
137 {
138     IGenericSFImpl *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) ||
146         IsEqualIID (riid, &IID_IShellFolder2))
147     {
148         *ppvObj = This;
149     }
150     else if (IsEqualIID (riid, &IID_IPersist) ||
151              IsEqualIID (riid, &IID_IPersistFolder) ||
152              IsEqualIID (riid, &IID_IPersistFolder2))
153     {
154         *ppvObj = _IPersistFolder2_ (This);
155     }
156
157     if (*ppvObj)
158     {
159         IUnknown_AddRef ((IUnknown *) (*ppvObj));
160         TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
161         return S_OK;
162     }
163     TRACE ("-- Interface: E_NOINTERFACE\n");
164     return E_NOINTERFACE;
165 }
166
167 static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface)
168 {
169     IGenericSFImpl *This = (IGenericSFImpl *)iface;
170     ULONG refCount = InterlockedIncrement(&This->ref);
171
172     TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
173
174     return refCount;
175 }
176
177 static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface)
178 {
179     IGenericSFImpl *This = (IGenericSFImpl *)iface;
180     ULONG refCount = InterlockedDecrement(&This->ref);
181
182     TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
183
184     if (!refCount)
185     {
186         TRACE ("-- destroying IShellFolder(%p)\n", This);
187         if (This->pidlRoot)
188             SHFree (This->pidlRoot);
189         LocalFree ((HLOCAL) This);
190     }
191     return refCount;
192 }
193
194 /**************************************************************************
195 *    ISF_MyComputer_fnParseDisplayName
196 */
197 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface,
198                HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
199                DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
200 {
201     IGenericSFImpl *This = (IGenericSFImpl *)iface;
202     HRESULT hr = E_INVALIDARG;
203     LPCWSTR szNext = NULL;
204     WCHAR szElement[MAX_PATH];
205     LPITEMIDLIST pidlTemp = NULL;
206     CLSID clsid;
207
208     TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", This,
209           hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
210           pchEaten, ppidl, pdwAttributes);
211
212     *ppidl = 0;
213     if (pchEaten)
214         *pchEaten = 0;        /* strange but like the original */
215
216     /* handle CLSID paths */
217     if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
218     {
219         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
220         TRACE ("-- element: %s\n", debugstr_w (szElement));
221         SHCLSIDFromStringW (szElement + 2, &clsid);
222         pidlTemp = _ILCreateGuid (PT_GUID, &clsid);
223     }
224     /* do we have an absolute path name ? */
225     else if (PathGetDriveNumberW (lpszDisplayName) >= 0 &&
226               lpszDisplayName[2] == (WCHAR) '\\')
227     {
228         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
229         /* make drive letter uppercase to enable PIDL comparison */
230         szElement[0] = toupper(szElement[0]);
231         pidlTemp = _ILCreateDrive (szElement);
232     }
233
234     if (szNext && *szNext)
235     {
236         hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp,
237                               (LPOLESTR) szNext, pchEaten, pdwAttributes);
238     }
239     else
240     {
241         if (pdwAttributes && *pdwAttributes)
242             SHELL32_GetItemAttributes (_IShellFolder_ (This),
243                                        pidlTemp, pdwAttributes);
244         hr = S_OK;
245     }
246
247     *ppidl = pidlTemp;
248
249     TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
250
251     return hr;
252 }
253
254 /**************************************************************************
255  *  CreateMyCompEnumList()
256  */
257 static const WCHAR MyComputer_NameSpaceW[] = { 'S','O','F','T','W','A','R','E',
258  '\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
259  'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l',
260  'o','r','e','r','\\','M','y','C','o','m','p','u','t','e','r','\\','N','a','m',
261  'e','s','p','a','c','e','\0' };
262
263 static BOOL CreateMyCompEnumList(IEnumIDList *list, DWORD dwFlags)
264 {
265     BOOL ret = TRUE;
266
267     TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags);
268
269     /* enumerate the folders */
270     if (dwFlags & SHCONTF_FOLDERS)
271     {
272         WCHAR wszDriveName[] = {'A', ':', '\\', '\0'};
273         DWORD dwDrivemap = GetLogicalDrives();
274         HKEY hkey;
275
276         while (ret && wszDriveName[0]<='Z')
277         {
278             if(dwDrivemap & 0x00000001L)
279                 ret = AddToEnumList(list, _ILCreateDrive(wszDriveName));
280             wszDriveName[0]++;
281             dwDrivemap = dwDrivemap >> 1;
282         }
283
284         TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",list);
285         if (ret && !RegOpenKeyExW(HKEY_LOCAL_MACHINE, MyComputer_NameSpaceW,
286          0, KEY_READ, &hkey))
287         {
288             WCHAR iid[50];
289             int i=0;
290
291             while (ret)
292             {
293                 DWORD size;
294                 LONG r;
295
296                 size = sizeof(iid) / sizeof(iid[0]);
297                 r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL);
298                 if (ERROR_SUCCESS == r)
299                 {
300                     /* FIXME: shell extensions, shouldn't the type be
301                      * PT_SHELLEXT? */
302                     ret = AddToEnumList(list, _ILCreateGuidFromStrW(iid));
303                     i++;
304                 }
305                 else if (ERROR_NO_MORE_ITEMS == r)
306                     break;
307                 else
308                     ret = FALSE;
309             }
310             RegCloseKey(hkey);
311         }
312     }
313     return ret;
314 }
315
316 /**************************************************************************
317 *        ISF_MyComputer_fnEnumObjects
318 */
319 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects (IShellFolder2 *iface,
320                HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
321 {
322     IGenericSFImpl *This = (IGenericSFImpl *)iface;
323
324     TRACE("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This,
325           hwndOwner, dwFlags, ppEnumIDList);
326
327     *ppEnumIDList = IEnumIDList_Constructor();
328     if (*ppEnumIDList)
329         CreateMyCompEnumList(*ppEnumIDList, dwFlags);
330
331     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
332
333     return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
334 }
335
336 /**************************************************************************
337 *        ISF_MyComputer_fnBindToObject
338 */
339 static HRESULT WINAPI ISF_MyComputer_fnBindToObject (IShellFolder2 *iface,
340                LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
341 {
342     IGenericSFImpl *This = (IGenericSFImpl *)iface;
343
344     TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This,
345           pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
346
347     return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
348 }
349
350 /**************************************************************************
351 *    ISF_MyComputer_fnBindToStorage
352 */
353 static HRESULT WINAPI ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface,
354                LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
355 {
356     IGenericSFImpl *This = (IGenericSFImpl *)iface;
357
358     FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This,
359           pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
360
361     *ppvOut = NULL;
362     return E_NOTIMPL;
363 }
364
365 /**************************************************************************
366 *     ISF_MyComputer_fnCompareIDs
367 */
368
369 static HRESULT WINAPI ISF_MyComputer_fnCompareIDs (IShellFolder2 *iface,
370                LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
371 {
372     IGenericSFImpl *This = (IGenericSFImpl *)iface;
373     int nReturn;
374
375     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
376     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
377     TRACE ("-- %i\n", nReturn);
378     return nReturn;
379 }
380
381 /**************************************************************************
382 *    ISF_MyComputer_fnCreateViewObject
383 */
384 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject (IShellFolder2 *iface,
385                HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
386 {
387     IGenericSFImpl *This = (IGenericSFImpl *)iface;
388     LPSHELLVIEW pShellView;
389     HRESULT hr = E_INVALIDARG;
390
391     TRACE("(%p)->(hwnd=%p,%s,%p)\n", This,
392           hwndOwner, shdebugstr_guid (riid), ppvOut);
393
394     if (!ppvOut)
395         return hr;
396
397     *ppvOut = NULL;
398
399     if (IsEqualIID (riid, &IID_IDropTarget))
400     {
401         WARN ("IDropTarget not implemented\n");
402         hr = E_NOTIMPL;
403     }
404     else if (IsEqualIID (riid, &IID_IContextMenu))
405     {
406         WARN ("IContextMenu not implemented\n");
407         hr = E_NOTIMPL;
408     }
409     else if (IsEqualIID (riid, &IID_IShellView))
410     {
411         pShellView = IShellView_Constructor ((IShellFolder *) iface);
412         if (pShellView)
413         {
414             hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
415             IShellView_Release (pShellView);
416         }
417     }
418     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
419     return hr;
420 }
421
422 /**************************************************************************
423 *  ISF_MyComputer_fnGetAttributesOf
424 */
425 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface,
426                 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
427 {
428     IGenericSFImpl *This = (IGenericSFImpl *)iface;
429     HRESULT hr = S_OK;
430
431     TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
432
433     if (!cidl || !apidl || !rgfInOut)
434         return E_INVALIDARG;
435
436     if (*rgfInOut == 0)
437         *rgfInOut = ~0;
438
439     while (cidl > 0 && *apidl)
440     {
441         pdump (*apidl);
442         SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
443         apidl++;
444         cidl--;
445     }
446
447     TRACE ("-- result=0x%08lx\n", *rgfInOut);
448     return hr;
449 }
450
451 /**************************************************************************
452 *    ISF_MyComputer_fnGetUIObjectOf
453 *
454 * PARAMETERS
455 *  hwndOwner [in]  Parent window for any output
456 *  cidl      [in]  array size
457 *  apidl     [in]  simple pidl array
458 *  riid      [in]  Requested Interface
459 *  prgfInOut [   ] reserved
460 *  ppvObject [out] Resulting Interface
461 *
462 */
463 static HRESULT WINAPI ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
464                 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
465                 UINT * prgfInOut, LPVOID * ppvOut)
466 {
467     IGenericSFImpl *This = (IGenericSFImpl *)iface;
468
469     LPITEMIDLIST pidl;
470     IUnknown *pObj = NULL;
471     HRESULT hr = E_INVALIDARG;
472
473     TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", This,
474           hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
475
476     if (!ppvOut)
477         return hr;
478
479     *ppvOut = NULL;
480
481     if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
482     {
483         pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface,
484                                               This->pidlRoot, apidl, cidl);
485         hr = S_OK;
486     }
487     else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
488     {
489         pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
490                                               This->pidlRoot, apidl, cidl);
491         hr = S_OK;
492     }
493     else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
494     {
495         pidl = ILCombine (This->pidlRoot, apidl[0]);
496         pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
497         SHFree (pidl);
498         hr = S_OK;
499     }
500     else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
501     {
502         pidl = ILCombine (This->pidlRoot, apidl[0]);
503         pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
504         SHFree (pidl);
505         hr = S_OK;
506     }
507     else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
508     {
509         hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget,
510                                           (LPVOID *) &pObj);
511     }
512     else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
513               IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1))
514     {
515         pidl = ILCombine (This->pidlRoot, apidl[0]);
516         hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*) &pObj);
517         SHFree (pidl);
518     }
519     else 
520         hr = E_NOINTERFACE;
521
522     if (SUCCEEDED(hr) && !pObj)
523         hr = E_OUTOFMEMORY;
524
525     *ppvOut = pObj;
526     TRACE ("(%p)->hr=0x%08lx\n", This, hr);
527     return hr;
528 }
529
530 /**************************************************************************
531 *    ISF_MyComputer_fnGetDisplayNameOf
532 */
533 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 *iface,
534                LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
535 {
536     IGenericSFImpl *This = (IGenericSFImpl *)iface;
537
538     char szPath[MAX_PATH], szDrive[18];
539     int len = 0;
540     BOOL bSimplePidl;
541     HRESULT hr = S_OK;
542
543     TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
544     pdump (pidl);
545
546     if (!strRet)
547         return E_INVALIDARG;
548
549     szPath[0] = 0x00;
550     szDrive[0] = 0x00;
551
552     bSimplePidl = _ILIsPidlSimple (pidl);
553
554     if (!pidl->mkid.cb)
555     {
556         /* parsing name like ::{...} */
557         lstrcpyA (szPath, "::");
558         SHELL32_GUIDToStringA(&CLSID_MyComputer, &szPath[2]);
559     }
560     else if (_ILIsSpecialFolder (pidl))
561     {
562         /* take names of special folders only if its only this folder */
563         if (bSimplePidl)
564         {
565             GUID const *clsid;
566
567             clsid = _ILGetGUIDPointer (pidl);
568             if (clsid)
569             {
570                 if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
571                 {
572                     static const WCHAR clsidW[] =
573                      { 'C','L','S','I','D','\\',0 };
574                     static const WCHAR shellfolderW[] =
575                      { '\\','s','h','e','l','l','f','o','l','d','e','r',0 };
576                     static const WCHAR wantsForParsingW[] =
577                      { 'W','a','n','t','s','F','o','r','P','a','r','s','i','n',
578                      'g',0 };
579                     int bWantsForParsing = FALSE;
580                     WCHAR szRegPath[100];
581                     LONG r;
582
583                     /*
584                      * We can only get a filesystem path from a shellfolder
585                      * if the value WantsFORPARSING exists in
586                      *      CLSID\\{...}\\shellfolder 
587                      * exception: the MyComputer folder has this keys not
588                      *            but like any filesystem backed
589                      *            folder it needs these behaviour
590                      *
591                      * Get the "WantsFORPARSING" flag from the registry
592                      */
593
594                     lstrcpyW (szRegPath, clsidW);
595                     SHELL32_GUIDToStringW (clsid, &szRegPath[6]);
596                     lstrcatW (szRegPath, shellfolderW);
597                     r = SHGetValueW (HKEY_CLASSES_ROOT, szRegPath, 
598                                      wantsForParsingW, NULL, NULL, NULL);
599                     if (r == ERROR_SUCCESS)
600                         bWantsForParsing = TRUE;
601
602                     if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
603                         bWantsForParsing)
604                     {
605                         /*
606                          * We need the filesystem path to the destination folder
607                          * Only the folder itself can know it
608                          */
609                         hr = SHELL32_GetDisplayNameOfChild (iface, pidl,
610                                                 dwFlags, szPath, MAX_PATH);
611                     }
612                     else
613                     {
614                         LPSTR p;
615
616                         /* parsing name like ::{...} */
617                         p = lstrcpyA(szPath, "::") + 2;
618                         p += SHELL32_GUIDToStringA(&CLSID_MyComputer, p);
619
620                         lstrcatA(p, "\\::");
621                         p += 3;
622                         SHELL32_GUIDToStringA(clsid, p);
623                     }
624                 }
625                 else
626                 {
627                     /* user friendly name */
628                     HCR_GetClassNameA (clsid, szPath, MAX_PATH);
629                 }
630             }
631             else
632             {
633                 /* append my own path */
634                 _ILSimpleGetText (pidl, szPath, MAX_PATH);
635             }
636         }
637         else
638             FIXME ("special folder\n");
639     }
640     else
641     {
642         if (!_ILIsDrive (pidl))
643         {
644             ERR ("Wrong pidl type\n");
645             return E_INVALIDARG;
646         }
647
648         _ILSimpleGetText (pidl, szPath, MAX_PATH);    /* append my own path */
649
650         /* long view "lw_name (C:)" */
651         if (bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
652         {
653             DWORD dwVolumeSerialNumber, dwMaximumComponetLength, dwFileSystemFlags;
654
655             GetVolumeInformationA (szPath, szDrive, sizeof (szDrive) - 6,
656                        &dwVolumeSerialNumber,
657                        &dwMaximumComponetLength, &dwFileSystemFlags, NULL, 0);
658             strcat (szDrive, " (");
659             strncat (szDrive, szPath, 2);
660             strcat (szDrive, ")");
661             strcpy (szPath, szDrive);
662         }
663     }
664
665     if (!bSimplePidl)
666     {
667         /* go deeper if needed */
668         PathAddBackslashA (szPath);
669         len = strlen (szPath);
670
671         hr = SHELL32_GetDisplayNameOfChild (iface, pidl,
672                   dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len);
673     }
674
675     if (SUCCEEDED (hr))
676     {
677         strRet->uType = STRRET_CSTR;
678         lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
679     }
680
681     TRACE ("-- (%p)->(%s)\n", This, szPath);
682     return hr;
683 }
684
685 /**************************************************************************
686 *  ISF_MyComputer_fnSetNameOf
687 *  Changes the name of a file object or subfolder, possibly changing its item
688 *  identifier in the process.
689 *
690 * PARAMETERS
691 *  hwndOwner  [in]   Owner window for output
692 *  pidl       [in]   simple pidl of item to change
693 *  lpszName   [in]   the items new display name
694 *  dwFlags    [in]   SHGNO formatting flags
695 *  ppidlOut   [out]  simple pidl returned
696 */
697 static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (
698                IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,
699                LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
700 {
701     IGenericSFImpl *This = (IGenericSFImpl *)iface;
702     FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This,
703            hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
704     return E_FAIL;
705 }
706
707 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID (
708                IShellFolder2 * iface, GUID * pguid)
709 {
710     IGenericSFImpl *This = (IGenericSFImpl *)iface;
711     FIXME ("(%p)\n", This);
712     return E_NOTIMPL;
713 }
714 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (
715                IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
716 {
717     IGenericSFImpl *This = (IGenericSFImpl *)iface;
718     FIXME ("(%p)\n", This);
719     return E_NOTIMPL;
720 }
721 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn (
722                IShellFolder2 *iface, DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
723 {
724     IGenericSFImpl *This = (IGenericSFImpl *)iface;
725
726     TRACE ("(%p)\n", This);
727
728     if (pSort)
729          *pSort = 0;
730     if (pDisplay)
731         *pDisplay = 0;
732     return S_OK;
733 }
734 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (
735                IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
736 {
737     IGenericSFImpl *This = (IGenericSFImpl *)iface;
738
739     TRACE ("(%p)\n", This);
740
741     if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
742         return E_INVALIDARG;
743     *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
744     return S_OK;
745 }
746
747 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface,
748                LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
749 {
750     IGenericSFImpl *This = (IGenericSFImpl *)iface;
751     FIXME ("(%p)\n", This);
752     return E_NOTIMPL;
753 }
754
755 /* FIXME: drive size >4GB is rolling over */
756 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 * iface,
757                LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
758 {
759     IGenericSFImpl *This = (IGenericSFImpl *)iface;
760     HRESULT hr;
761
762     TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
763
764     if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS)
765         return E_INVALIDARG;
766
767     if (!pidl)
768     {
769         psd->fmt = MyComputerSFHeader[iColumn].fmt;
770         psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
771         psd->str.uType = STRRET_CSTR;
772         LoadStringA (shell32_hInstance, MyComputerSFHeader[iColumn].colnameid,
773                      psd->str.u.cStr, MAX_PATH);
774         return S_OK;
775     }
776     else
777     {
778         char szPath[MAX_PATH];
779         ULARGE_INTEGER ulBytes;
780
781         psd->str.u.cStr[0] = 0x00;
782         psd->str.uType = STRRET_CSTR;
783         switch (iColumn)
784         {
785         case 0:        /* name */
786             hr = IShellFolder_GetDisplayNameOf (iface, pidl,
787                        SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
788             break;
789         case 1:        /* type */
790             _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
791             break;
792         case 2:        /* total size */
793             if (_ILIsDrive (pidl))
794             {
795                 _ILSimpleGetText (pidl, szPath, MAX_PATH);
796                 GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
797                 StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH);
798             }
799             break;
800         case 3:        /* free size */
801             if (_ILIsDrive (pidl))
802             {
803                 _ILSimpleGetText (pidl, szPath, MAX_PATH);
804                 GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
805                 StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH);
806             }
807             break;
808         }
809         hr = S_OK;
810     }
811
812     return hr;
813 }
814
815 static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (
816                IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
817 {
818     IGenericSFImpl *This = (IGenericSFImpl *)iface;
819     FIXME ("(%p)\n", This);
820     return E_NOTIMPL;
821 }
822
823 static IShellFolder2Vtbl vt_ShellFolder2 =
824 {
825     ISF_MyComputer_fnQueryInterface,
826     ISF_MyComputer_fnAddRef,
827     ISF_MyComputer_fnRelease,
828     ISF_MyComputer_fnParseDisplayName,
829     ISF_MyComputer_fnEnumObjects,
830     ISF_MyComputer_fnBindToObject,
831     ISF_MyComputer_fnBindToStorage,
832     ISF_MyComputer_fnCompareIDs,
833     ISF_MyComputer_fnCreateViewObject,
834     ISF_MyComputer_fnGetAttributesOf,
835     ISF_MyComputer_fnGetUIObjectOf,
836     ISF_MyComputer_fnGetDisplayNameOf,
837     ISF_MyComputer_fnSetNameOf,
838     /* ShellFolder2 */
839     ISF_MyComputer_fnGetDefaultSearchGUID,
840     ISF_MyComputer_fnEnumSearches,
841     ISF_MyComputer_fnGetDefaultColumn,
842     ISF_MyComputer_fnGetDefaultColumnState,
843     ISF_MyComputer_fnGetDetailsEx,
844     ISF_MyComputer_fnGetDetailsOf,
845     ISF_MyComputer_fnMapColumnToSCID
846 };
847
848 /************************************************************************
849  *    IMCFldr_PersistFolder2_QueryInterface
850  */
851 static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (
852                IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
853 {
854     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
855
856     TRACE ("(%p)\n", This);
857
858     return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
859 }
860
861 /************************************************************************
862  *    IMCFldr_PersistFolder2_AddRef
863  */
864 static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
865 {
866     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
867
868     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
869
870     return IUnknown_AddRef (_IUnknown_ (This));
871 }
872
873 /************************************************************************
874  *    ISFPersistFolder_Release
875  */
876 static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface)
877 {
878     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
879
880     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
881
882     return IUnknown_Release (_IUnknown_ (This));
883 }
884
885 /************************************************************************
886  *    IMCFldr_PersistFolder2_GetClassID
887  */
888 static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (
889                IPersistFolder2 * iface, CLSID * lpClassId)
890 {
891     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
892
893     TRACE ("(%p)\n", This);
894
895     if (!lpClassId)
896     return E_POINTER;
897     *lpClassId = CLSID_MyComputer;
898
899     return S_OK;
900 }
901
902 /************************************************************************
903  *    IMCFldr_PersistFolder2_Initialize
904  *
905  * NOTES: it makes no sense to change the pidl
906  */
907 static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (
908                IPersistFolder2 * iface, LPCITEMIDLIST pidl)
909 {
910     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
911     TRACE ("(%p)->(%p)\n", This, pidl);
912     return E_NOTIMPL;
913 }
914
915 /**************************************************************************
916  *    IPersistFolder2_fnGetCurFolder
917  */
918 static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (
919                IPersistFolder2 * iface, LPITEMIDLIST * pidl)
920 {
921     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
922
923     TRACE ("(%p)->(%p)\n", This, pidl);
924
925     if (!pidl)
926         return E_POINTER;
927     *pidl = ILClone (This->pidlRoot);
928     return S_OK;
929 }
930
931 static IPersistFolder2Vtbl vt_PersistFolder2 =
932 {
933     IMCFldr_PersistFolder2_QueryInterface,
934     IMCFldr_PersistFolder2_AddRef,
935     IMCFldr_PersistFolder2_Release,
936     IMCFldr_PersistFolder2_GetClassID,
937     IMCFldr_PersistFolder2_Initialize,
938     IMCFldr_PersistFolder2_GetCurFolder
939 };