Remove tabs and make formatting consistent.
[wine] / dlls / shell32 / shfldr_desktop.c
1
2 /*
3  *    Virtual Desktop 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 COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34
35 #include "winerror.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winreg.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41
42 #include "ole2.h"
43 #include "shlguid.h"
44
45 #include "enumidlist.h"
46 #include "pidl.h"
47 #include "undocshell.h"
48 #include "shell32_main.h"
49 #include "shresdef.h"
50 #include "shlwapi.h"
51 #include "shellfolder.h"
52 #include "wine/debug.h"
53 #include "debughlp.h"
54 #include "shfldr.h"
55
56 WINE_DEFAULT_DEBUG_CHANNEL (shell);
57
58 /***********************************************************************
59 *     Desktopfolder implementation
60 */
61
62 typedef struct {
63     IShellFolder2Vtbl *lpVtbl;
64     DWORD ref;
65
66     CLSID *pclsid;
67
68     /* both paths are parsible from the desktop */
69     LPSTR sPathTarget;        /* complete path to target used for enumeration and ChangeNotify */
70     LPITEMIDLIST pidlRoot;    /* absolute pidl */
71
72     int dwAttributes;        /* attributes returned by GetAttributesOf FIXME: use it */
73
74     UINT cfShellIDList;        /* clipboardformat for IDropTarget */
75     BOOL fAcceptFmt;        /* flag for pending Drop */
76 } IGenericSFImpl;
77
78 #define _IUnknown_(This)    (IShellFolder*)&(This->lpVtbl)
79 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpVtbl)
80
81 static struct IShellFolder2Vtbl vt_MCFldr_ShellFolder2;
82
83 static shvheader DesktopSFHeader[] = {
84     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
85     {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
86     {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
87     {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
88     {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
89 };
90
91 #define DESKTOPSHELLVIEWCOLUMNS 5
92
93 /**************************************************************************
94  *    ISF_Desktop_Constructor
95  */
96 HRESULT WINAPI ISF_Desktop_Constructor (
97                 IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
98 {
99     IGenericSFImpl *sf;
100     char szMyPath[MAX_PATH];
101
102     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
103
104     if (!ppv)
105         return E_POINTER;
106     if (pUnkOuter)
107         return CLASS_E_NOAGGREGATION;
108
109     if (!SHGetSpecialFolderPathA (0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE))
110         return E_UNEXPECTED;
111
112     sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
113     if (!sf)
114         return E_OUTOFMEMORY;
115
116     sf->ref = 0;
117     sf->lpVtbl = &vt_MCFldr_ShellFolder2;
118     sf->pidlRoot = _ILCreateDesktop ();    /* my qualified pidl */
119     sf->sPathTarget = SHAlloc (strlen (szMyPath) + 1);
120     lstrcpyA (sf->sPathTarget, szMyPath);
121
122     if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv)))
123     {
124         IUnknown_Release (_IUnknown_ (sf));
125         return E_NOINTERFACE;
126     }
127
128     TRACE ("--(%p)\n", sf);
129     return S_OK;
130 }
131
132 /**************************************************************************
133  *    ISF_Desktop_fnQueryInterface
134  *
135  * NOTES supports not IPersist/IPersistFolder
136  */
137 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
138                 IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
139 {
140     IGenericSFImpl *This = (IGenericSFImpl *)iface;
141
142     TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
143
144     *ppvObj = NULL;
145
146     if (IsEqualIID (riid, &IID_IUnknown) ||
147         IsEqualIID (riid, &IID_IShellFolder) ||
148         IsEqualIID (riid, &IID_IShellFolder2))
149     {
150         *ppvObj = This;
151     }
152
153     if (*ppvObj)
154     {
155         IUnknown_AddRef ((IUnknown *) (*ppvObj));
156         TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
157         return S_OK;
158     }
159     TRACE ("-- Interface: E_NOINTERFACE\n");
160     return E_NOINTERFACE;
161 }
162
163 static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface)
164 {
165     IGenericSFImpl *This = (IGenericSFImpl *)iface;
166     ULONG refCount = InterlockedIncrement(&This->ref);
167
168     TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
169
170     return refCount;
171 }
172
173 static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface)
174 {
175     IGenericSFImpl *This = (IGenericSFImpl *)iface;
176     ULONG refCount = InterlockedDecrement(&This->ref);
177
178     TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
179
180     if (!refCount)
181     {
182         TRACE ("-- destroying IShellFolder(%p)\n", This);
183         if (This->pidlRoot)
184             SHFree (This->pidlRoot);
185         if (This->sPathTarget)
186             SHFree (This->sPathTarget);
187         LocalFree ((HLOCAL) This);
188         return 0;
189     }
190     return refCount;
191 }
192
193 /**************************************************************************
194  *    ISF_Desktop_fnParseDisplayName
195  *
196  * NOTES
197  *    "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
198  *    to MyComputer
199  */
200 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface,
201                 HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
202                 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
203 {
204     IGenericSFImpl *This = (IGenericSFImpl *)iface;
205     WCHAR szElement[MAX_PATH];
206     LPCWSTR szNext = NULL;
207     LPITEMIDLIST pidlTemp = NULL;
208     HRESULT hr = S_OK;
209     char szPath[MAX_PATH];
210     DWORD len;
211     CLSID clsid;
212
213     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
214            This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
215            pchEaten, ppidl, pdwAttributes);
216
217     if (!lpszDisplayName || !ppidl)
218         return E_INVALIDARG;
219
220     *ppidl = 0;
221
222     if (pchEaten)
223         *pchEaten = 0;        /* strange but like the original */
224
225     if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
226     {
227         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
228         TRACE ("-- element: %s\n", debugstr_w (szElement));
229         SHCLSIDFromStringW (szElement + 2, &clsid);
230         pidlTemp = _ILCreateGuid (PT_GUID, &clsid);
231     }
232     else if (PathGetDriveNumberW (lpszDisplayName) >= 0)
233     {
234         /* it's a filesystem path with a drive. Let MyComputer parse it */
235         pidlTemp = _ILCreateMyComputer ();
236         szNext = lpszDisplayName;
237     }
238     else if (PathIsUNCW(lpszDisplayName))
239     {
240         pidlTemp = _ILCreateNetwork();
241         szNext = lpszDisplayName;
242     }
243     else
244     {
245         /* it's a filesystem path on the desktop. Let a FSFolder parse it */
246
247         if (*lpszDisplayName)
248         {
249             /* build a complete path to create a simple pidl */
250             lstrcpyA(szPath, This->sPathTarget);
251             PathAddBackslashA(szPath);
252             len = lstrlenA(szPath);
253             WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1,
254                                 szPath + len, MAX_PATH - len, NULL, NULL);
255             hr = _ILCreateFromPathA(szPath, &pidlTemp);
256         }
257         else
258             pidlTemp = _ILCreateMyComputer();
259
260         szNext = NULL;
261     }
262
263     if (SUCCEEDED(hr) && pidlTemp)
264     {
265         if (szNext && *szNext)
266         {
267             hr = SHELL32_ParseNextElement(iface, hwndOwner, pbc,
268                     &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
269         }
270         else
271         {
272             if (pdwAttributes && *pdwAttributes)
273                 hr = SHELL32_GetItemAttributes(_IShellFolder_ (This),
274                                                pidlTemp, pdwAttributes);
275         }
276     }
277
278     *ppidl = pidlTemp;
279
280     TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
281
282     return hr;
283 }
284
285 /**************************************************************************
286  *  CreateDesktopEnumList()
287  */
288 static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags)
289 {
290     BOOL ret = TRUE;
291     char szPath[MAX_PATH];
292
293     TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags);
294
295     /* enumerate the root folders */
296     if (dwFlags & SHCONTF_FOLDERS)
297     {
298         HKEY hkey;
299         LONG r;
300
301         /* create the pidl for This item */
302         ret = AddToEnumList(list, _ILCreateMyComputer());
303
304         r = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
305                           "SOFTWARE\\Microsoft\\Windows\\"
306                           "CurrentVersion\\explorer\\desktop\\NameSpace",
307                           0, KEY_READ, &hkey);
308         if (ret && ERROR_SUCCESS == r)
309         {
310             char iid[50];
311             int i=0;
312             BOOL moreKeys = TRUE;
313
314             while (ret && moreKeys)
315             {
316                 DWORD size;
317
318                 size = sizeof (iid);
319                 r = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL, NULL);
320                 if (ERROR_SUCCESS == r)
321                 {
322                     ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid));
323                     i++;
324                 }
325                 else if (ERROR_NO_MORE_ITEMS == r)
326                     moreKeys = FALSE;
327                 else
328                     ret = FALSE;
329             }
330             RegCloseKey(hkey);
331         }
332     }
333
334     /* enumerate the elements in %windir%\desktop */
335     SHGetSpecialFolderPathA(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE);
336     ret = ret && CreateFolderEnumList(list, szPath, dwFlags);
337
338     return ret;
339 }
340
341 /**************************************************************************
342  *        ISF_Desktop_fnEnumObjects
343  */
344 static HRESULT WINAPI ISF_Desktop_fnEnumObjects (IShellFolder2 * iface,
345                 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
346 {
347     IGenericSFImpl *This = (IGenericSFImpl *)iface;
348
349     TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n",
350            This, hwndOwner, dwFlags, ppEnumIDList);
351
352     *ppEnumIDList = IEnumIDList_Constructor();
353     if (*ppEnumIDList)
354         CreateDesktopEnumList(*ppEnumIDList, dwFlags);
355
356     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
357
358     return *ppEnumIDList ? S_OK : E_OUTOFMEMORY;
359 }
360
361 /**************************************************************************
362  *        ISF_Desktop_fnBindToObject
363  */
364 static HRESULT WINAPI ISF_Desktop_fnBindToObject (IShellFolder2 * iface,
365                 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
366 {
367     IGenericSFImpl *This = (IGenericSFImpl *)iface;
368
369     TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
370            This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
371
372     return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut);
373 }
374
375 /**************************************************************************
376  *    ISF_Desktop_fnBindToStorage
377  */
378 static HRESULT WINAPI ISF_Desktop_fnBindToStorage (IShellFolder2 * iface,
379                 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
380 {
381     IGenericSFImpl *This = (IGenericSFImpl *)iface;
382
383     FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
384            This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
385
386     *ppvOut = NULL;
387     return E_NOTIMPL;
388 }
389
390 /**************************************************************************
391  *     ISF_Desktop_fnCompareIDs
392  */
393 static HRESULT WINAPI ISF_Desktop_fnCompareIDs (IShellFolder2 * iface,
394                         LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
395 {
396     IGenericSFImpl *This = (IGenericSFImpl *)iface;
397     int nReturn;
398
399     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
400     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
401     TRACE ("-- %i\n", nReturn);
402     return nReturn;
403 }
404
405 /**************************************************************************
406  *    ISF_Desktop_fnCreateViewObject
407  */
408 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface,
409                               HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
410 {
411     IGenericSFImpl *This = (IGenericSFImpl *)iface;
412     LPSHELLVIEW pShellView;
413     HRESULT hr = E_INVALIDARG;
414
415     TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
416            This, hwndOwner, shdebugstr_guid (riid), ppvOut);
417
418     if (!ppvOut)
419         return hr;
420
421     *ppvOut = NULL;
422
423     if (IsEqualIID (riid, &IID_IDropTarget))
424     {
425         WARN ("IDropTarget not implemented\n");
426         hr = E_NOTIMPL;
427     }
428     else if (IsEqualIID (riid, &IID_IContextMenu))
429     {
430         WARN ("IContextMenu not implemented\n");
431         hr = E_NOTIMPL;
432     }
433     else if (IsEqualIID (riid, &IID_IShellView))
434     {
435         pShellView = IShellView_Constructor ((IShellFolder *) iface);
436         if (pShellView)
437         {
438             hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
439             IShellView_Release (pShellView);
440         }
441     }
442     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
443     return hr;
444 }
445
446 /**************************************************************************
447  *  ISF_Desktop_fnGetAttributesOf
448  */
449 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface,
450                 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
451 {
452     IGenericSFImpl *This = (IGenericSFImpl *)iface;
453     HRESULT hr = S_OK;
454
455     TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",
456            This, cidl, apidl, *rgfInOut);
457
458     if (!cidl || !apidl || !rgfInOut)
459         return E_INVALIDARG;
460
461     if (*rgfInOut == 0)
462         *rgfInOut = ~0;
463
464     while (cidl > 0 && *apidl)
465     {
466         pdump (*apidl);
467         SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
468         apidl++;
469         cidl--;
470     }
471
472     TRACE ("-- result=0x%08lx\n", *rgfInOut);
473
474     return hr;
475 }
476
477 /**************************************************************************
478  *    ISF_Desktop_fnGetUIObjectOf
479  *
480  * PARAMETERS
481  *  HWND           hwndOwner, //[in ] Parent window for any output
482  *  UINT           cidl,      //[in ] array size
483  *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
484  *  REFIID         riid,      //[in ] Requested Interface
485  *  UINT*          prgfInOut, //[   ] reserved
486  *  LPVOID*        ppvObject) //[out] Resulting Interface
487  *
488  */
489 static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface,
490                 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
491                 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
492 {
493     IGenericSFImpl *This = (IGenericSFImpl *)iface;
494
495     LPITEMIDLIST pidl;
496     IUnknown *pObj = NULL;
497     HRESULT hr = E_INVALIDARG;
498
499     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
500        This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
501
502     if (!ppvOut)
503         return hr;
504
505     *ppvOut = NULL;
506
507     if (IsEqualIID (riid, &IID_IContextMenu))
508     {
509         pObj = (LPUNKNOWN) ISvItemCm_Constructor( (IShellFolder *) iface,
510                                                   This->pidlRoot, apidl, cidl);
511         hr = S_OK;
512     }
513     else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
514     {
515         pObj = (LPUNKNOWN) IDataObject_Constructor( hwndOwner,
516                                                   This->pidlRoot, apidl, cidl);
517         hr = S_OK;
518     }
519     else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
520     {
521         pidl = ILCombine (This->pidlRoot, apidl[0]);
522         pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
523         SHFree (pidl);
524         hr = S_OK;
525     }
526     else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
527     {
528         pidl = ILCombine (This->pidlRoot, apidl[0]);
529         pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
530         SHFree (pidl);
531         hr = S_OK;
532     }
533     else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
534     {
535         hr = IShellFolder_QueryInterface (iface,
536                                           &IID_IDropTarget, (LPVOID *) & pObj);
537     }
538     else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
539               IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1))
540     {
541         pidl = ILCombine (This->pidlRoot, apidl[0]);
542         hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
543         SHFree (pidl);
544     }
545     else
546         hr = E_NOINTERFACE;
547
548     if (SUCCEEDED(hr) && !pObj)
549         hr = E_OUTOFMEMORY;
550
551     *ppvOut = pObj;
552     TRACE ("(%p)->hr=0x%08lx\n", This, hr);
553     return hr;
554 }
555
556 /**************************************************************************
557  *    ISF_Desktop_fnGetDisplayNameOf
558  *
559  * NOTES
560  *    special case: pidl = null gives desktop-name back
561  */
562 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface,
563                 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
564 {
565     IGenericSFImpl *This = (IGenericSFImpl *)iface;
566     CHAR szPath[MAX_PATH];
567     GUID const *clsid;
568     HRESULT hr = S_OK;
569
570     *szPath = '\0';
571
572     TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
573     pdump (pidl);
574
575     if (!strRet)
576         return E_INVALIDARG;
577
578     if (_ILIsDesktop (pidl))
579     {
580         if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
581             (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING))
582         {
583             lstrcpyA (szPath, This->sPathTarget);
584         }
585         else
586             HCR_GetClassNameA(&CLSID_ShellDesktop, szPath, MAX_PATH);
587     }
588     else if (_ILIsPidlSimple (pidl))
589     {
590         if ((clsid = _ILGetGUIDPointer (pidl)))
591         {
592             if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
593             {
594                 int bWantsForParsing;
595
596                 /*
597                  * We can only get a filesystem path from a shellfolder if the
598                  *  value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
599                  *
600                  * Exception: The MyComputer folder doesn't have this key,
601                  *   but any other filesystem backed folder it needs it.
602                  */
603                 if (IsEqualIID (clsid, &CLSID_MyComputer))
604                 {
605                     bWantsForParsing = 1;
606                 }
607                 else
608                 {
609                     /* get the "WantsFORPARSING" flag from the registry */
610                     char szRegPath[100];
611                     LONG r;
612
613                     lstrcpyA (szRegPath, "CLSID\\");
614                     SHELL32_GUIDToStringA (clsid, &szRegPath[6]);
615                     lstrcatA (szRegPath, "\\shellfolder");
616                     r = SHGetValueA(HKEY_CLASSES_ROOT, szRegPath,
617                                     "WantsFORPARSING", NULL, NULL, NULL);
618                     if (r == ERROR_SUCCESS)
619                         bWantsForParsing = TRUE;
620                     else
621                         bWantsForParsing = FALSE;
622                 }
623
624                 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
625                      bWantsForParsing)
626                 {
627                     /*
628                      * we need the filesystem path to the destination folder.
629                      * Only the folder itself can know it
630                      */
631                     hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags,
632                                                         szPath, MAX_PATH);
633                 }
634                 else
635                 {
636                     /* parsing name like ::{...} */
637                     lstrcpyA (szPath, "::");
638                     SHELL32_GUIDToStringA (clsid, &szPath[2]);
639                 }
640             }
641             else
642             {
643                 /* user friendly name */
644                 HCR_GetClassNameA (clsid, szPath, MAX_PATH);
645             }
646         }
647         else
648         {
649             /* file system folder */
650             _ILSimpleGetText (pidl, szPath, MAX_PATH);
651
652             if (!_ILIsFolder(pidl))
653             SHELL_FS_ProcessDisplayFilename(szPath, dwFlags);
654         }
655     }
656     else
657     {
658         /* a complex pidl, let the subfolder do the work */
659         hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH);
660     }
661
662     if (SUCCEEDED (hr))
663     {
664         strRet->uType = STRRET_CSTR;
665         lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
666     }
667
668     TRACE ("-- (%p)->(%s,0x%08lx)\n", This, szPath, hr);
669     return hr;
670 }
671
672 /**************************************************************************
673  *  ISF_Desktop_fnSetNameOf
674  *  Changes the name of a file object or subfolder, possibly changing its item
675  *  identifier in the process.
676  *
677  * PARAMETERS
678  *  HWND          hwndOwner,  //[in ] Owner window for output
679  *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
680  *  LPCOLESTR     lpszName,   //[in ] the items new display name
681  *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
682  *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
683  */
684 static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface,
685                 HWND hwndOwner, LPCITEMIDLIST pidl,    /* simple pidl */
686                 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
687 {
688     IGenericSFImpl *This = (IGenericSFImpl *)iface;
689
690     FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl,
691            debugstr_w (lpName), dwFlags, pPidlOut);
692
693     return E_FAIL;
694 }
695
696 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(IShellFolder2 *iface,
697                 GUID * pguid)
698 {
699     IGenericSFImpl *This = (IGenericSFImpl *)iface;
700
701     FIXME ("(%p)\n", This);
702     return E_NOTIMPL;
703 }
704
705 static HRESULT WINAPI ISF_Desktop_fnEnumSearches (IShellFolder2 *iface,
706                 IEnumExtraSearch ** ppenum)
707 {
708     IGenericSFImpl *This = (IGenericSFImpl *)iface;
709     FIXME ("(%p)\n", This);
710     return E_NOTIMPL;
711 }
712
713 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn (IShellFolder2 * iface,
714                 DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
715 {
716     IGenericSFImpl *This = (IGenericSFImpl *)iface;
717
718     TRACE ("(%p)\n", This);
719
720     if (pSort)
721         *pSort = 0;
722     if (pDisplay)
723         *pDisplay = 0;
724
725     return S_OK;
726 }
727 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState (
728                 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
729 {
730     IGenericSFImpl *This = (IGenericSFImpl *)iface;
731
732     TRACE ("(%p)\n", This);
733
734     if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
735     return E_INVALIDARG;
736
737     *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
738
739     return S_OK;
740 }
741
742 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx (IShellFolder2 * iface,
743                 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
744 {
745     IGenericSFImpl *This = (IGenericSFImpl *)iface;
746     FIXME ("(%p)\n", This);
747
748     return E_NOTIMPL;
749 }
750
751 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface,
752                 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
753 {
754     IGenericSFImpl *This = (IGenericSFImpl *)iface;
755
756     HRESULT hr = E_FAIL;
757
758     TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
759
760     if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
761         return E_INVALIDARG;
762
763     if (!pidl)
764     {
765         psd->fmt = DesktopSFHeader[iColumn].fmt;
766         psd->cxChar = DesktopSFHeader[iColumn].cxChar;
767         psd->str.uType = STRRET_CSTR;
768         LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid,
769                      psd->str.u.cStr, MAX_PATH);
770         return S_OK;
771     }
772
773     /* the data from the pidl */
774     switch (iColumn)
775     {
776     case 0:        /* name */
777         hr = IShellFolder_GetDisplayNameOf(iface, pidl,
778                    SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
779         break;
780     case 1:        /* size */
781         _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
782         break;
783     case 2:        /* type */
784         _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
785         break;
786     case 3:        /* date */
787         _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
788         break;
789     case 4:        /* attributes */
790         _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
791         break;
792     }
793     hr = S_OK;
794     psd->str.uType = STRRET_CSTR;
795
796     return hr;
797 }
798
799 static HRESULT WINAPI ISF_Desktop_fnMapColumnToSCID (
800                 IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
801 {
802     IGenericSFImpl *This = (IGenericSFImpl *)iface;
803     FIXME ("(%p)\n", This);
804     return E_NOTIMPL;
805 }
806
807 static IShellFolder2Vtbl vt_MCFldr_ShellFolder2 =
808 {
809     ISF_Desktop_fnQueryInterface,
810     ISF_Desktop_fnAddRef,
811     ISF_Desktop_fnRelease,
812     ISF_Desktop_fnParseDisplayName,
813     ISF_Desktop_fnEnumObjects,
814     ISF_Desktop_fnBindToObject,
815     ISF_Desktop_fnBindToStorage,
816     ISF_Desktop_fnCompareIDs,
817     ISF_Desktop_fnCreateViewObject,
818     ISF_Desktop_fnGetAttributesOf,
819     ISF_Desktop_fnGetUIObjectOf,
820     ISF_Desktop_fnGetDisplayNameOf,
821     ISF_Desktop_fnSetNameOf,
822     /* ShellFolder2 */
823     ISF_Desktop_fnGetDefaultSearchGUID,
824     ISF_Desktop_fnEnumSearches,
825     ISF_Desktop_fnGetDefaultColumn,
826     ISF_Desktop_fnGetDefaultColumnState,
827     ISF_Desktop_fnGetDetailsEx,
828     ISF_Desktop_fnGetDetailsOf,
829     ISF_Desktop_fnMapColumnToSCID
830 };