server: Send WM_WINE_SETCURSOR with the thread input cursor handle.
[wine.git] / dlls / shell32 / shfldr_mycomp.c
blob6d24a8e5c9ebec9ec5929072cf67430bc223452e
1 /*
2 * Virtual Workplace folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <stdio.h>
27 #define COBJMACROS
28 #include "winerror.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
33 #include "wingdi.h"
34 #include "pidl.h"
35 #include "shlguid.h"
36 #include "shell32_main.h"
37 #include "shresdef.h"
38 #include "shlwapi.h"
39 #include "wine/debug.h"
40 #include "debughlp.h"
41 #include "shfldr.h"
43 WINE_DEFAULT_DEBUG_CHANNEL (shell);
45 /***********************************************************************
46 * IShellFolder implementation
49 typedef struct {
50 IShellFolder2 IShellFolder2_iface;
51 IPersistFolder2 IPersistFolder2_iface;
52 LONG ref;
54 /* both paths are parsible from the desktop */
55 LPITEMIDLIST pidlRoot; /* absolute pidl */
56 } IMyComputerFolderImpl;
58 static const IShellFolder2Vtbl vt_ShellFolder2;
59 static const IPersistFolder2Vtbl vt_PersistFolder2;
61 static inline IMyComputerFolderImpl *impl_from_IShellFolder2(IShellFolder2 *iface)
63 return CONTAINING_RECORD(iface, IMyComputerFolderImpl, IShellFolder2_iface);
66 static inline IMyComputerFolderImpl *impl_from_IPersistFolder2(IPersistFolder2 *iface)
68 return CONTAINING_RECORD(iface, IMyComputerFolderImpl, IPersistFolder2_iface);
72 /***********************************************************************
73 * IShellFolder [MyComputer] implementation
76 static const shvheader mycomputer_header[] =
78 { &FMTID_Storage, PID_STG_NAME, IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
79 { &FMTID_Storage, PID_STG_STORAGETYPE, IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
80 { NULL, 0, IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
81 { NULL, 0, IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
84 /**************************************************************************
85 * ISF_MyComputer_Constructor
87 HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
89 IMyComputerFolderImpl *sf;
91 TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
93 if (!ppv)
94 return E_POINTER;
95 if (pUnkOuter)
96 return CLASS_E_NOAGGREGATION;
98 sf = LocalAlloc (LMEM_ZEROINIT, sizeof (IMyComputerFolderImpl));
99 if (!sf)
100 return E_OUTOFMEMORY;
102 sf->ref = 0;
103 sf->IShellFolder2_iface.lpVtbl = &vt_ShellFolder2;
104 sf->IPersistFolder2_iface.lpVtbl = &vt_PersistFolder2;
105 sf->pidlRoot = _ILCreateMyComputer (); /* my qualified pidl */
107 if (FAILED (IShellFolder2_QueryInterface (&sf->IShellFolder2_iface, riid, ppv)))
109 IShellFolder2_Release (&sf->IShellFolder2_iface);
110 return E_NOINTERFACE;
113 TRACE ("--(%p)\n", sf);
114 return S_OK;
117 /**************************************************************************
118 * ISF_MyComputer_fnQueryInterface
120 * NOTES supports not IPersist/IPersistFolder
122 static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 *iface,
123 REFIID riid, LPVOID *ppvObj)
125 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
127 TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
129 *ppvObj = NULL;
131 if (IsEqualIID (riid, &IID_IUnknown) ||
132 IsEqualIID (riid, &IID_IShellFolder) ||
133 IsEqualIID (riid, &IID_IShellFolder2))
135 *ppvObj = &This->IShellFolder2_iface;
137 else if (IsEqualIID (riid, &IID_IPersist) ||
138 IsEqualIID (riid, &IID_IPersistFolder) ||
139 IsEqualIID (riid, &IID_IPersistFolder2))
141 *ppvObj = &This->IPersistFolder2_iface;
144 if (*ppvObj)
146 IUnknown_AddRef ((IUnknown *) (*ppvObj));
147 TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
148 return S_OK;
150 TRACE ("-- Interface: E_NOINTERFACE\n");
151 return E_NOINTERFACE;
154 static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface)
156 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
157 ULONG refCount = InterlockedIncrement(&This->ref);
159 TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
161 return refCount;
164 static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface)
166 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
167 ULONG refCount = InterlockedDecrement(&This->ref);
169 TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
171 if (!refCount)
173 TRACE ("-- destroying IShellFolder(%p)\n", This);
174 SHFree (This->pidlRoot);
175 LocalFree (This);
177 return refCount;
180 /**************************************************************************
181 * ISF_MyComputer_fnParseDisplayName
183 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface,
184 HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
185 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
187 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
188 HRESULT hr = E_INVALIDARG;
189 LPCWSTR szNext = NULL;
190 WCHAR c, szElement[MAX_PATH];
191 LPITEMIDLIST pidlTemp = NULL;
192 CLSID clsid;
194 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", This,
195 hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
196 pchEaten, ppidl, pdwAttributes);
198 *ppidl = 0;
199 if (pchEaten)
200 *pchEaten = 0; /* strange but like the original */
202 /* handle CLSID paths */
203 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
205 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
206 TRACE ("-- element: %s\n", debugstr_w (szElement));
207 SHCLSIDFromStringW (szElement + 2, &clsid);
208 pidlTemp = _ILCreateGuid (PT_GUID, &clsid);
210 /* we can't use PathGetDriveNumberW because we can't have the \\?\ prefix */
211 else if ((c = towupper(lpszDisplayName[0])) >= 'A' && c <= 'Z' &&
212 lpszDisplayName[1] == ':' &&
213 (lpszDisplayName[2] == '\\' || lpszDisplayName[2] == '\0'))
215 /* drive letter has to be uppercase to enable PIDL comparison */
216 szElement[0] = c;
217 szElement[1] = ':';
218 szElement[2] = '\\';
219 szElement[3] = '\0';
220 szNext = &lpszDisplayName[2] + (lpszDisplayName[2] == '\\');
221 pidlTemp = _ILCreateDrive (szElement);
224 if (szNext && *szNext)
226 hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp,
227 (LPOLESTR) szNext, pchEaten, pdwAttributes);
229 else if (pidlTemp)
231 if (pdwAttributes && *pdwAttributes)
232 SHELL32_GetItemAttributes (&This->IShellFolder2_iface, pidlTemp, pdwAttributes);
233 hr = S_OK;
236 *ppidl = pidlTemp;
238 TRACE ("(%p)->(-- ret=0x%08lx)\n", This, hr);
240 return hr;
243 /* retrieve a map of drives that should be displayed */
244 static DWORD get_drive_map(void)
246 static DWORD drive_mask;
247 static BOOL init_done = FALSE;
249 if (!init_done)
251 DWORD type, size, data, mask = 0;
252 HKEY hkey;
254 if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", &hkey ))
256 size = sizeof(data);
257 if (!RegQueryValueExW( hkey, L"NoDrives", NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
258 mask |= data;
259 RegCloseKey( hkey );
261 if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", &hkey ))
263 size = sizeof(data);
264 if (!RegQueryValueExW( hkey, L"NoDrives", NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
265 mask |= data;
266 RegCloseKey( hkey );
268 drive_mask = mask;
269 init_done = TRUE;
272 return GetLogicalDrives() & ~drive_mask;
275 /**************************************************************************
276 * CreateMyCompEnumList()
278 static BOOL CreateMyCompEnumList(IEnumIDListImpl *list, DWORD dwFlags)
280 BOOL ret = TRUE;
282 TRACE("(%p)->(flags=0x%08lx)\n", list, dwFlags);
284 /* enumerate the folders */
285 if (dwFlags & SHCONTF_FOLDERS)
287 WCHAR wszDriveName[] = L"A:\\";
288 DWORD dwDrivemap = get_drive_map();
289 HKEY hkey;
290 UINT i;
292 while (ret && wszDriveName[0]<='Z')
294 if(dwDrivemap & 0x00000001L)
295 ret = AddToEnumList(list, _ILCreateDrive(wszDriveName));
296 wszDriveName[0]++;
297 dwDrivemap = dwDrivemap >> 1;
300 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",list);
301 for (i=0; i<2; i++) {
302 if (ret && !RegOpenKeyExW(i == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
303 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace",
304 0, KEY_READ, &hkey))
306 WCHAR iid[50];
307 int i=0;
309 while (ret)
311 DWORD size;
312 LONG r;
314 size = ARRAY_SIZE(iid);
315 r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL);
316 if (ERROR_SUCCESS == r)
318 /* FIXME: shell extensions, shouldn't the type be
319 * PT_SHELLEXT? */
320 ret = AddToEnumList(list, _ILCreateGuidFromStrW(iid));
321 i++;
323 else if (ERROR_NO_MORE_ITEMS == r)
324 break;
325 else
326 ret = FALSE;
328 RegCloseKey(hkey);
332 return ret;
335 /**************************************************************************
336 * ISF_MyComputer_fnEnumObjects
338 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects (IShellFolder2 *iface,
339 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
341 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
342 IEnumIDListImpl *list;
344 TRACE("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This,
345 hwndOwner, dwFlags, ppEnumIDList);
347 if (!(list = IEnumIDList_Constructor()))
348 return E_OUTOFMEMORY;
349 CreateMyCompEnumList(list, dwFlags);
350 *ppEnumIDList = &list->IEnumIDList_iface;
352 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
354 return S_OK;
357 /**************************************************************************
358 * ISF_MyComputer_fnBindToObject
360 static HRESULT WINAPI ISF_MyComputer_fnBindToObject (IShellFolder2 *iface,
361 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
363 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
365 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This,
366 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
368 return SHELL32_BindToChild (This->pidlRoot, &CLSID_ShellFSFolder, NULL, pidl, riid, ppvOut);
371 /**************************************************************************
372 * ISF_MyComputer_fnBindToStorage
374 static HRESULT WINAPI ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface,
375 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
377 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
379 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This,
380 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
382 *ppvOut = NULL;
383 return E_NOTIMPL;
386 /**************************************************************************
387 * ISF_MyComputer_fnCompareIDs
390 static HRESULT WINAPI ISF_MyComputer_fnCompareIDs (IShellFolder2 *iface,
391 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
393 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
394 HRESULT hr;
396 TRACE ("(%p)->(0x%08Ix,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
397 hr = SHELL32_CompareIDs(&This->IShellFolder2_iface, lParam, pidl1, pidl2);
398 TRACE ("-- 0x%08lx\n", hr);
399 return hr;
402 /**************************************************************************
403 * ISF_MyComputer_fnCreateViewObject
405 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject (IShellFolder2 *iface,
406 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
408 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
409 LPSHELLVIEW pShellView;
410 HRESULT hr = E_INVALIDARG;
412 TRACE("(%p)->(hwnd=%p,%s,%p)\n", This,
413 hwndOwner, shdebugstr_guid (riid), ppvOut);
415 if (!ppvOut)
416 return hr;
418 *ppvOut = NULL;
420 if (IsEqualIID (riid, &IID_IDropTarget))
422 WARN ("IDropTarget not implemented\n");
423 hr = E_NOTIMPL;
425 else if (IsEqualIID (riid, &IID_IContextMenu))
427 hr = BackgroundMenu_Constructor((IShellFolder*)iface, FALSE, riid, ppvOut);
429 else if (IsEqualIID (riid, &IID_IShellView))
431 pShellView = IShellView_Constructor ((IShellFolder *) iface);
432 if (pShellView)
434 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
435 IShellView_Release (pShellView);
438 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
439 return hr;
442 /**************************************************************************
443 * ISF_MyComputer_fnGetAttributesOf
445 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface,
446 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
448 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
449 HRESULT hr = S_OK;
451 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n",
452 This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
454 if (!rgfInOut)
455 return E_INVALIDARG;
456 if (cidl && !apidl)
457 return E_INVALIDARG;
459 if (*rgfInOut == 0)
460 *rgfInOut = ~0;
462 if(cidl == 0){
463 IShellFolder2 *parent = NULL;
464 LPCITEMIDLIST rpidl = NULL;
466 hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder2, (void **)&parent, &rpidl);
467 if(SUCCEEDED(hr)) {
468 SHELL32_GetItemAttributes(parent, rpidl, rgfInOut);
469 IShellFolder2_Release(parent);
471 } else {
472 while (cidl > 0 && *apidl) {
473 pdump (*apidl);
474 SHELL32_GetItemAttributes(&This->IShellFolder2_iface, *apidl, rgfInOut);
475 apidl++;
476 cidl--;
479 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
480 *rgfInOut &= ~SFGAO_VALIDATE;
482 TRACE ("-- result=0x%08lx\n", *rgfInOut);
483 return hr;
486 /**************************************************************************
487 * ISF_MyComputer_fnGetUIObjectOf
489 * PARAMETERS
490 * hwndOwner [in] Parent window for any output
491 * cidl [in] array size
492 * apidl [in] simple pidl array
493 * riid [in] Requested Interface
494 * prgfInOut [ ] reserved
495 * ppvObject [out] Resulting Interface
498 static HRESULT WINAPI ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
499 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
500 UINT * prgfInOut, LPVOID * ppvOut)
502 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
504 LPITEMIDLIST pidl;
505 IUnknown *pObj = NULL;
506 HRESULT hr = E_INVALIDARG;
508 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", This,
509 hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
511 if (!ppvOut)
512 return hr;
514 *ppvOut = NULL;
516 if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
518 return ItemMenu_Constructor((IShellFolder*) iface, This->pidlRoot, apidl, cidl, riid, ppvOut);
520 else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
522 pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
523 This->pidlRoot, apidl, cidl);
524 hr = S_OK;
526 else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
528 pidl = ILCombine (This->pidlRoot, apidl[0]);
529 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
530 ILFree(pidl);
531 hr = S_OK;
533 else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
535 pidl = ILCombine (This->pidlRoot, apidl[0]);
536 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
537 ILFree(pidl);
538 hr = S_OK;
540 else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
542 hr = IShellFolder2_QueryInterface (iface, &IID_IDropTarget,
543 (LPVOID *) &pObj);
545 else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
546 IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1))
548 pidl = ILCombine (This->pidlRoot, apidl[0]);
549 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, &pObj);
550 ILFree(pidl);
552 else
553 hr = E_NOINTERFACE;
555 if (SUCCEEDED(hr) && !pObj)
556 hr = E_OUTOFMEMORY;
558 *ppvOut = pObj;
559 TRACE ("(%p)->hr=0x%08lx\n", This, hr);
560 return hr;
563 /**************************************************************************
564 * ISF_MyComputer_fnGetDisplayNameOf
566 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 *iface,
567 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
569 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
571 LPWSTR pszPath;
572 HRESULT hr = S_OK;
574 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
575 pdump (pidl);
577 if (!strRet)
578 return E_INVALIDARG;
580 pszPath = CoTaskMemAlloc((MAX_PATH +1) * sizeof(WCHAR));
581 if (!pszPath)
582 return E_OUTOFMEMORY;
584 pszPath[0] = 0;
586 if (!pidl->mkid.cb)
588 /* parsing name like ::{...} */
589 pszPath[0] = ':';
590 pszPath[1] = ':';
591 SHELL32_GUIDToStringW(&CLSID_MyComputer, &pszPath[2]);
593 else if (_ILIsPidlSimple(pidl))
595 /* take names of special folders only if its only this folder */
596 if (_ILIsSpecialFolder(pidl))
598 GUID const *clsid;
600 clsid = _ILGetGUIDPointer (pidl);
601 if (clsid)
603 if ((GET_SHGDN_FOR (dwFlags) & (SHGDN_FORPARSING | SHGDN_FORADDRESSBAR)) == SHGDN_FORPARSING)
605 BOOL bWantsForParsing = FALSE;
606 WCHAR szRegPath[100];
607 LONG r;
610 * We can only get a filesystem path from a shellfolder
611 * if the value WantsFORPARSING exists in
612 * CLSID\\{...}\\shellfolder
613 * exception: the MyComputer folder has this keys not
614 * but like any filesystem backed
615 * folder it needs these behaviour
617 * Get the "WantsFORPARSING" flag from the registry
620 lstrcpyW (szRegPath, L"CLSID\\");
621 SHELL32_GUIDToStringW (clsid, &szRegPath[6]);
622 lstrcatW (szRegPath, L"\\shellfolder");
623 r = SHGetValueW (HKEY_CLASSES_ROOT, szRegPath, L"WantsForParsing", NULL, NULL, NULL);
624 if (r == ERROR_SUCCESS)
625 bWantsForParsing = TRUE;
627 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
628 bWantsForParsing)
631 * We need the filesystem path to the destination folder
632 * Only the folder itself can know it
634 hr = SHELL32_GetDisplayNameOfChild (iface, pidl,
635 dwFlags, pszPath, MAX_PATH);
637 else
639 LPWSTR p = pszPath;
641 /* parsing name like ::{...} */
642 p[0] = ':';
643 p[1] = ':';
644 p += 2;
645 p += SHELL32_GUIDToStringW(&CLSID_MyComputer, p);
647 /* \:: */
648 p[0] = '\\';
649 p[1] = ':';
650 p[2] = ':';
651 p += 3;
652 SHELL32_GUIDToStringW(clsid, p);
655 else
657 /* user friendly name */
658 HCR_GetClassNameW (clsid, pszPath, MAX_PATH);
661 else
663 /* append my own path */
664 _ILSimpleGetTextW (pidl, pszPath, MAX_PATH);
667 else if (_ILIsDrive(pidl))
669 _ILSimpleGetTextW (pidl, pszPath, MAX_PATH); /* append my own path */
671 /* long view "lw_name (C:)" */
672 if (!(dwFlags & SHGDN_FORPARSING))
674 WCHAR wszDrive[32 /* label */ + 6 /* ' (C:)'\0 */] = {0};
676 GetVolumeInformationW (pszPath, wszDrive, ARRAY_SIZE(wszDrive) - 5, NULL, NULL,
677 NULL, NULL, 0);
678 lstrcatW (wszDrive, L" (");
679 lstrcpynW (wszDrive + lstrlenW(wszDrive), pszPath, 3);
680 lstrcatW (wszDrive, L")");
681 lstrcpyW (pszPath, wszDrive);
684 else
686 /* Neither a shell namespace extension nor a drive letter. */
687 ERR("Wrong pidl type\n");
688 CoTaskMemFree(pszPath);
689 return E_INVALIDARG;
692 else
694 /* Complex pidl. Let the child folder do the work */
695 hr = SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, pszPath, MAX_PATH);
698 if (SUCCEEDED (hr))
700 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
701 if (GetVersion() & 0x80000000)
703 strRet->uType = STRRET_CSTR;
704 if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->cStr, MAX_PATH,
705 NULL, NULL))
706 strRet->cStr[0] = '\0';
707 CoTaskMemFree(pszPath);
709 else
711 strRet->uType = STRRET_WSTR;
712 strRet->pOleStr = pszPath;
715 else
716 CoTaskMemFree(pszPath);
718 TRACE ("-- (%p)->(%s)\n", This, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
719 return hr;
722 /**************************************************************************
723 * ISF_MyComputer_fnSetNameOf
724 * Changes the name of a file object or subfolder, possibly changing its item
725 * identifier in the process.
727 * PARAMETERS
728 * hwndOwner [in] Owner window for output
729 * pidl [in] simple pidl of item to change
730 * lpszName [in] the items new display name
731 * dwFlags [in] SHGNO formatting flags
732 * ppidlOut [out] simple pidl returned
734 static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (
735 IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,
736 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
738 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
739 FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This,
740 hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
741 return E_FAIL;
744 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(IShellFolder2 *iface, GUID *guid)
746 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
747 TRACE("(%p)->(%p)\n", This, guid);
748 return E_NOTIMPL;
750 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (
751 IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
753 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
754 FIXME ("(%p)\n", This);
755 return E_NOTIMPL;
758 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(IShellFolder2 *iface, DWORD reserved,
759 ULONG *sort, ULONG *display)
761 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
763 TRACE("(%p)->(%#lx, %p, %p)\n", This, reserved, sort, display);
765 return E_NOTIMPL;
768 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (
769 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
771 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
773 TRACE ("(%p)->(%d %p)\n", This, iColumn, pcsFlags);
775 if (!pcsFlags || iColumn >= ARRAY_SIZE(mycomputer_header))
776 return E_INVALIDARG;
778 *pcsFlags = mycomputer_header[iColumn].pcsFlags;
780 return S_OK;
783 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface,
784 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
786 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
787 FIXME ("(%p)\n", This);
788 return E_NOTIMPL;
791 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 *iface,
792 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
794 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
795 WCHAR path[MAX_PATH];
796 ULARGE_INTEGER bytes;
797 HRESULT hr = S_OK;
799 TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
801 if (!psd || iColumn >= ARRAY_SIZE(mycomputer_header))
802 return E_INVALIDARG;
804 if (!pidl)
805 return SHELL32_GetColumnDetails(mycomputer_header, iColumn, psd);
807 psd->str.cStr[0] = 0;
808 psd->str.uType = STRRET_CSTR;
810 switch (iColumn)
812 case 2: /* total size */
813 if (!_ILIsDrive (pidl))
814 break;
816 _ILSimpleGetTextW(pidl, path, MAX_PATH);
817 if (!GetDiskFreeSpaceExW(path, NULL, &bytes, NULL))
818 break;
820 psd->str.uType = STRRET_WSTR;
821 psd->str.pOleStr = CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
822 StrFormatByteSizeW(bytes.QuadPart, psd->str.pOleStr, MAX_PATH);
823 break;
824 case 3: /* free size */
825 if (!_ILIsDrive (pidl))
826 break;
828 _ILSimpleGetTextW(pidl, path, MAX_PATH);
829 if (!GetDiskFreeSpaceExW(path, &bytes, NULL, NULL))
830 break;
832 psd->str.uType = STRRET_WSTR;
833 psd->str.pOleStr = CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
834 StrFormatByteSizeW(bytes.QuadPart, psd->str.pOleStr, MAX_PATH);
835 break;
836 default:
837 return shellfolder_get_file_details( iface, pidl, mycomputer_header, iColumn, psd );
840 return hr;
843 static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (IShellFolder2 *iface, UINT column, SHCOLUMNID *scid)
845 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
847 TRACE("(%p)->(%u %p)\n", This, column, scid);
849 if (column >= ARRAY_SIZE(mycomputer_header))
850 return E_INVALIDARG;
852 return shellfolder_map_column_to_scid(mycomputer_header, column, scid);
855 static const IShellFolder2Vtbl vt_ShellFolder2 =
857 ISF_MyComputer_fnQueryInterface,
858 ISF_MyComputer_fnAddRef,
859 ISF_MyComputer_fnRelease,
860 ISF_MyComputer_fnParseDisplayName,
861 ISF_MyComputer_fnEnumObjects,
862 ISF_MyComputer_fnBindToObject,
863 ISF_MyComputer_fnBindToStorage,
864 ISF_MyComputer_fnCompareIDs,
865 ISF_MyComputer_fnCreateViewObject,
866 ISF_MyComputer_fnGetAttributesOf,
867 ISF_MyComputer_fnGetUIObjectOf,
868 ISF_MyComputer_fnGetDisplayNameOf,
869 ISF_MyComputer_fnSetNameOf,
870 /* ShellFolder2 */
871 ISF_MyComputer_fnGetDefaultSearchGUID,
872 ISF_MyComputer_fnEnumSearches,
873 ISF_MyComputer_fnGetDefaultColumn,
874 ISF_MyComputer_fnGetDefaultColumnState,
875 ISF_MyComputer_fnGetDetailsEx,
876 ISF_MyComputer_fnGetDetailsOf,
877 ISF_MyComputer_fnMapColumnToSCID
880 /************************************************************************
881 * IMCFldr_PersistFolder2_QueryInterface
883 static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (
884 IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
886 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
887 TRACE ("(%p)\n", This);
888 return IShellFolder2_QueryInterface (&This->IShellFolder2_iface, iid, ppvObj);
891 /************************************************************************
892 * IMCFldr_PersistFolder2_AddRef
894 static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
896 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
897 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
898 return IShellFolder2_AddRef (&This->IShellFolder2_iface);
901 /************************************************************************
902 * ISFPersistFolder_Release
904 static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface)
906 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
907 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
908 return IShellFolder2_Release (&This->IShellFolder2_iface);
911 /************************************************************************
912 * IMCFldr_PersistFolder2_GetClassID
914 static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (
915 IPersistFolder2 * iface, CLSID * lpClassId)
917 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
919 TRACE ("(%p)\n", This);
921 if (!lpClassId)
922 return E_POINTER;
923 *lpClassId = CLSID_MyComputer;
925 return S_OK;
928 /************************************************************************
929 * IMCFldr_PersistFolder2_Initialize
931 * NOTES: it makes no sense to change the pidl
933 static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (
934 IPersistFolder2 * iface, LPCITEMIDLIST pidl)
936 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
937 TRACE ("(%p)->(%p)\n", This, pidl);
938 return E_NOTIMPL;
941 /**************************************************************************
942 * IPersistFolder2_fnGetCurFolder
944 static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (
945 IPersistFolder2 * iface, LPITEMIDLIST * pidl)
947 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
949 TRACE ("(%p)->(%p)\n", This, pidl);
951 if (!pidl)
952 return E_POINTER;
953 *pidl = ILClone (This->pidlRoot);
954 return S_OK;
957 static const IPersistFolder2Vtbl vt_PersistFolder2 =
959 IMCFldr_PersistFolder2_QueryInterface,
960 IMCFldr_PersistFolder2_AddRef,
961 IMCFldr_PersistFolder2_Release,
962 IMCFldr_PersistFolder2_GetClassID,
963 IMCFldr_PersistFolder2_Initialize,
964 IMCFldr_PersistFolder2_GetCurFolder