Removed W->A from DEFWND_ImmIsUIMessageW.
[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 (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
97 {
98     IGenericSFImpl *sf;
99     char szMyPath[MAX_PATH];
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     if (!SHGetSpecialFolderPathA (0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE))
109         return E_UNEXPECTED;
110
111     sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
112     if (!sf)
113         return E_OUTOFMEMORY;
114
115     sf->ref = 0;
116     sf->lpVtbl = &vt_MCFldr_ShellFolder2;
117     sf->pidlRoot = _ILCreateDesktop (); /* my qualified pidl */
118     sf->sPathTarget = SHAlloc (strlen (szMyPath) + 1);
119     lstrcpyA (sf->sPathTarget, szMyPath);
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_Desktop_fnQueryInterface
132  *
133  * NOTES supports not IPersist/IPersistFolder
134  */
135 static HRESULT WINAPI ISF_Desktop_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
136 {
137     IGenericSFImpl *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) || IsEqualIID (riid, &IID_IShellFolder)
144         || IsEqualIID (riid, &IID_IShellFolder2)) {
145         *ppvObj = This;
146     }
147
148     if (*ppvObj) {
149         IUnknown_AddRef ((IUnknown *) (*ppvObj));
150         TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
151         return S_OK;
152     }
153     TRACE ("-- Interface: E_NOINTERFACE\n");
154     return E_NOINTERFACE;
155 }
156
157 static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface)
158 {
159     IGenericSFImpl *This = (IGenericSFImpl *)iface;
160
161     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
162
163     return ++(This->ref);
164 }
165
166 static ULONG WINAPI ISF_Desktop_fnRelease (IShellFolder2 * iface)
167 {
168     IGenericSFImpl *This = (IGenericSFImpl *)iface;
169
170     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
171
172     if (!--(This->ref)) {
173         TRACE ("-- destroying IShellFolder(%p)\n", This);
174         if (This->pidlRoot)
175             SHFree (This->pidlRoot);
176         if (This->sPathTarget)
177             SHFree (This->sPathTarget);
178         LocalFree ((HLOCAL) This);
179         return 0;
180     }
181     return This->ref;
182 }
183
184 /**************************************************************************
185 *       ISF_Desktop_fnParseDisplayName
186 *
187 * NOTES
188 *       "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
189 *       to MyComputer
190 */
191 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName (IShellFolder2 * iface,
192                                                       HWND hwndOwner,
193                                                       LPBC pbc,
194                                                       LPOLESTR lpszDisplayName,
195                                                       DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
196 {
197     IGenericSFImpl *This = (IGenericSFImpl *)iface;
198
199     WCHAR szElement[MAX_PATH];
200     LPCWSTR szNext = NULL;
201     LPITEMIDLIST pidlTemp = NULL;
202     HRESULT hr = S_OK;
203     char szPath[MAX_PATH];
204     DWORD len;
205     CLSID clsid;
206
207     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
208            This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
209
210     if (!lpszDisplayName || !ppidl)
211         return E_INVALIDARG;
212
213     *ppidl = 0;
214
215     if (pchEaten)
216         *pchEaten = 0;          /* strange but like the original */
217
218     if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') {
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     } else if (PathGetDriveNumberW (lpszDisplayName) >= 0) {
224         /* it's a filesystem path with a drive. Let MyComputer parse it */
225         pidlTemp = _ILCreateMyComputer ();
226         szNext = lpszDisplayName;
227     } else if (PathIsUNCW(lpszDisplayName)) {
228         pidlTemp = _ILCreateNetwork();
229         szNext = lpszDisplayName;
230     } else {
231         /* it's a filesystem path on the desktop. Let a FSFolder parse it */
232
233         if (*lpszDisplayName) {
234             /* build a complete path to create a simple pidl */
235             lstrcpyA(szPath, This->sPathTarget);
236             PathAddBackslashA(szPath);
237             len = lstrlenA(szPath);
238             WideCharToMultiByte(CP_ACP, 0, lpszDisplayName, -1, szPath + len, MAX_PATH - len, NULL, NULL);
239             hr = _ILCreateFromPathA(szPath, &pidlTemp);
240         } else {
241             pidlTemp = _ILCreateMyComputer();
242         }
243
244         szNext = NULL;
245     }
246
247     if (SUCCEEDED(hr) && pidlTemp) {
248         if (szNext && *szNext) {
249             hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
250         } else {
251             if (pdwAttributes && *pdwAttributes) {
252                 hr = SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
253             }
254         }
255     }
256
257     *ppidl = pidlTemp;
258
259     TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
260
261     return hr;
262 }
263
264 /**************************************************************************
265  *  CreateDesktopEnumList()
266  */
267 static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags)
268 {
269     BOOL ret = TRUE;
270     char szPath[MAX_PATH];
271
272     TRACE("(%p)->(flags=0x%08lx) \n",list,dwFlags);
273
274     /*enumerate the root folders */
275     if(dwFlags & SHCONTF_FOLDERS)
276     {
277         HKEY hkey;
278
279         /*create the pidl for This item */
280         ret = AddToEnumList(list, _ILCreateMyComputer());
281
282         if (ret && !RegOpenKeyExA(HKEY_LOCAL_MACHINE,
283          "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\desktop\\NameSpace",
284          0, KEY_READ, &hkey))
285         {
286             char iid[50];
287             int i=0;
288             BOOL moreKeys = TRUE;
289
290             while (ret && moreKeys)
291             {
292                 DWORD size = sizeof (iid);
293                 LONG apiRet = RegEnumKeyExA(hkey, i, iid, &size, 0, NULL, NULL,
294                  NULL);
295
296                 if (ERROR_SUCCESS == apiRet)
297                 {
298                     ret = AddToEnumList(list, _ILCreateGuidFromStrA(iid));
299                     i++;
300                 }
301                 else if (ERROR_NO_MORE_ITEMS == apiRet)
302                     moreKeys = FALSE;
303                 else
304                     ret = FALSE;
305             }
306             RegCloseKey(hkey);
307         }
308     }
309
310     /*enumerate the elements in %windir%\desktop */
311     SHGetSpecialFolderPathA(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE);
312     ret = ret && CreateFolderEnumList(list, szPath, dwFlags);
313
314     return ret;
315 }
316
317 /**************************************************************************
318 *               ISF_Desktop_fnEnumObjects
319 */
320 static HRESULT WINAPI ISF_Desktop_fnEnumObjects (IShellFolder2 * iface,
321                                                  HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
322 {
323     IGenericSFImpl *This = (IGenericSFImpl *)iface;
324
325     TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
326
327     *ppEnumIDList = IEnumIDList_Constructor();
328     if (*ppEnumIDList)
329         CreateDesktopEnumList(*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_Desktop_fnBindToObject
338 */
339 static HRESULT WINAPI ISF_Desktop_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, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
345
346     return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut);
347 }
348
349 /**************************************************************************
350 *       ISF_Desktop_fnBindToStorage
351 */
352 static HRESULT WINAPI ISF_Desktop_fnBindToStorage (IShellFolder2 * iface,
353                                                    LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
354 {
355     IGenericSFImpl *This = (IGenericSFImpl *)iface;
356
357     FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
358
359     *ppvOut = NULL;
360     return E_NOTIMPL;
361 }
362
363 /**************************************************************************
364 *       ISF_Desktop_fnCompareIDs
365 */
366
367 static HRESULT WINAPI ISF_Desktop_fnCompareIDs (IShellFolder2 * iface,
368                                                 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
369 {
370     IGenericSFImpl *This = (IGenericSFImpl *)iface;
371
372     int nReturn;
373
374     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
375     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
376     TRACE ("-- %i\n", nReturn);
377     return nReturn;
378 }
379
380 /**************************************************************************
381 *       ISF_Desktop_fnCreateViewObject
382 */
383 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface,
384                                                       HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
385 {
386     IGenericSFImpl *This = (IGenericSFImpl *)iface;
387
388     LPSHELLVIEW pShellView;
389     HRESULT hr = E_INVALIDARG;
390
391     TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
392
393     if (ppvOut) {
394         *ppvOut = NULL;
395
396         if (IsEqualIID (riid, &IID_IDropTarget)) {
397             WARN ("IDropTarget not implemented\n");
398             hr = E_NOTIMPL;
399         } else if (IsEqualIID (riid, &IID_IContextMenu)) {
400             WARN ("IContextMenu not implemented\n");
401             hr = E_NOTIMPL;
402         } else if (IsEqualIID (riid, &IID_IShellView)) {
403             pShellView = IShellView_Constructor ((IShellFolder *) iface);
404             if (pShellView) {
405                 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
406                 IShellView_Release (pShellView);
407             }
408         }
409     }
410     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
411     return hr;
412 }
413
414 /**************************************************************************
415 *  ISF_Desktop_fnGetAttributesOf
416 */
417 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf (IShellFolder2 * iface,
418                                                      UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
419 {
420     IGenericSFImpl *This = (IGenericSFImpl *)iface;
421
422     HRESULT hr = S_OK;
423
424     TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
425
426     if ((!cidl) || (!apidl) || (!rgfInOut))
427         return E_INVALIDARG;
428
429     if (*rgfInOut == 0)
430         *rgfInOut = ~0;
431
432     while (cidl > 0 && *apidl) {
433         pdump (*apidl);
434         SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
435         apidl++;
436         cidl--;
437     }
438
439     TRACE ("-- result=0x%08lx\n", *rgfInOut);
440
441     return hr;
442 }
443
444 /**************************************************************************
445 *       ISF_Desktop_fnGetUIObjectOf
446 *
447 * PARAMETERS
448 *  HWND           hwndOwner, //[in ] Parent window for any output
449 *  UINT           cidl,      //[in ] array size
450 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
451 *  REFIID         riid,      //[in ] Requested Interface
452 *  UINT*          prgfInOut, //[   ] reserved
453 *  LPVOID*        ppvObject) //[out] Resulting Interface
454 *
455 */
456 static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface,
457                                                    HWND hwndOwner,
458                                                    UINT cidl,
459                                                    LPCITEMIDLIST * apidl,
460                                                    REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
461 {
462     IGenericSFImpl *This = (IGenericSFImpl *)iface;
463
464     LPITEMIDLIST pidl;
465     IUnknown *pObj = NULL;
466     HRESULT hr = E_INVALIDARG;
467
468     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
469            This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
470
471     if (ppvOut) {
472         *ppvOut = NULL;
473
474         if (IsEqualIID (riid, &IID_IContextMenu)) {
475             pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
476             hr = S_OK;
477         } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
478             pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
479             hr = S_OK;
480         } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
481             pidl = ILCombine (This->pidlRoot, apidl[0]);
482             pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
483             SHFree (pidl);
484             hr = S_OK;
485         } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) {
486             pidl = ILCombine (This->pidlRoot, apidl[0]);
487             pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
488             SHFree (pidl);
489             hr = S_OK;
490         } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
491             hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
492         } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA))
493                                 && (cidl == 1)) {
494             pidl = ILCombine (This->pidlRoot, apidl[0]);
495             hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
496             SHFree (pidl);
497         } else {
498             hr = E_NOINTERFACE;
499         }
500
501         if (SUCCEEDED(hr) && !pObj)
502             hr = E_OUTOFMEMORY;
503
504         *ppvOut = pObj;
505     }
506     TRACE ("(%p)->hr=0x%08lx\n", This, hr);
507     return hr;
508 }
509
510 /**************************************************************************
511 *       ISF_Desktop_fnGetDisplayNameOf
512 *
513 * NOTES
514 *       special case: pidl = null gives desktop-name back
515 */
516 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface,
517                                                       LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
518 {
519     IGenericSFImpl *This = (IGenericSFImpl *)iface;
520
521     CHAR szPath[MAX_PATH];
522     GUID const *clsid;
523     HRESULT hr = S_OK;
524
525     *szPath = '\0';
526
527     TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
528     pdump (pidl);
529
530     if (!strRet)
531         return E_INVALIDARG;
532
533     if (_ILIsDesktop (pidl)) {
534         if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)) {
535             lstrcpyA (szPath, This->sPathTarget);
536         } else {
537             HCR_GetClassNameA(&CLSID_ShellDesktop, szPath, MAX_PATH);
538         }
539     } else if (_ILIsPidlSimple (pidl)) {
540         if ((clsid = _ILGetGUIDPointer (pidl))) {
541             if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING) {
542                 int bWantsForParsing;
543
544                 /*
545                  * we can only get a filesystem path from a shellfolder if the value WantsFORPARSING in
546                  * CLSID\\{...}\\shellfolder exists
547                  * exception: the MyComputer folder has this keys not but like any filesystem backed
548                  *            folder it needs these behaviour
549                  */
550                 if (IsEqualIID (clsid, &CLSID_MyComputer)) {
551                     bWantsForParsing = 1;
552                 } else {
553                     /* get the "WantsFORPARSING" flag from the registry */
554                     char szRegPath[100];
555
556                     lstrcpyA (szRegPath, "CLSID\\");
557                     SHELL32_GUIDToStringA (clsid, &szRegPath[6]);
558                     lstrcatA (szRegPath, "\\shellfolder");
559                     bWantsForParsing =
560                         (ERROR_SUCCESS ==
561                          SHGetValueA (HKEY_CLASSES_ROOT, szRegPath, "WantsFORPARSING", NULL, NULL, NULL));
562                 }
563
564                 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) && bWantsForParsing) {
565                     /* we need the filesystem path to the destination folder. Only the folder itself can know it */
566                     hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH);
567                 } else {
568                     /* parsing name like ::{...} */
569                     lstrcpyA (szPath, "::");
570                     SHELL32_GUIDToStringA (clsid, &szPath[2]);
571                 }
572             } else {
573                 /* user friendly name */
574                 HCR_GetClassNameA (clsid, szPath, MAX_PATH);
575             }
576         } else {
577             /* file system folder */
578             _ILSimpleGetText (pidl, szPath, MAX_PATH);
579
580             if (!_ILIsFolder(pidl))
581                 SHELL_FS_ProcessDisplayFilename(szPath, dwFlags);
582         }
583     } else {
584         /* a complex pidl, let the subfolder do the work */
585         hr = SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags, szPath, MAX_PATH);
586     }
587
588     if (SUCCEEDED (hr)) {
589         strRet->uType = STRRET_CSTR;
590         lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
591     }
592
593     TRACE ("-- (%p)->(%s,0x%08lx)\n", This, szPath, hr);
594     return hr;
595 }
596
597 /**************************************************************************
598 *  ISF_Desktop_fnSetNameOf
599 *  Changes the name of a file object or subfolder, possibly changing its item
600 *  identifier in the process.
601 *
602 * PARAMETERS
603 *  HWND          hwndOwner,  //[in ] Owner window for output
604 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
605 *  LPCOLESTR     lpszName,   //[in ] the items new display name
606 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
607 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
608 */
609 static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,       /*simple pidl */
610                                                LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
611 {
612     IGenericSFImpl *This = (IGenericSFImpl *)iface;
613
614     FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
615
616     return E_FAIL;
617 }
618
619 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
620 {
621     IGenericSFImpl *This = (IGenericSFImpl *)iface;
622
623     FIXME ("(%p)\n", This);
624     return E_NOTIMPL;
625 }
626 static HRESULT WINAPI ISF_Desktop_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
627 {
628     IGenericSFImpl *This = (IGenericSFImpl *)iface;
629     FIXME ("(%p)\n", This);
630     return E_NOTIMPL;
631 }
632 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn (IShellFolder2 * iface,
633                                                       DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
634 {
635     IGenericSFImpl *This = (IGenericSFImpl *)iface;
636
637     TRACE ("(%p)\n", This);
638
639     if (pSort)
640         *pSort = 0;
641     if (pDisplay)
642         *pDisplay = 0;
643
644     return S_OK;
645 }
646 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
647 {
648     IGenericSFImpl *This = (IGenericSFImpl *)iface;
649
650     TRACE ("(%p)\n", This);
651
652     if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
653         return E_INVALIDARG;
654
655     *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
656
657     return S_OK;
658 }
659 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx (IShellFolder2 * iface,
660                                                   LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
661 {
662     IGenericSFImpl *This = (IGenericSFImpl *)iface;
663     FIXME ("(%p)\n", This);
664
665     return E_NOTIMPL;
666 }
667 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf (IShellFolder2 * iface,
668                                                   LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
669 {
670     IGenericSFImpl *This = (IGenericSFImpl *)iface;
671
672     HRESULT hr = E_FAIL;
673
674     TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
675
676     if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS)
677         return E_INVALIDARG;
678
679     if (!pidl) {
680         psd->fmt = DesktopSFHeader[iColumn].fmt;
681         psd->cxChar = DesktopSFHeader[iColumn].cxChar;
682         psd->str.uType = STRRET_CSTR;
683         LoadStringA (shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
684         return S_OK;
685     } else {
686         /* the data from the pidl */
687         switch (iColumn) {
688         case 0:         /* name */
689             hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
690             break;
691         case 1:         /* size */
692             _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
693             break;
694         case 2:         /* type */
695             _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
696             break;
697         case 3:         /* date */
698             _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
699             break;
700         case 4:         /* attributes */
701             _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
702             break;
703         }
704         hr = S_OK;
705         psd->str.uType = STRRET_CSTR;
706     }
707
708     return hr;
709 }
710 static HRESULT WINAPI ISF_Desktop_fnMapColumnToSCID (IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
711 {
712     IGenericSFImpl *This = (IGenericSFImpl *)iface;
713     FIXME ("(%p)\n", This);
714     return E_NOTIMPL;
715 }
716
717 static IShellFolder2Vtbl vt_MCFldr_ShellFolder2 =
718 {
719         ISF_Desktop_fnQueryInterface,
720         ISF_Desktop_fnAddRef,
721         ISF_Desktop_fnRelease,
722         ISF_Desktop_fnParseDisplayName,
723         ISF_Desktop_fnEnumObjects,
724         ISF_Desktop_fnBindToObject,
725         ISF_Desktop_fnBindToStorage,
726         ISF_Desktop_fnCompareIDs,
727         ISF_Desktop_fnCreateViewObject,
728         ISF_Desktop_fnGetAttributesOf,
729         ISF_Desktop_fnGetUIObjectOf,
730         ISF_Desktop_fnGetDisplayNameOf,
731         ISF_Desktop_fnSetNameOf,
732         /* ShellFolder2 */
733         ISF_Desktop_fnGetDefaultSearchGUID,
734         ISF_Desktop_fnEnumSearches,
735         ISF_Desktop_fnGetDefaultColumn,
736         ISF_Desktop_fnGetDefaultColumnState,
737         ISF_Desktop_fnGetDetailsEx,
738         ISF_Desktop_fnGetDetailsOf,
739         ISF_Desktop_fnMapColumnToSCID};