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