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