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