2 * Virtual Workplace folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2009 Andrew Hill
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 WINE_DEFAULT_DEBUG_CHANNEL (shell
);
28 CDrivesFolder should create a CRegFolder to represent the virtual items that exist only in
29 the registry. The CRegFolder is aggregated by the CDrivesFolder.
30 The CDrivesFolderEnum class should enumerate only drives on the system. Since the CRegFolder
31 implementation of IShellFolder::EnumObjects enumerates the virtual items, the
32 CDrivesFolderEnum is only responsible for returning the physical items.
34 2. At least on my XP system, the drive pidls returned are of type PT_DRIVE1, not PT_DRIVE
35 3. The parsing name returned for my computer is incorrect. It should be "My Computer"
38 static int iDriveIconIds
[7] = { IDI_SHELL_DRIVE
, /* DRIVE_UNKNOWN */
39 IDI_SHELL_CDROM
, /* DRIVE_NO_ROOT_DIR*/
40 IDI_SHELL_3_14_FLOPPY
, /* DRIVE_REMOVABLE*/
41 IDI_SHELL_DRIVE
, /* DRIVE_FIXED*/
42 IDI_SHELL_NETDRIVE
, /* DRIVE_REMOTE*/
43 IDI_SHELL_CDROM
, /* DRIVE_CDROM*/
44 IDI_SHELL_RAMDISK
/* DRIVE_RAMDISK*/
47 static int iDriveTypeIds
[7] = { IDS_DRIVE_FIXED
, /* DRIVE_UNKNOWN */
48 IDS_DRIVE_FIXED
, /* DRIVE_NO_ROOT_DIR*/
49 IDS_DRIVE_FLOPPY
, /* DRIVE_REMOVABLE*/
50 IDS_DRIVE_FIXED
, /* DRIVE_FIXED*/
51 IDS_DRIVE_NETWORK
, /* DRIVE_REMOTE*/
52 IDS_DRIVE_CDROM
, /* DRIVE_CDROM*/
53 IDS_DRIVE_FIXED
/* DRIVE_RAMDISK*/
56 /***********************************************************************
57 * IShellFolder implementation
60 HRESULT CALLBACK
DrivesContextMenuCallback(IShellFolder
*psf
,
67 if (uMsg
!= DFM_MERGECONTEXTMENU
&& uMsg
!= DFM_INVOKECOMMAND
)
70 PIDLIST_ABSOLUTE pidlFolder
;
71 PUITEMID_CHILD
*apidl
;
73 HRESULT hr
= SH_GetApidlFromDataObject(pdtobj
, &pidlFolder
, &apidl
, &cidl
);
74 if (FAILED_UNEXPECTEDLY(hr
))
77 char szDrive
[8] = {0};
78 if (!_ILGetDrive(apidl
[0], szDrive
, sizeof(szDrive
)))
80 ERR("pidl is not a drive\n");
82 _ILFreeaPidl(apidl
, cidl
);
86 if (uMsg
== DFM_MERGECONTEXTMENU
)
88 QCMINFO
*pqcminfo
= (QCMINFO
*)lParam
;
91 if (GetVolumeInformationA(szDrive
, NULL
, 0, NULL
, NULL
, &dwFlags
, NULL
, 0))
93 /* Disable format if read only */
94 if (!(dwFlags
& FILE_READ_ONLY_VOLUME
) && GetDriveTypeA(szDrive
) != DRIVE_REMOTE
)
96 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
97 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, pqcminfo
->idCmdFirst
++, MFT_STRING
, MAKEINTRESOURCEW(IDS_FORMATDRIVE
), MFS_ENABLED
);
101 else if (uMsg
== DFM_INVOKECOMMAND
)
103 if (wParam
== DFM_CMD_PROPERTIES
)
106 wcscpy(wszBuf
, L
"A:\\");
107 wszBuf
[0] = (WCHAR
)szDrive
[0];
108 if (!SH_ShowDriveProperties(wszBuf
, pidlFolder
, apidl
))
113 SHFormatDrive(hwnd
, szDrive
[0] - 'A', SHFMT_ID_DEFAULT
, 0);
118 _ILFreeaPidl(apidl
, cidl
);
123 HRESULT
CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder
,
126 PCUITEMID_CHILD_ARRAY apidl
,
132 AddClassKeyToArray(L
"Drive", hKeys
, &cKeys
);
133 AddClassKeyToArray(L
"Folder", hKeys
, &cKeys
);
135 return CDefFolderMenu_Create2(pidlFolder
, hwnd
, cidl
, apidl
, psf
, DrivesContextMenuCallback
, cKeys
, hKeys
, ppcm
);
138 HRESULT
CDrivesExtractIcon_CreateInstance(IShellFolder
* psf
, LPCITEMIDLIST pidl
, REFIID riid
, LPVOID
* ppvOut
)
140 CComPtr
<IDefaultExtractIconInit
> initIcon
;
141 HRESULT hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
, &initIcon
));
142 if (FAILED_UNEXPECTEDLY(hr
))
145 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
146 UINT DriveType
= GetDriveTypeA(pszDrive
);
147 if (DriveType
> DRIVE_RAMDISK
)
148 DriveType
= DRIVE_FIXED
;
150 WCHAR wTemp
[MAX_PATH
];
152 if ((DriveType
== DRIVE_FIXED
|| DriveType
== DRIVE_UNKNOWN
) &&
153 (HCR_GetIconW(L
"Drive", wTemp
, NULL
, MAX_PATH
, &icon_idx
)))
155 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
159 icon_idx
= iDriveIconIds
[DriveType
];
160 initIcon
->SetNormalIcon(swShell32Name
, -icon_idx
);
163 return initIcon
->QueryInterface(riid
, ppvOut
);
166 class CDrivesFolderEnum
:
167 public CEnumIDListBase
171 ~CDrivesFolderEnum();
172 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
);
173 BOOL
CreateMyCompEnumList(DWORD dwFlags
);
175 BEGIN_COM_MAP(CDrivesFolderEnum
)
176 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
180 /***********************************************************************
181 * IShellFolder [MyComputer] implementation
184 static const shvheader MyComputerSFHeader
[] = {
185 {IDS_SHV_COLUMN_NAME
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
186 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
, LVCFMT_LEFT
, 10},
187 {IDS_SHV_COLUMN_TYPE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
188 {IDS_SHV_COLUMN_DISK_CAPACITY
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
189 {IDS_SHV_COLUMN_DISK_AVAILABLE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
192 #define MYCOMPUTERSHELLVIEWCOLUMNS 5
194 static const DWORD dwComputerAttributes
=
195 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
196 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
197 static const DWORD dwControlPanelAttributes
=
198 SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
| SFGAO_CANLINK
;
199 static const DWORD dwDriveAttributes
=
200 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
201 SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANRENAME
| SFGAO_CANLINK
;
203 CDrivesFolderEnum::CDrivesFolderEnum()
207 CDrivesFolderEnum::~CDrivesFolderEnum()
211 HRESULT WINAPI
CDrivesFolderEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
213 if (CreateMyCompEnumList(dwFlags
) == FALSE
)
219 /**************************************************************************
220 * CDrivesFolderEnum::CreateMyCompEnumList()
223 BOOL
CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags
)
226 static const WCHAR MyComputer_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
228 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
230 /* enumerate the folders */
231 if (dwFlags
& SHCONTF_FOLDERS
)
233 WCHAR wszDriveName
[] = {'A', ':', '\\', '\0'};
234 DWORD dwDrivemap
= GetLogicalDrives();
238 while (bRet
&& wszDriveName
[0] <= 'Z')
240 if(dwDrivemap
& 0x00000001L
)
241 bRet
= AddToEnumList(_ILCreateDrive(wszDriveName
));
243 dwDrivemap
= dwDrivemap
>> 1;
246 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
247 for (i
= 0; i
< 2; i
++)
249 if (bRet
&& ERROR_SUCCESS
== RegOpenKeyExW(i
== 0 ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
250 MyComputer_NameSpaceW
, 0, KEY_READ
, &hKey
))
259 dwSize
= sizeof(wszBuf
) / sizeof(wszBuf
[0]);
260 ErrorCode
= RegEnumKeyExW(hKey
, j
, wszBuf
, &dwSize
, 0, NULL
, NULL
, NULL
);
261 if (ERROR_SUCCESS
== ErrorCode
)
263 if (wszBuf
[0] != L
'{')
265 dwSize
= sizeof(wszBuf
);
266 RegGetValueW(hKey
, wszBuf
, NULL
, RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
);
269 /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
270 pidl
= _ILCreateGuidFromStrW(wszBuf
);
272 bRet
= AddToEnumList(pidl
);
274 ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf
);
277 else if (ERROR_NO_MORE_ITEMS
== ErrorCode
)
289 CDrivesFolder::CDrivesFolder()
294 CDrivesFolder::~CDrivesFolder()
296 TRACE ("-- destroying IShellFolder(%p)\n", this);
300 HRESULT WINAPI
CDrivesFolder::FinalConstruct()
302 pidlRoot
= _ILCreateMyComputer(); /* my qualified pidl */
303 if (pidlRoot
== NULL
)
304 return E_OUTOFMEMORY
;
306 HRESULT hr
= CRegFolder_CreateInstance(&CLSID_MyComputer
,
308 L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
309 IID_PPV_ARG(IShellFolder2
, &m_regFolder
));
314 /**************************************************************************
315 * CDrivesFolder::ParseDisplayName
317 HRESULT WINAPI
CDrivesFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
318 DWORD
* pchEaten
, PIDLIST_RELATIVE
* ppidl
, DWORD
* pdwAttributes
)
320 HRESULT hr
= E_INVALIDARG
;
321 LPCWSTR szNext
= NULL
;
322 LPITEMIDLIST pidlTemp
= NULL
;
324 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
325 hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
326 pchEaten
, ppidl
, pdwAttributes
);
330 *pchEaten
= 0; /* strange but like the original */
332 /* handle CLSID paths */
333 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
334 return m_regFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
336 if (PathGetDriveNumberW(lpszDisplayName
) < 0)
339 pidlTemp
= _ILCreateDrive(lpszDisplayName
);
341 return E_OUTOFMEMORY
;
343 if (lpszDisplayName
[2] == L
'\\')
345 szNext
= &lpszDisplayName
[3];
348 if (szNext
&& *szNext
)
350 hr
= SHELL32_ParseNextElement (this, hwndOwner
, pbc
, &pidlTemp
,
351 (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
356 if (pdwAttributes
&& *pdwAttributes
)
358 if (_ILIsDrive(pidlTemp
))
359 *pdwAttributes
&= dwDriveAttributes
;
360 else if (_ILIsSpecialFolder(pidlTemp
))
361 m_regFolder
->GetAttributesOf(1, &pidlTemp
, pdwAttributes
);
363 ERR("Got an unkown pidl here!\n");
369 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
374 /**************************************************************************
375 * CDrivesFolder::EnumObjects
377 HRESULT WINAPI
CDrivesFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
379 return ShellObjectCreatorInit
<CDrivesFolderEnum
>(hwndOwner
, dwFlags
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
382 /**************************************************************************
383 * CDrivesFolder::BindToObject
385 HRESULT WINAPI
CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
387 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
388 pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
390 if (_ILIsSpecialFolder(pidl
))
391 return m_regFolder
->BindToObject(pidl
, pbcReserved
, riid
, ppvOut
);
393 LPITEMIDLIST pidlChild
= ILCloneFirst (pidl
);
395 return E_OUTOFMEMORY
;
397 CComPtr
<IShellFolder
> psf
;
398 HRESULT hr
= SHELL32_CoCreateInitSF(pidlRoot
,
401 &CLSID_ShellFSFolder
,
403 IID_PPV_ARG(IShellFolder
, &psf
));
410 if (_ILIsPidlSimple (pidl
))
412 return psf
->QueryInterface(riid
, ppvOut
);
416 return psf
->BindToObject(ILGetNext (pidl
), pbcReserved
, riid
, ppvOut
);
420 /**************************************************************************
421 * CDrivesFolder::BindToStorage
423 HRESULT WINAPI
CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
425 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
426 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
432 /**************************************************************************
433 * CDrivesFolder::CompareIDs
436 HRESULT WINAPI
CDrivesFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
440 if (!pidl1
|| !pidl2
)
442 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
446 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
447 return m_regFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
449 if (!_ILIsDrive(pidl1
) || !_ILIsDrive(pidl2
) || LOWORD(lParam
) >= MYCOMPUTERSHELLVIEWCOLUMNS
)
452 CHAR
* pszDrive1
= _ILGetDataPointer(pidl1
)->u
.drive
.szDriveName
;
453 CHAR
* pszDrive2
= _ILGetDataPointer(pidl2
)->u
.drive
.szDriveName
;
456 switch(LOWORD(lParam
))
460 result
= stricmp(pszDrive1
, pszDrive2
);
461 hres
= MAKE_COMPARE_HRESULT(result
);
464 case 1: /* comments */
465 hres
= MAKE_COMPARE_HRESULT(0);
469 /* We want to return immediately because SHELL32_CompareDetails also compares children. */
470 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
473 case 4: /* Size Available */
475 ULARGE_INTEGER Drive1Available
, Drive1Total
, Drive2Available
, Drive2Total
;
477 if (GetVolumeInformationA(pszDrive1
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
478 GetDiskFreeSpaceExA(pszDrive1
, &Drive1Available
, &Drive1Total
, NULL
);
480 Drive1Available
.QuadPart
= Drive1Total
.QuadPart
= 0;
482 if (GetVolumeInformationA(pszDrive2
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
483 GetDiskFreeSpaceExA(pszDrive2
, &Drive2Available
, &Drive2Total
, NULL
);
485 Drive2Available
.QuadPart
= Drive2Total
.QuadPart
= 0;
488 if (lParam
== 3) /* Size */
489 Diff
.QuadPart
= Drive1Total
.QuadPart
- Drive2Total
.QuadPart
;
490 else /* Size available */
491 Diff
.QuadPart
= Drive1Available
.QuadPart
- Drive2Available
.QuadPart
;
493 hres
= MAKE_COMPARE_HRESULT(Diff
.QuadPart
);
500 if (HRESULT_CODE(hres
) == 0)
501 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
506 /**************************************************************************
507 * CDrivesFolder::CreateViewObject
509 HRESULT WINAPI
CDrivesFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
511 CComPtr
<IShellView
> pShellView
;
512 HRESULT hr
= E_INVALIDARG
;
514 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
515 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
522 if (IsEqualIID(riid
, IID_IDropTarget
))
524 WARN("IDropTarget not implemented\n");
527 else if (IsEqualIID(riid
, IID_IContextMenu
))
529 WARN("IContextMenu not implemented\n");
532 else if (IsEqualIID(riid
, IID_IShellView
))
534 SFV_CREATE sfvparams
= {sizeof(SFV_CREATE
), this};
535 hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**)ppvOut
);
537 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
541 static BOOL
_ILIsControlPanel(LPCITEMIDLIST pidl
)
543 GUID
*guid
= _ILGetGUIDPointer(pidl
);
545 TRACE("(%p)\n", pidl
);
548 return IsEqualIID(*guid
, CLSID_ControlPanel
);
552 /**************************************************************************
553 * CDrivesFolder::GetAttributesOf
555 HRESULT WINAPI
CDrivesFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
557 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
558 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
566 /* FIXME: always add SFGAO_CANLINK */
568 *rgfInOut
&= dwComputerAttributes
;
571 for (UINT i
= 0; i
< cidl
; ++i
)
573 if (_ILIsDrive(apidl
[i
]))
574 *rgfInOut
&= dwDriveAttributes
;
575 else if (_ILIsControlPanel(apidl
[i
]))
576 *rgfInOut
&= dwControlPanelAttributes
;
577 else if (_ILIsSpecialFolder(*apidl
))
578 m_regFolder
->GetAttributesOf(1, &apidl
[i
], rgfInOut
);
580 ERR("Got unknown pidl type!\n");
584 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
585 *rgfInOut
&= ~SFGAO_VALIDATE
;
587 TRACE ("-- result=0x%08x\n", *rgfInOut
);
591 /**************************************************************************
592 * CDrivesFolder::GetUIObjectOf
595 * hwndOwner [in] Parent window for any output
596 * cidl [in] array size
597 * apidl [in] simple pidl array
598 * riid [in] Requested Interface
599 * prgfInOut [ ] reserved
600 * ppvObject [out] Resulting Interface
603 HRESULT WINAPI
CDrivesFolder::GetUIObjectOf(HWND hwndOwner
,
604 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
605 REFIID riid
, UINT
*prgfInOut
, LPVOID
*ppvOut
)
608 HRESULT hr
= E_INVALIDARG
;
610 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
611 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
618 if (IsEqualIID (riid
, IID_IContextMenu
) && (cidl
>= 1))
620 if (_ILIsDrive(apidl
[0]))
621 hr
= CDrivesContextMenu_CreateInstance(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), (IContextMenu
**)&pObj
);
623 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
625 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
627 hr
= IDataObject_Constructor (hwndOwner
,
628 pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
630 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
632 if (_ILIsDrive(apidl
[0]))
633 hr
= CDrivesExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
635 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
637 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
== 1))
639 CComPtr
<IShellFolder
> psfChild
;
640 hr
= this->BindToObject(apidl
[0], NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
641 if (FAILED_UNEXPECTEDLY(hr
))
644 return psfChild
->CreateViewObject(NULL
, riid
, ppvOut
);
649 if (SUCCEEDED(hr
) && !pObj
)
653 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
657 /**************************************************************************
658 * CDrivesFolder::GetDisplayNameOf
660 HRESULT WINAPI
CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
665 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
671 if (!_ILIsPidlSimple (pidl
))
673 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
675 else if (_ILIsSpecialFolder(pidl
))
677 return m_regFolder
->GetDisplayNameOf(pidl
, dwFlags
, strRet
);
679 else if (!_ILIsDrive(pidl
))
681 ERR("Wrong pidl type\n");
685 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
687 return E_OUTOFMEMORY
;
691 _ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
); /* append my own path */
692 /* long view "lw_name (C:)" */
693 if (!(dwFlags
& SHGDN_FORPARSING
))
695 WCHAR wszDrive
[18] = {0};
696 DWORD dwVolumeSerialNumber
, dwMaximumComponentLength
, dwFileSystemFlags
;
697 static const WCHAR wszOpenBracket
[] = {' ', '(', 0};
698 static const WCHAR wszCloseBracket
[] = {')', 0};
700 lstrcpynW(wszDrive
, pszPath
, 4);
702 GetVolumeInformationW(wszDrive
, pszPath
,
704 &dwVolumeSerialNumber
,
705 &dwMaximumComponentLength
, &dwFileSystemFlags
, NULL
, 0);
706 pszPath
[MAX_PATH
-1] = L
'\0';
707 if (!wcslen(pszPath
))
709 UINT DriveType
, ResourceId
;
710 DriveType
= GetDriveTypeW(wszDrive
);
714 ResourceId
= IDS_DRIVE_FIXED
;
717 ResourceId
= IDS_DRIVE_NETWORK
;
720 ResourceId
= IDS_DRIVE_CDROM
;
727 dwFileSystemFlags
= LoadStringW(shell32_hInstance
, ResourceId
, pszPath
, MAX_PATH
);
728 if (dwFileSystemFlags
> MAX_PATH
- 7)
729 pszPath
[MAX_PATH
-7] = L
'\0';
732 wcscat (pszPath
, wszOpenBracket
);
734 wcscat (pszPath
, wszDrive
);
735 wcscat (pszPath
, wszCloseBracket
);
740 strRet
->uType
= STRRET_WSTR
;
741 strRet
->pOleStr
= pszPath
;
744 CoTaskMemFree(pszPath
);
746 TRACE("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
750 /**************************************************************************
751 * CDrivesFolder::SetNameOf
752 * Changes the name of a file object or subfolder, possibly changing its item
753 * identifier in the process.
756 * hwndOwner [in] Owner window for output
757 * pidl [in] simple pidl of item to change
758 * lpszName [in] the items new display name
759 * dwFlags [in] SHGNO formatting flags
760 * ppidlOut [out] simple pidl returned
762 HRESULT WINAPI
CDrivesFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
,
763 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
767 if (_ILIsDrive(pidl
))
769 if (_ILSimpleGetTextW(pidl
, szName
, _countof(szName
)))
770 SetVolumeLabelW(szName
, lpName
);
772 *pPidlOut
= _ILCreateDrive(szName
);
776 return m_regFolder
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
779 HRESULT WINAPI
CDrivesFolder::GetDefaultSearchGUID(GUID
* pguid
)
781 FIXME ("(%p)\n", this);
785 HRESULT WINAPI
CDrivesFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
787 FIXME ("(%p)\n", this);
791 HRESULT WINAPI
CDrivesFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
793 TRACE ("(%p)\n", this);
802 HRESULT WINAPI
CDrivesFolder::GetDefaultColumnState(UINT iColumn
, DWORD
* pcsFlags
)
804 TRACE ("(%p)\n", this);
806 if (!pcsFlags
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
808 *pcsFlags
= MyComputerSFHeader
[iColumn
].pcsFlags
;
812 HRESULT WINAPI
CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
* pscid
, VARIANT
* pv
)
814 FIXME ("(%p)\n", this);
818 HRESULT WINAPI
CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
822 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
824 if (!psd
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
829 psd
->fmt
= MyComputerSFHeader
[iColumn
].fmt
;
830 psd
->cxChar
= MyComputerSFHeader
[iColumn
].cxChar
;
831 return SHSetStrRet(&psd
->str
, MyComputerSFHeader
[iColumn
].colnameid
);
833 else if (!_ILIsDrive(pidl
))
835 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
839 ULARGE_INTEGER ulTotalBytes
, ulFreeBytes
;
840 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
841 UINT DriveType
= GetDriveTypeA(pszDrive
);
842 if (DriveType
> DRIVE_RAMDISK
)
843 DriveType
= DRIVE_FIXED
;
848 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
850 case 1: /* FIXME: comments */
851 hr
= SHSetStrRet(&psd
->str
, "");
854 hr
= SHSetStrRet(&psd
->str
, iDriveTypeIds
[DriveType
]);
856 case 3: /* total size */
857 case 4: /* free size */
858 psd
->str
.cStr
[0] = 0x00;
859 psd
->str
.uType
= STRRET_CSTR
;
860 if (GetVolumeInformationA(pszDrive
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
862 GetDiskFreeSpaceExA(pszDrive
, &ulFreeBytes
, &ulTotalBytes
, NULL
);
864 StrFormatByteSize64A(ulTotalBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
866 StrFormatByteSize64A(ulFreeBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
876 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
878 FIXME("(%p)\n", this);
882 /************************************************************************
883 * CDrivesFolder::GetClassID
885 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
887 TRACE ("(%p)\n", this);
892 *lpClassId
= CLSID_MyComputer
;
896 /************************************************************************
897 * CDrivesFolder::Initialize
899 * NOTES: it makes no sense to change the pidl
901 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
906 /**************************************************************************
907 * CDrivesFolder::GetCurFolder
909 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
911 TRACE("(%p)->(%p)\n", this, pidl
);
914 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
916 *pidl
= ILClone(pidlRoot
);