hidclass.sys: Remove old reports from WINE_HIDP_PREPARSED_DATA.
[wine.git] / dlls / shell32 / shfldr_mycomp.c
blob7f5aaeb13fc42f85ad10eb5fdebe67db80b4e25b
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 "config.h"
23 #include "wine/port.h"
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdio.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
33 #include "winerror.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
38 #include "wingdi.h"
39 #include "pidl.h"
40 #include "shlguid.h"
41 #include "undocshell.h"
42 #include "shell32_main.h"
43 #include "shresdef.h"
44 #include "shlwapi.h"
45 #include "wine/debug.h"
46 #include "debughlp.h"
47 #include "shfldr.h"
49 WINE_DEFAULT_DEBUG_CHANNEL (shell);
51 /***********************************************************************
52 * IShellFolder implementation
55 typedef struct {
56 IShellFolder2 IShellFolder2_iface;
57 IPersistFolder2 IPersistFolder2_iface;
58 LONG ref;
60 /* both paths are parsible from the desktop */
61 LPITEMIDLIST pidlRoot; /* absolute pidl */
62 } IMyComputerFolderImpl;
64 static const IShellFolder2Vtbl vt_ShellFolder2;
65 static const IPersistFolder2Vtbl vt_PersistFolder2;
67 static inline IMyComputerFolderImpl *impl_from_IShellFolder2(IShellFolder2 *iface)
69 return CONTAINING_RECORD(iface, IMyComputerFolderImpl, IShellFolder2_iface);
72 static inline IMyComputerFolderImpl *impl_from_IPersistFolder2(IPersistFolder2 *iface)
74 return CONTAINING_RECORD(iface, IMyComputerFolderImpl, IPersistFolder2_iface);
78 /***********************************************************************
79 * IShellFolder [MyComputer] implementation
82 static const shvheader mycomputer_header[] =
84 { &FMTID_Storage, PID_STG_NAME, IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
85 { &FMTID_Storage, PID_STG_STORAGETYPE, IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
86 { NULL, 0, IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
87 { NULL, 0, IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
90 /**************************************************************************
91 * ISF_MyComputer_Constructor
93 HRESULT WINAPI ISF_MyComputer_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
95 IMyComputerFolderImpl *sf;
97 TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
99 if (!ppv)
100 return E_POINTER;
101 if (pUnkOuter)
102 return CLASS_E_NOAGGREGATION;
104 sf = LocalAlloc (LMEM_ZEROINIT, sizeof (IMyComputerFolderImpl));
105 if (!sf)
106 return E_OUTOFMEMORY;
108 sf->ref = 0;
109 sf->IShellFolder2_iface.lpVtbl = &vt_ShellFolder2;
110 sf->IPersistFolder2_iface.lpVtbl = &vt_PersistFolder2;
111 sf->pidlRoot = _ILCreateMyComputer (); /* my qualified pidl */
113 if (FAILED (IShellFolder2_QueryInterface (&sf->IShellFolder2_iface, riid, ppv)))
115 IShellFolder2_Release (&sf->IShellFolder2_iface);
116 return E_NOINTERFACE;
119 TRACE ("--(%p)\n", sf);
120 return S_OK;
123 /**************************************************************************
124 * ISF_MyComputer_fnQueryInterface
126 * NOTES supports not IPersist/IPersistFolder
128 static HRESULT WINAPI ISF_MyComputer_fnQueryInterface (IShellFolder2 *iface,
129 REFIID riid, LPVOID *ppvObj)
131 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
133 TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
135 *ppvObj = NULL;
137 if (IsEqualIID (riid, &IID_IUnknown) ||
138 IsEqualIID (riid, &IID_IShellFolder) ||
139 IsEqualIID (riid, &IID_IShellFolder2))
141 *ppvObj = &This->IShellFolder2_iface;
143 else if (IsEqualIID (riid, &IID_IPersist) ||
144 IsEqualIID (riid, &IID_IPersistFolder) ||
145 IsEqualIID (riid, &IID_IPersistFolder2))
147 *ppvObj = &This->IPersistFolder2_iface;
150 if (*ppvObj)
152 IUnknown_AddRef ((IUnknown *) (*ppvObj));
153 TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
154 return S_OK;
156 TRACE ("-- Interface: E_NOINTERFACE\n");
157 return E_NOINTERFACE;
160 static ULONG WINAPI ISF_MyComputer_fnAddRef (IShellFolder2 * iface)
162 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
163 ULONG refCount = InterlockedIncrement(&This->ref);
165 TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
167 return refCount;
170 static ULONG WINAPI ISF_MyComputer_fnRelease (IShellFolder2 * iface)
172 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
173 ULONG refCount = InterlockedDecrement(&This->ref);
175 TRACE ("(%p)->(count=%u)\n", This, refCount + 1);
177 if (!refCount)
179 TRACE ("-- destroying IShellFolder(%p)\n", This);
180 SHFree (This->pidlRoot);
181 LocalFree (This);
183 return refCount;
186 /**************************************************************************
187 * ISF_MyComputer_fnParseDisplayName
189 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName (IShellFolder2 *iface,
190 HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
191 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
193 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
194 HRESULT hr = E_INVALIDARG;
195 LPCWSTR szNext = NULL;
196 WCHAR szElement[MAX_PATH];
197 LPITEMIDLIST pidlTemp = NULL;
198 CLSID clsid;
200 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", This,
201 hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
202 pchEaten, ppidl, pdwAttributes);
204 *ppidl = 0;
205 if (pchEaten)
206 *pchEaten = 0; /* strange but like the original */
208 /* handle CLSID paths */
209 if (lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':')
211 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
212 TRACE ("-- element: %s\n", debugstr_w (szElement));
213 SHCLSIDFromStringW (szElement + 2, &clsid);
214 pidlTemp = _ILCreateGuid (PT_GUID, &clsid);
216 /* do we have an absolute path name ? */
217 else if (PathGetDriveNumberW (lpszDisplayName) >= 0 &&
218 lpszDisplayName[2] == (WCHAR) '\\')
220 szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
221 /* make drive letter uppercase to enable PIDL comparison */
222 szElement[0] = toupper(szElement[0]);
223 pidlTemp = _ILCreateDrive (szElement);
226 if (szNext && *szNext)
228 hr = SHELL32_ParseNextElement (iface, hwndOwner, pbc, &pidlTemp,
229 (LPOLESTR) szNext, pchEaten, pdwAttributes);
231 else
233 if (pdwAttributes && *pdwAttributes)
234 SHELL32_GetItemAttributes (&This->IShellFolder2_iface, pidlTemp, pdwAttributes);
235 hr = S_OK;
238 *ppidl = pidlTemp;
240 TRACE ("(%p)->(-- ret=0x%08x)\n", This, hr);
242 return hr;
245 /* retrieve a map of drives that should be displayed */
246 static DWORD get_drive_map(void)
248 static const WCHAR policiesW[] = {'S','o','f','t','w','a','r','e','\\',
249 'M','i','c','r','o','s','o','f','t','\\',
250 'W','i','n','d','o','w','s','\\',
251 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
252 'P','o','l','i','c','i','e','s','\\',
253 'E','x','p','l','o','r','e','r',0};
254 static const WCHAR nodrivesW[] = {'N','o','D','r','i','v','e','s',0};
255 static DWORD drive_mask;
256 static BOOL init_done = FALSE;
258 if (!init_done)
260 DWORD type, size, data, mask = 0;
261 HKEY hkey;
263 if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, policiesW, &hkey ))
265 size = sizeof(data);
266 if (!RegQueryValueExW( hkey, nodrivesW, NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
267 mask |= data;
268 RegCloseKey( hkey );
270 if (!RegOpenKeyW( HKEY_CURRENT_USER, policiesW, &hkey ))
272 size = sizeof(data);
273 if (!RegQueryValueExW( hkey, nodrivesW, NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
274 mask |= data;
275 RegCloseKey( hkey );
277 drive_mask = mask;
278 init_done = TRUE;
281 return GetLogicalDrives() & ~drive_mask;
284 /**************************************************************************
285 * CreateMyCompEnumList()
287 static const WCHAR MyComputer_NameSpaceW[] = { 'S','O','F','T','W','A','R','E',
288 '\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
289 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l',
290 'o','r','e','r','\\','M','y','C','o','m','p','u','t','e','r','\\','N','a','m',
291 'e','s','p','a','c','e','\0' };
293 static BOOL CreateMyCompEnumList(IEnumIDListImpl *list, DWORD dwFlags)
295 BOOL ret = TRUE;
297 TRACE("(%p)->(flags=0x%08x)\n", list, dwFlags);
299 /* enumerate the folders */
300 if (dwFlags & SHCONTF_FOLDERS)
302 WCHAR wszDriveName[] = {'A', ':', '\\', '\0'};
303 DWORD dwDrivemap = get_drive_map();
304 HKEY hkey;
305 UINT i;
307 while (ret && wszDriveName[0]<='Z')
309 if(dwDrivemap & 0x00000001L)
310 ret = AddToEnumList(list, _ILCreateDrive(wszDriveName));
311 wszDriveName[0]++;
312 dwDrivemap = dwDrivemap >> 1;
315 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n",list);
316 for (i=0; i<2; i++) {
317 if (ret && !RegOpenKeyExW(i == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
318 MyComputer_NameSpaceW, 0, KEY_READ, &hkey))
320 WCHAR iid[50];
321 int i=0;
323 while (ret)
325 DWORD size;
326 LONG r;
328 size = ARRAY_SIZE(iid);
329 r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL);
330 if (ERROR_SUCCESS == r)
332 /* FIXME: shell extensions, shouldn't the type be
333 * PT_SHELLEXT? */
334 ret = AddToEnumList(list, _ILCreateGuidFromStrW(iid));
335 i++;
337 else if (ERROR_NO_MORE_ITEMS == r)
338 break;
339 else
340 ret = FALSE;
342 RegCloseKey(hkey);
346 return ret;
349 /**************************************************************************
350 * ISF_MyComputer_fnEnumObjects
352 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects (IShellFolder2 *iface,
353 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
355 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
356 IEnumIDListImpl *list;
358 TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", This,
359 hwndOwner, dwFlags, ppEnumIDList);
361 if (!(list = IEnumIDList_Constructor()))
362 return E_OUTOFMEMORY;
363 CreateMyCompEnumList(list, dwFlags);
364 *ppEnumIDList = &list->IEnumIDList_iface;
366 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
368 return S_OK;
371 /**************************************************************************
372 * ISF_MyComputer_fnBindToObject
374 static HRESULT WINAPI ISF_MyComputer_fnBindToObject (IShellFolder2 *iface,
375 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
377 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
379 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", This,
380 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
382 return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
385 /**************************************************************************
386 * ISF_MyComputer_fnBindToStorage
388 static HRESULT WINAPI ISF_MyComputer_fnBindToStorage (IShellFolder2 * iface,
389 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
391 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
393 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", This,
394 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
396 *ppvOut = NULL;
397 return E_NOTIMPL;
400 /**************************************************************************
401 * ISF_MyComputer_fnCompareIDs
404 static HRESULT WINAPI ISF_MyComputer_fnCompareIDs (IShellFolder2 *iface,
405 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
407 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
408 HRESULT hr;
410 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
411 hr = SHELL32_CompareIDs(&This->IShellFolder2_iface, lParam, pidl1, pidl2);
412 TRACE ("-- 0x%08x\n", hr);
413 return hr;
416 /**************************************************************************
417 * ISF_MyComputer_fnCreateViewObject
419 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject (IShellFolder2 *iface,
420 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
422 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
423 LPSHELLVIEW pShellView;
424 HRESULT hr = E_INVALIDARG;
426 TRACE("(%p)->(hwnd=%p,%s,%p)\n", This,
427 hwndOwner, shdebugstr_guid (riid), ppvOut);
429 if (!ppvOut)
430 return hr;
432 *ppvOut = NULL;
434 if (IsEqualIID (riid, &IID_IDropTarget))
436 WARN ("IDropTarget not implemented\n");
437 hr = E_NOTIMPL;
439 else if (IsEqualIID (riid, &IID_IContextMenu))
441 hr = BackgroundMenu_Constructor((IShellFolder*)iface, FALSE, riid, ppvOut);
443 else if (IsEqualIID (riid, &IID_IShellView))
445 pShellView = IShellView_Constructor ((IShellFolder *) iface);
446 if (pShellView)
448 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
449 IShellView_Release (pShellView);
452 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
453 return hr;
456 /**************************************************************************
457 * ISF_MyComputer_fnGetAttributesOf
459 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface,
460 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
462 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
463 HRESULT hr = S_OK;
465 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
466 This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
468 if (!rgfInOut)
469 return E_INVALIDARG;
470 if (cidl && !apidl)
471 return E_INVALIDARG;
473 if (*rgfInOut == 0)
474 *rgfInOut = ~0;
476 if(cidl == 0){
477 IShellFolder2 *parent = NULL;
478 LPCITEMIDLIST rpidl = NULL;
480 hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder2, (void **)&parent, &rpidl);
481 if(SUCCEEDED(hr)) {
482 SHELL32_GetItemAttributes(parent, rpidl, rgfInOut);
483 IShellFolder2_Release(parent);
485 } else {
486 while (cidl > 0 && *apidl) {
487 pdump (*apidl);
488 SHELL32_GetItemAttributes(&This->IShellFolder2_iface, *apidl, rgfInOut);
489 apidl++;
490 cidl--;
493 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
494 *rgfInOut &= ~SFGAO_VALIDATE;
496 TRACE ("-- result=0x%08x\n", *rgfInOut);
497 return hr;
500 /**************************************************************************
501 * ISF_MyComputer_fnGetUIObjectOf
503 * PARAMETERS
504 * hwndOwner [in] Parent window for any output
505 * cidl [in] array size
506 * apidl [in] simple pidl array
507 * riid [in] Requested Interface
508 * prgfInOut [ ] reserved
509 * ppvObject [out] Resulting Interface
512 static HRESULT WINAPI ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
513 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
514 UINT * prgfInOut, LPVOID * ppvOut)
516 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
518 LPITEMIDLIST pidl;
519 IUnknown *pObj = NULL;
520 HRESULT hr = E_INVALIDARG;
522 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", This,
523 hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
525 if (!ppvOut)
526 return hr;
528 *ppvOut = NULL;
530 if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
532 return ItemMenu_Constructor((IShellFolder*) iface, This->pidlRoot, apidl, cidl, riid, ppvOut);
534 else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
536 pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
537 This->pidlRoot, apidl, cidl);
538 hr = S_OK;
540 else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
542 pidl = ILCombine (This->pidlRoot, apidl[0]);
543 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
544 SHFree (pidl);
545 hr = S_OK;
547 else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
549 pidl = ILCombine (This->pidlRoot, apidl[0]);
550 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
551 SHFree (pidl);
552 hr = S_OK;
554 else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
556 hr = IShellFolder2_QueryInterface (iface, &IID_IDropTarget,
557 (LPVOID *) &pObj);
559 else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
560 IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1))
562 pidl = ILCombine (This->pidlRoot, apidl[0]);
563 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, &pObj);
564 SHFree (pidl);
566 else
567 hr = E_NOINTERFACE;
569 if (SUCCEEDED(hr) && !pObj)
570 hr = E_OUTOFMEMORY;
572 *ppvOut = pObj;
573 TRACE ("(%p)->hr=0x%08x\n", This, hr);
574 return hr;
577 /**************************************************************************
578 * ISF_MyComputer_fnGetDisplayNameOf
580 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf (IShellFolder2 *iface,
581 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
583 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
585 LPWSTR pszPath;
586 HRESULT hr = S_OK;
588 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet);
589 pdump (pidl);
591 if (!strRet)
592 return E_INVALIDARG;
594 pszPath = CoTaskMemAlloc((MAX_PATH +1) * sizeof(WCHAR));
595 if (!pszPath)
596 return E_OUTOFMEMORY;
598 pszPath[0] = 0;
600 if (!pidl->mkid.cb)
602 /* parsing name like ::{...} */
603 pszPath[0] = ':';
604 pszPath[1] = ':';
605 SHELL32_GUIDToStringW(&CLSID_MyComputer, &pszPath[2]);
607 else if (_ILIsPidlSimple(pidl))
609 /* take names of special folders only if its only this folder */
610 if (_ILIsSpecialFolder(pidl))
612 GUID const *clsid;
614 clsid = _ILGetGUIDPointer (pidl);
615 if (clsid)
617 if ((GET_SHGDN_FOR (dwFlags) & (SHGDN_FORPARSING | SHGDN_FORADDRESSBAR)) == SHGDN_FORPARSING)
619 static const WCHAR clsidW[] =
620 { 'C','L','S','I','D','\\',0 };
621 static const WCHAR shellfolderW[] =
622 { '\\','s','h','e','l','l','f','o','l','d','e','r',0 };
623 static const WCHAR wantsForParsingW[] =
624 { 'W','a','n','t','s','F','o','r','P','a','r','s','i','n',
625 'g',0 };
626 BOOL bWantsForParsing = FALSE;
627 WCHAR szRegPath[100];
628 LONG r;
631 * We can only get a filesystem path from a shellfolder
632 * if the value WantsFORPARSING exists in
633 * CLSID\\{...}\\shellfolder
634 * exception: the MyComputer folder has this keys not
635 * but like any filesystem backed
636 * folder it needs these behaviour
638 * Get the "WantsFORPARSING" flag from the registry
641 lstrcpyW (szRegPath, clsidW);
642 SHELL32_GUIDToStringW (clsid, &szRegPath[6]);
643 lstrcatW (szRegPath, shellfolderW);
644 r = SHGetValueW (HKEY_CLASSES_ROOT, szRegPath,
645 wantsForParsingW, NULL, NULL, NULL);
646 if (r == ERROR_SUCCESS)
647 bWantsForParsing = TRUE;
649 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
650 bWantsForParsing)
653 * We need the filesystem path to the destination folder
654 * Only the folder itself can know it
656 hr = SHELL32_GetDisplayNameOfChild (iface, pidl,
657 dwFlags, pszPath, MAX_PATH);
659 else
661 LPWSTR p = pszPath;
663 /* parsing name like ::{...} */
664 p[0] = ':';
665 p[1] = ':';
666 p += 2;
667 p += SHELL32_GUIDToStringW(&CLSID_MyComputer, p);
669 /* \:: */
670 p[0] = '\\';
671 p[1] = ':';
672 p[2] = ':';
673 p += 3;
674 SHELL32_GUIDToStringW(clsid, p);
677 else
679 /* user friendly name */
680 HCR_GetClassNameW (clsid, pszPath, MAX_PATH);
683 else
685 /* append my own path */
686 _ILSimpleGetTextW (pidl, pszPath, MAX_PATH);
689 else if (_ILIsDrive(pidl))
691 _ILSimpleGetTextW (pidl, pszPath, MAX_PATH); /* append my own path */
693 /* long view "lw_name (C:)" */
694 if (!(dwFlags & SHGDN_FORPARSING))
696 static const WCHAR wszOpenBracket[] = {' ','(',0};
697 static const WCHAR wszCloseBracket[] = {')',0};
698 WCHAR wszDrive[32 /* label */ + 6 /* ' (C:)'\0 */] = {0};
700 GetVolumeInformationW (pszPath, wszDrive, ARRAY_SIZE(wszDrive) - 5, NULL, NULL,
701 NULL, NULL, 0);
702 strcatW (wszDrive, wszOpenBracket);
703 lstrcpynW (wszDrive + strlenW(wszDrive), pszPath, 3);
704 strcatW (wszDrive, wszCloseBracket);
705 strcpyW (pszPath, wszDrive);
708 else
710 /* Neither a shell namespace extension nor a drive letter. */
711 ERR("Wrong pidl type\n");
712 CoTaskMemFree(pszPath);
713 return E_INVALIDARG;
716 else
718 /* Complex pidl. Let the child folder do the work */
719 hr = SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, pszPath, MAX_PATH);
722 if (SUCCEEDED (hr))
724 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
725 if (GetVersion() & 0x80000000)
727 strRet->uType = STRRET_CSTR;
728 if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->u.cStr, MAX_PATH,
729 NULL, NULL))
730 strRet->u.cStr[0] = '\0';
731 CoTaskMemFree(pszPath);
733 else
735 strRet->uType = STRRET_WSTR;
736 strRet->u.pOleStr = pszPath;
739 else
740 CoTaskMemFree(pszPath);
742 TRACE ("-- (%p)->(%s)\n", This, strRet->uType == STRRET_CSTR ? strRet->u.cStr : debugstr_w(strRet->u.pOleStr));
743 return hr;
746 /**************************************************************************
747 * ISF_MyComputer_fnSetNameOf
748 * Changes the name of a file object or subfolder, possibly changing its item
749 * identifier in the process.
751 * PARAMETERS
752 * hwndOwner [in] Owner window for output
753 * pidl [in] simple pidl of item to change
754 * lpszName [in] the items new display name
755 * dwFlags [in] SHGNO formatting flags
756 * ppidlOut [out] simple pidl returned
758 static HRESULT WINAPI ISF_MyComputer_fnSetNameOf (
759 IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,
760 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
762 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
763 FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This,
764 hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
765 return E_FAIL;
768 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(IShellFolder2 *iface, GUID *guid)
770 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
771 TRACE("(%p)->(%p)\n", This, guid);
772 return E_NOTIMPL;
774 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches (
775 IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
777 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
778 FIXME ("(%p)\n", This);
779 return E_NOTIMPL;
782 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(IShellFolder2 *iface, DWORD reserved,
783 ULONG *sort, ULONG *display)
785 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
787 TRACE("(%p)->(%#x, %p, %p)\n", This, reserved, sort, display);
789 return E_NOTIMPL;
792 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState (
793 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
795 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
797 TRACE ("(%p)->(%d %p)\n", This, iColumn, pcsFlags);
799 if (!pcsFlags || iColumn >= ARRAY_SIZE(mycomputer_header))
800 return E_INVALIDARG;
802 *pcsFlags = mycomputer_header[iColumn].pcsFlags;
804 return S_OK;
807 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx (IShellFolder2 * iface,
808 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
810 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
811 FIXME ("(%p)\n", This);
812 return E_NOTIMPL;
815 /* FIXME: drive size >4GB is rolling over */
816 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf (IShellFolder2 *iface,
817 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
819 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
820 char szPath[MAX_PATH];
821 ULARGE_INTEGER ulBytes;
822 HRESULT hr = S_OK;
824 TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
826 if (!psd || iColumn >= ARRAY_SIZE(mycomputer_header))
827 return E_INVALIDARG;
829 if (!pidl)
830 return SHELL32_GetColumnDetails(mycomputer_header, iColumn, psd);
832 psd->str.u.cStr[0] = 0;
833 psd->str.uType = STRRET_CSTR;
835 switch (iColumn)
837 case 0: /* name */
838 hr = IShellFolder2_GetDisplayNameOf (iface, pidl,
839 SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
840 break;
841 case 1: /* type */
842 _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
843 break;
844 case 2: /* total size */
845 if (_ILIsDrive (pidl))
847 _ILSimpleGetText (pidl, szPath, MAX_PATH);
848 GetDiskFreeSpaceExA (szPath, NULL, &ulBytes, NULL);
849 StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH);
851 break;
852 case 3: /* free size */
853 if (_ILIsDrive (pidl))
855 _ILSimpleGetText (pidl, szPath, MAX_PATH);
856 GetDiskFreeSpaceExA (szPath, &ulBytes, NULL, NULL);
857 StrFormatByteSizeA (ulBytes.u.LowPart, psd->str.u.cStr, MAX_PATH);
859 break;
862 return hr;
865 static HRESULT WINAPI ISF_MyComputer_fnMapColumnToSCID (IShellFolder2 *iface, UINT column, SHCOLUMNID *scid)
867 IMyComputerFolderImpl *This = impl_from_IShellFolder2(iface);
869 TRACE("(%p)->(%u %p)\n", This, column, scid);
871 if (column >= ARRAY_SIZE(mycomputer_header))
872 return E_INVALIDARG;
874 return shellfolder_map_column_to_scid(mycomputer_header, column, scid);
877 static const IShellFolder2Vtbl vt_ShellFolder2 =
879 ISF_MyComputer_fnQueryInterface,
880 ISF_MyComputer_fnAddRef,
881 ISF_MyComputer_fnRelease,
882 ISF_MyComputer_fnParseDisplayName,
883 ISF_MyComputer_fnEnumObjects,
884 ISF_MyComputer_fnBindToObject,
885 ISF_MyComputer_fnBindToStorage,
886 ISF_MyComputer_fnCompareIDs,
887 ISF_MyComputer_fnCreateViewObject,
888 ISF_MyComputer_fnGetAttributesOf,
889 ISF_MyComputer_fnGetUIObjectOf,
890 ISF_MyComputer_fnGetDisplayNameOf,
891 ISF_MyComputer_fnSetNameOf,
892 /* ShellFolder2 */
893 ISF_MyComputer_fnGetDefaultSearchGUID,
894 ISF_MyComputer_fnEnumSearches,
895 ISF_MyComputer_fnGetDefaultColumn,
896 ISF_MyComputer_fnGetDefaultColumnState,
897 ISF_MyComputer_fnGetDetailsEx,
898 ISF_MyComputer_fnGetDetailsOf,
899 ISF_MyComputer_fnMapColumnToSCID
902 /************************************************************************
903 * IMCFldr_PersistFolder2_QueryInterface
905 static HRESULT WINAPI IMCFldr_PersistFolder2_QueryInterface (
906 IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
908 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
909 TRACE ("(%p)\n", This);
910 return IShellFolder2_QueryInterface (&This->IShellFolder2_iface, iid, ppvObj);
913 /************************************************************************
914 * IMCFldr_PersistFolder2_AddRef
916 static ULONG WINAPI IMCFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
918 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
919 TRACE ("(%p)->(count=%u)\n", This, This->ref);
920 return IShellFolder2_AddRef (&This->IShellFolder2_iface);
923 /************************************************************************
924 * ISFPersistFolder_Release
926 static ULONG WINAPI IMCFldr_PersistFolder2_Release (IPersistFolder2 * iface)
928 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
929 TRACE ("(%p)->(count=%u)\n", This, This->ref);
930 return IShellFolder2_Release (&This->IShellFolder2_iface);
933 /************************************************************************
934 * IMCFldr_PersistFolder2_GetClassID
936 static HRESULT WINAPI IMCFldr_PersistFolder2_GetClassID (
937 IPersistFolder2 * iface, CLSID * lpClassId)
939 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
941 TRACE ("(%p)\n", This);
943 if (!lpClassId)
944 return E_POINTER;
945 *lpClassId = CLSID_MyComputer;
947 return S_OK;
950 /************************************************************************
951 * IMCFldr_PersistFolder2_Initialize
953 * NOTES: it makes no sense to change the pidl
955 static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize (
956 IPersistFolder2 * iface, LPCITEMIDLIST pidl)
958 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
959 TRACE ("(%p)->(%p)\n", This, pidl);
960 return E_NOTIMPL;
963 /**************************************************************************
964 * IPersistFolder2_fnGetCurFolder
966 static HRESULT WINAPI IMCFldr_PersistFolder2_GetCurFolder (
967 IPersistFolder2 * iface, LPITEMIDLIST * pidl)
969 IMyComputerFolderImpl *This = impl_from_IPersistFolder2(iface);
971 TRACE ("(%p)->(%p)\n", This, pidl);
973 if (!pidl)
974 return E_POINTER;
975 *pidl = ILClone (This->pidlRoot);
976 return S_OK;
979 static const IPersistFolder2Vtbl vt_PersistFolder2 =
981 IMCFldr_PersistFolder2_QueryInterface,
982 IMCFldr_PersistFolder2_AddRef,
983 IMCFldr_PersistFolder2_Release,
984 IMCFldr_PersistFolder2_GetClassID,
985 IMCFldr_PersistFolder2_Initialize,
986 IMCFldr_PersistFolder2_GetCurFolder