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
170 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
, IEnumIDList
* pRegEnumerator
)
172 /* enumerate the folders */
173 if (dwFlags
& SHCONTF_FOLDERS
)
175 WCHAR wszDriveName
[] = {'A', ':', '\\', '\0'};
176 DWORD dwDrivemap
= GetLogicalDrives();
178 while (wszDriveName
[0] <= 'Z')
180 if(dwDrivemap
& 0x00000001L
)
181 AddToEnumList(_ILCreateDrive(wszDriveName
));
183 dwDrivemap
= dwDrivemap
>> 1;
187 /* Enumerate the items of the reg folder */
188 AppendItemsFromEnumerator(pRegEnumerator
);
193 BEGIN_COM_MAP(CDrivesFolderEnum
)
194 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
198 /***********************************************************************
199 * IShellFolder [MyComputer] implementation
202 static const shvheader MyComputerSFHeader
[] = {
203 {IDS_SHV_COLUMN_NAME
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
204 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
, LVCFMT_LEFT
, 10},
205 {IDS_SHV_COLUMN_TYPE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
206 {IDS_SHV_COLUMN_DISK_CAPACITY
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
207 {IDS_SHV_COLUMN_DISK_AVAILABLE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
210 #define MYCOMPUTERSHELLVIEWCOLUMNS 5
212 static const DWORD dwComputerAttributes
=
213 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
214 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
215 static const DWORD dwControlPanelAttributes
=
216 SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
| SFGAO_CANLINK
;
217 static const DWORD dwDriveAttributes
=
218 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
219 SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANRENAME
| SFGAO_CANLINK
;
221 CDrivesFolder::CDrivesFolder()
226 CDrivesFolder::~CDrivesFolder()
228 TRACE ("-- destroying IShellFolder(%p)\n", this);
232 HRESULT WINAPI
CDrivesFolder::FinalConstruct()
234 pidlRoot
= _ILCreateMyComputer(); /* my qualified pidl */
235 if (pidlRoot
== NULL
)
236 return E_OUTOFMEMORY
;
238 HRESULT hr
= CRegFolder_CreateInstance(&CLSID_MyComputer
,
240 L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
242 IID_PPV_ARG(IShellFolder2
, &m_regFolder
));
247 /**************************************************************************
248 * CDrivesFolder::ParseDisplayName
250 HRESULT WINAPI
CDrivesFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
251 DWORD
* pchEaten
, PIDLIST_RELATIVE
* ppidl
, DWORD
* pdwAttributes
)
253 HRESULT hr
= E_INVALIDARG
;
254 LPCWSTR szNext
= NULL
;
255 LPITEMIDLIST pidlTemp
= NULL
;
257 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
258 hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
259 pchEaten
, ppidl
, pdwAttributes
);
263 *pchEaten
= 0; /* strange but like the original */
265 /* handle CLSID paths */
266 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
267 return m_regFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
269 if (PathGetDriveNumberW(lpszDisplayName
) < 0)
272 pidlTemp
= _ILCreateDrive(lpszDisplayName
);
274 return E_OUTOFMEMORY
;
276 if (lpszDisplayName
[2] == L
'\\')
278 szNext
= &lpszDisplayName
[3];
281 if (szNext
&& *szNext
)
283 hr
= SHELL32_ParseNextElement (this, hwndOwner
, pbc
, &pidlTemp
,
284 (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
289 if (pdwAttributes
&& *pdwAttributes
)
291 if (_ILIsDrive(pidlTemp
))
292 *pdwAttributes
&= dwDriveAttributes
;
293 else if (_ILIsSpecialFolder(pidlTemp
))
294 m_regFolder
->GetAttributesOf(1, &pidlTemp
, pdwAttributes
);
296 ERR("Got an unkown pidl here!\n");
302 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
307 /**************************************************************************
308 * CDrivesFolder::EnumObjects
310 HRESULT WINAPI
CDrivesFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
312 CComPtr
<IEnumIDList
> pRegEnumerator
;
313 m_regFolder
->EnumObjects(hwndOwner
, dwFlags
, &pRegEnumerator
);
315 return ShellObjectCreatorInit
<CDrivesFolderEnum
>(hwndOwner
, dwFlags
, pRegEnumerator
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
318 /**************************************************************************
319 * CDrivesFolder::BindToObject
321 HRESULT WINAPI
CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
323 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
324 pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
326 if (_ILIsSpecialFolder(pidl
))
327 return m_regFolder
->BindToObject(pidl
, pbcReserved
, riid
, ppvOut
);
329 CHAR
* pchDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
331 PERSIST_FOLDER_TARGET_INFO pfti
= {0};
332 pfti
.dwAttributes
= -1;
334 pfti
.szTargetParsingName
[0] = *pchDrive
;
335 pfti
.szTargetParsingName
[1] = L
':';
336 pfti
.szTargetParsingName
[2] = L
'\\';
338 HRESULT hr
= SHELL32_BindToSF(pidlRoot
,
341 &CLSID_ShellFSFolder
,
344 if (FAILED_UNEXPECTEDLY(hr
))
350 /**************************************************************************
351 * CDrivesFolder::BindToStorage
353 HRESULT WINAPI
CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
355 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
356 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
362 /**************************************************************************
363 * CDrivesFolder::CompareIDs
366 HRESULT WINAPI
CDrivesFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
370 if (!pidl1
|| !pidl2
)
372 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
376 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
377 return m_regFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
379 if (!_ILIsDrive(pidl1
) || !_ILIsDrive(pidl2
) || LOWORD(lParam
) >= MYCOMPUTERSHELLVIEWCOLUMNS
)
382 CHAR
* pszDrive1
= _ILGetDataPointer(pidl1
)->u
.drive
.szDriveName
;
383 CHAR
* pszDrive2
= _ILGetDataPointer(pidl2
)->u
.drive
.szDriveName
;
386 switch(LOWORD(lParam
))
390 result
= stricmp(pszDrive1
, pszDrive2
);
391 hres
= MAKE_COMPARE_HRESULT(result
);
394 case 1: /* comments */
395 hres
= MAKE_COMPARE_HRESULT(0);
399 /* We want to return immediately because SHELL32_CompareDetails also compares children. */
400 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
403 case 4: /* Size Available */
405 ULARGE_INTEGER Drive1Available
, Drive1Total
, Drive2Available
, Drive2Total
;
407 if (GetVolumeInformationA(pszDrive1
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
408 GetDiskFreeSpaceExA(pszDrive1
, &Drive1Available
, &Drive1Total
, NULL
);
410 Drive1Available
.QuadPart
= Drive1Total
.QuadPart
= 0;
412 if (GetVolumeInformationA(pszDrive2
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
413 GetDiskFreeSpaceExA(pszDrive2
, &Drive2Available
, &Drive2Total
, NULL
);
415 Drive2Available
.QuadPart
= Drive2Total
.QuadPart
= 0;
418 if (lParam
== 3) /* Size */
419 Diff
.QuadPart
= Drive1Total
.QuadPart
- Drive2Total
.QuadPart
;
420 else /* Size available */
421 Diff
.QuadPart
= Drive1Available
.QuadPart
- Drive2Available
.QuadPart
;
423 hres
= MAKE_COMPARE_HRESULT(Diff
.QuadPart
);
430 if (HRESULT_CODE(hres
) == 0)
431 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
436 /**************************************************************************
437 * CDrivesFolder::CreateViewObject
439 HRESULT WINAPI
CDrivesFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
441 CComPtr
<IShellView
> pShellView
;
442 HRESULT hr
= E_INVALIDARG
;
444 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
445 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
452 if (IsEqualIID(riid
, IID_IDropTarget
))
454 WARN("IDropTarget not implemented\n");
457 else if (IsEqualIID(riid
, IID_IContextMenu
))
459 WARN("IContextMenu not implemented\n");
462 else if (IsEqualIID(riid
, IID_IShellView
))
464 SFV_CREATE sfvparams
= {sizeof(SFV_CREATE
), this};
465 hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**)ppvOut
);
467 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
471 static BOOL
_ILIsControlPanel(LPCITEMIDLIST pidl
)
473 GUID
*guid
= _ILGetGUIDPointer(pidl
);
475 TRACE("(%p)\n", pidl
);
478 return IsEqualIID(*guid
, CLSID_ControlPanel
);
482 /**************************************************************************
483 * CDrivesFolder::GetAttributesOf
485 HRESULT WINAPI
CDrivesFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
487 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
488 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
496 /* FIXME: always add SFGAO_CANLINK */
498 *rgfInOut
&= dwComputerAttributes
;
501 for (UINT i
= 0; i
< cidl
; ++i
)
503 if (_ILIsDrive(apidl
[i
]))
504 *rgfInOut
&= dwDriveAttributes
;
505 else if (_ILIsControlPanel(apidl
[i
]))
506 *rgfInOut
&= dwControlPanelAttributes
;
507 else if (_ILIsSpecialFolder(*apidl
))
508 m_regFolder
->GetAttributesOf(1, &apidl
[i
], rgfInOut
);
510 ERR("Got unknown pidl type!\n");
514 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
515 *rgfInOut
&= ~SFGAO_VALIDATE
;
517 TRACE ("-- result=0x%08x\n", *rgfInOut
);
521 /**************************************************************************
522 * CDrivesFolder::GetUIObjectOf
525 * hwndOwner [in] Parent window for any output
526 * cidl [in] array size
527 * apidl [in] simple pidl array
528 * riid [in] Requested Interface
529 * prgfInOut [ ] reserved
530 * ppvObject [out] Resulting Interface
533 HRESULT WINAPI
CDrivesFolder::GetUIObjectOf(HWND hwndOwner
,
534 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
535 REFIID riid
, UINT
*prgfInOut
, LPVOID
*ppvOut
)
538 HRESULT hr
= E_INVALIDARG
;
540 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
541 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
548 if (IsEqualIID (riid
, IID_IContextMenu
) && (cidl
>= 1))
550 if (_ILIsDrive(apidl
[0]))
551 hr
= CDrivesContextMenu_CreateInstance(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), (IContextMenu
**)&pObj
);
553 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
555 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
557 hr
= IDataObject_Constructor (hwndOwner
,
558 pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
560 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
562 if (_ILIsDrive(apidl
[0]))
563 hr
= CDrivesExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
565 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
567 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
== 1))
569 CComPtr
<IShellFolder
> psfChild
;
570 hr
= this->BindToObject(apidl
[0], NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
571 if (FAILED_UNEXPECTEDLY(hr
))
574 return psfChild
->CreateViewObject(NULL
, riid
, ppvOut
);
579 if (SUCCEEDED(hr
) && !pObj
)
583 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
587 /**************************************************************************
588 * CDrivesFolder::GetDisplayNameOf
590 HRESULT WINAPI
CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
595 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
601 if (!_ILIsPidlSimple (pidl
))
603 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
605 else if (_ILIsSpecialFolder(pidl
))
607 return m_regFolder
->GetDisplayNameOf(pidl
, dwFlags
, strRet
);
609 else if (!_ILIsDrive(pidl
))
611 ERR("Wrong pidl type\n");
615 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
617 return E_OUTOFMEMORY
;
621 _ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
); /* append my own path */
622 /* long view "lw_name (C:)" */
623 if (!(dwFlags
& SHGDN_FORPARSING
))
625 WCHAR wszDrive
[18] = {0};
626 DWORD dwVolumeSerialNumber
, dwMaximumComponentLength
, dwFileSystemFlags
;
627 static const WCHAR wszOpenBracket
[] = {' ', '(', 0};
628 static const WCHAR wszCloseBracket
[] = {')', 0};
630 lstrcpynW(wszDrive
, pszPath
, 4);
632 GetVolumeInformationW(wszDrive
, pszPath
,
634 &dwVolumeSerialNumber
,
635 &dwMaximumComponentLength
, &dwFileSystemFlags
, NULL
, 0);
636 pszPath
[MAX_PATH
-1] = L
'\0';
637 if (!wcslen(pszPath
))
639 UINT DriveType
, ResourceId
;
640 DriveType
= GetDriveTypeW(wszDrive
);
644 ResourceId
= IDS_DRIVE_FIXED
;
647 ResourceId
= IDS_DRIVE_NETWORK
;
650 ResourceId
= IDS_DRIVE_CDROM
;
657 dwFileSystemFlags
= LoadStringW(shell32_hInstance
, ResourceId
, pszPath
, MAX_PATH
);
658 if (dwFileSystemFlags
> MAX_PATH
- 7)
659 pszPath
[MAX_PATH
-7] = L
'\0';
662 wcscat (pszPath
, wszOpenBracket
);
664 wcscat (pszPath
, wszDrive
);
665 wcscat (pszPath
, wszCloseBracket
);
670 strRet
->uType
= STRRET_WSTR
;
671 strRet
->pOleStr
= pszPath
;
674 CoTaskMemFree(pszPath
);
676 TRACE("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
680 /**************************************************************************
681 * CDrivesFolder::SetNameOf
682 * Changes the name of a file object or subfolder, possibly changing its item
683 * identifier in the process.
686 * hwndOwner [in] Owner window for output
687 * pidl [in] simple pidl of item to change
688 * lpszName [in] the items new display name
689 * dwFlags [in] SHGNO formatting flags
690 * ppidlOut [out] simple pidl returned
692 HRESULT WINAPI
CDrivesFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
,
693 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
697 if (_ILIsDrive(pidl
))
699 if (_ILSimpleGetTextW(pidl
, szName
, _countof(szName
)))
700 SetVolumeLabelW(szName
, lpName
);
702 *pPidlOut
= _ILCreateDrive(szName
);
706 return m_regFolder
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
709 HRESULT WINAPI
CDrivesFolder::GetDefaultSearchGUID(GUID
* pguid
)
711 FIXME ("(%p)\n", this);
715 HRESULT WINAPI
CDrivesFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
717 FIXME ("(%p)\n", this);
721 HRESULT WINAPI
CDrivesFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
723 TRACE ("(%p)\n", this);
732 HRESULT WINAPI
CDrivesFolder::GetDefaultColumnState(UINT iColumn
, DWORD
* pcsFlags
)
734 TRACE ("(%p)\n", this);
736 if (!pcsFlags
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
738 *pcsFlags
= MyComputerSFHeader
[iColumn
].pcsFlags
;
742 HRESULT WINAPI
CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
* pscid
, VARIANT
* pv
)
744 FIXME ("(%p)\n", this);
748 HRESULT WINAPI
CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
752 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
754 if (!psd
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
759 psd
->fmt
= MyComputerSFHeader
[iColumn
].fmt
;
760 psd
->cxChar
= MyComputerSFHeader
[iColumn
].cxChar
;
761 return SHSetStrRet(&psd
->str
, MyComputerSFHeader
[iColumn
].colnameid
);
763 else if (!_ILIsDrive(pidl
))
765 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
769 ULARGE_INTEGER ulTotalBytes
, ulFreeBytes
;
770 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
771 UINT DriveType
= GetDriveTypeA(pszDrive
);
772 if (DriveType
> DRIVE_RAMDISK
)
773 DriveType
= DRIVE_FIXED
;
778 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
780 case 1: /* FIXME: comments */
781 hr
= SHSetStrRet(&psd
->str
, "");
784 hr
= SHSetStrRet(&psd
->str
, iDriveTypeIds
[DriveType
]);
786 case 3: /* total size */
787 case 4: /* free size */
788 psd
->str
.cStr
[0] = 0x00;
789 psd
->str
.uType
= STRRET_CSTR
;
790 if (GetVolumeInformationA(pszDrive
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
792 GetDiskFreeSpaceExA(pszDrive
, &ulFreeBytes
, &ulTotalBytes
, NULL
);
794 StrFormatByteSize64A(ulTotalBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
796 StrFormatByteSize64A(ulFreeBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
806 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
808 FIXME("(%p)\n", this);
812 /************************************************************************
813 * CDrivesFolder::GetClassID
815 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
817 TRACE ("(%p)\n", this);
822 *lpClassId
= CLSID_MyComputer
;
826 /************************************************************************
827 * CDrivesFolder::Initialize
829 * NOTES: it makes no sense to change the pidl
831 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
836 /**************************************************************************
837 * CDrivesFolder::GetCurFolder
839 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
841 TRACE("(%p)->(%p)\n", this, pidl
);
844 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
846 *pidl
= ILClone(pidlRoot
);