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