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_COLUMN1
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
186 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
187 {IDS_SHV_COLUMN6
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
188 {IDS_SHV_COLUMN7
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
191 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
193 static const DWORD dwComputerAttributes
=
194 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
195 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
196 static const DWORD dwControlPanelAttributes
=
197 SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
| SFGAO_CANLINK
;
198 static const DWORD dwDriveAttributes
=
199 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
200 SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANRENAME
| SFGAO_CANLINK
;
202 CDrivesFolderEnum::CDrivesFolderEnum()
206 CDrivesFolderEnum::~CDrivesFolderEnum()
210 HRESULT WINAPI
CDrivesFolderEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
212 if (CreateMyCompEnumList(dwFlags
) == FALSE
)
218 /**************************************************************************
219 * CDrivesFolderEnum::CreateMyCompEnumList()
222 BOOL
CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags
)
225 static const WCHAR MyComputer_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
227 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
229 /* enumerate the folders */
230 if (dwFlags
& SHCONTF_FOLDERS
)
232 WCHAR wszDriveName
[] = {'A', ':', '\\', '\0'};
233 DWORD dwDrivemap
= GetLogicalDrives();
237 while (bRet
&& wszDriveName
[0] <= 'Z')
239 if(dwDrivemap
& 0x00000001L
)
240 bRet
= AddToEnumList(_ILCreateDrive(wszDriveName
));
242 dwDrivemap
= dwDrivemap
>> 1;
245 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
246 for (i
= 0; i
< 2; i
++)
248 if (bRet
&& ERROR_SUCCESS
== RegOpenKeyExW(i
== 0 ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
249 MyComputer_NameSpaceW
, 0, KEY_READ
, &hKey
))
258 dwSize
= sizeof(wszBuf
) / sizeof(wszBuf
[0]);
259 ErrorCode
= RegEnumKeyExW(hKey
, j
, wszBuf
, &dwSize
, 0, NULL
, NULL
, NULL
);
260 if (ERROR_SUCCESS
== ErrorCode
)
262 if (wszBuf
[0] != L
'{')
264 dwSize
= sizeof(wszBuf
);
265 RegGetValueW(hKey
, wszBuf
, NULL
, RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
);
268 /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
269 pidl
= _ILCreateGuidFromStrW(wszBuf
);
271 bRet
= AddToEnumList(pidl
);
273 ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf
);
276 else if (ERROR_NO_MORE_ITEMS
== ErrorCode
)
288 CDrivesFolder::CDrivesFolder()
293 CDrivesFolder::~CDrivesFolder()
295 TRACE ("-- destroying IShellFolder(%p)\n", this);
299 HRESULT WINAPI
CDrivesFolder::FinalConstruct()
301 pidlRoot
= _ILCreateMyComputer(); /* my qualified pidl */
302 if (pidlRoot
== NULL
)
303 return E_OUTOFMEMORY
;
305 HRESULT hr
= CRegFolder_CreateInstance(&CLSID_MyComputer
,
307 L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
308 IID_PPV_ARG(IShellFolder2
, &m_regFolder
));
313 /**************************************************************************
314 * CDrivesFolder::ParseDisplayName
316 HRESULT WINAPI
CDrivesFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
317 DWORD
* pchEaten
, PIDLIST_RELATIVE
* ppidl
, DWORD
* pdwAttributes
)
319 HRESULT hr
= E_INVALIDARG
;
320 LPCWSTR szNext
= NULL
;
321 LPITEMIDLIST pidlTemp
= NULL
;
323 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
324 hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
325 pchEaten
, ppidl
, pdwAttributes
);
329 *pchEaten
= 0; /* strange but like the original */
331 /* handle CLSID paths */
332 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
333 return m_regFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
335 if (PathGetDriveNumberW(lpszDisplayName
) < 0)
338 pidlTemp
= _ILCreateDrive(lpszDisplayName
);
340 return E_OUTOFMEMORY
;
342 if (lpszDisplayName
[2] == L
'\\')
344 szNext
= &lpszDisplayName
[3];
347 if (szNext
&& *szNext
)
349 hr
= SHELL32_ParseNextElement (this, hwndOwner
, pbc
, &pidlTemp
,
350 (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
355 if (pdwAttributes
&& *pdwAttributes
)
357 if (_ILIsDrive(pidlTemp
))
358 *pdwAttributes
&= dwDriveAttributes
;
359 else if (_ILIsSpecialFolder(pidlTemp
))
360 m_regFolder
->GetAttributesOf(1, &pidlTemp
, pdwAttributes
);
362 ERR("Got an unkown pidl here!\n");
368 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
373 /**************************************************************************
374 * CDrivesFolder::EnumObjects
376 HRESULT WINAPI
CDrivesFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
378 return ShellObjectCreatorInit
<CDrivesFolderEnum
>(hwndOwner
, dwFlags
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
381 /**************************************************************************
382 * CDrivesFolder::BindToObject
384 HRESULT WINAPI
CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
386 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
387 pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
389 if (_ILIsSpecialFolder(pidl
))
390 return m_regFolder
->BindToObject(pidl
, pbcReserved
, riid
, ppvOut
);
392 LPITEMIDLIST pidlChild
= ILCloneFirst (pidl
);
394 return E_OUTOFMEMORY
;
396 CComPtr
<IShellFolder
> psf
;
397 HRESULT hr
= SHELL32_CoCreateInitSF(pidlRoot
,
400 &CLSID_ShellFSFolder
,
402 IID_PPV_ARG(IShellFolder
, &psf
));
409 if (_ILIsPidlSimple (pidl
))
411 return psf
->QueryInterface(riid
, ppvOut
);
415 return psf
->BindToObject(ILGetNext (pidl
), pbcReserved
, riid
, ppvOut
);
419 /**************************************************************************
420 * CDrivesFolder::BindToStorage
422 HRESULT WINAPI
CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
424 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
425 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
431 /**************************************************************************
432 * CDrivesFolder::CompareIDs
435 HRESULT WINAPI
CDrivesFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
439 if (!pidl1
|| !pidl2
)
441 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
445 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
446 return m_regFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
448 if (!_ILIsDrive(pidl1
) || !_ILIsDrive(pidl2
) || LOWORD(lParam
) >= MYCOMPUTERSHELLVIEWCOLUMNS
)
451 CHAR
* pszDrive1
= _ILGetDataPointer(pidl1
)->u
.drive
.szDriveName
;
452 CHAR
* pszDrive2
= _ILGetDataPointer(pidl2
)->u
.drive
.szDriveName
;
455 switch(LOWORD(lParam
))
459 result
= stricmp(pszDrive1
, pszDrive2
);
460 hres
= MAKE_COMPARE_HRESULT(result
);
465 /* We want to return immediately because SHELL32_CompareDetails also compares children. */
466 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
469 case 3: /* Size Available */
471 ULARGE_INTEGER Drive1Available
, Drive1Total
, Drive2Available
, Drive2Total
;
473 if (GetVolumeInformationA(pszDrive1
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
474 GetDiskFreeSpaceExA(pszDrive1
, &Drive1Available
, &Drive1Total
, NULL
);
476 Drive1Available
.QuadPart
= Drive1Total
.QuadPart
= 0;
478 if (GetVolumeInformationA(pszDrive2
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
479 GetDiskFreeSpaceExA(pszDrive2
, &Drive2Available
, &Drive2Total
, NULL
);
481 Drive2Available
.QuadPart
= Drive2Total
.QuadPart
= 0;
484 if (lParam
== 2) /* Size */
485 Diff
.QuadPart
= Drive1Total
.QuadPart
- Drive2Total
.QuadPart
;
486 else /* Size available */
487 Diff
.QuadPart
= Drive1Available
.QuadPart
- Drive2Available
.QuadPart
;
489 hres
= MAKE_COMPARE_HRESULT(Diff
.QuadPart
);
496 if (HRESULT_CODE(hres
) == 0)
497 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
502 /**************************************************************************
503 * CDrivesFolder::CreateViewObject
505 HRESULT WINAPI
CDrivesFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
507 CComPtr
<IShellView
> pShellView
;
508 HRESULT hr
= E_INVALIDARG
;
510 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
511 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
518 if (IsEqualIID(riid
, IID_IDropTarget
))
520 WARN("IDropTarget not implemented\n");
523 else if (IsEqualIID(riid
, IID_IContextMenu
))
525 WARN("IContextMenu not implemented\n");
528 else if (IsEqualIID(riid
, IID_IShellView
))
530 hr
= CDefView_Constructor(this, riid
, ppvOut
);
532 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
536 static BOOL
_ILIsControlPanel(LPCITEMIDLIST pidl
)
538 GUID
*guid
= _ILGetGUIDPointer(pidl
);
540 TRACE("(%p)\n", pidl
);
543 return IsEqualIID(*guid
, CLSID_ControlPanel
);
547 /**************************************************************************
548 * CDrivesFolder::GetAttributesOf
550 HRESULT WINAPI
CDrivesFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
552 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
553 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
561 /* FIXME: always add SFGAO_CANLINK */
563 *rgfInOut
&= dwComputerAttributes
;
566 for (UINT i
= 0; i
< cidl
; ++i
)
568 if (_ILIsDrive(apidl
[i
]))
569 *rgfInOut
&= dwDriveAttributes
;
570 else if (_ILIsControlPanel(apidl
[i
]))
571 *rgfInOut
&= dwControlPanelAttributes
;
572 else if (_ILIsSpecialFolder(*apidl
))
573 m_regFolder
->GetAttributesOf(1, &apidl
[i
], rgfInOut
);
575 ERR("Got unknown pidl type!\n");
579 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
580 *rgfInOut
&= ~SFGAO_VALIDATE
;
582 TRACE ("-- result=0x%08x\n", *rgfInOut
);
586 /**************************************************************************
587 * CDrivesFolder::GetUIObjectOf
590 * hwndOwner [in] Parent window for any output
591 * cidl [in] array size
592 * apidl [in] simple pidl array
593 * riid [in] Requested Interface
594 * prgfInOut [ ] reserved
595 * ppvObject [out] Resulting Interface
598 HRESULT WINAPI
CDrivesFolder::GetUIObjectOf(HWND hwndOwner
,
599 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
600 REFIID riid
, UINT
*prgfInOut
, LPVOID
*ppvOut
)
603 HRESULT hr
= E_INVALIDARG
;
605 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
606 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
613 if (IsEqualIID (riid
, IID_IContextMenu
) && (cidl
>= 1))
615 if (_ILIsDrive(apidl
[0]))
616 hr
= CDrivesContextMenu_CreateInstance(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), (IContextMenu
**)&pObj
);
618 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
620 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
622 hr
= IDataObject_Constructor (hwndOwner
,
623 pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
625 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
627 if (_ILIsDrive(apidl
[0]))
628 hr
= CDrivesExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
630 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
632 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
== 1))
634 CComPtr
<IShellFolder
> psfChild
;
635 hr
= this->BindToObject(apidl
[0], NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
636 if (FAILED_UNEXPECTEDLY(hr
))
639 return psfChild
->CreateViewObject(NULL
, riid
, ppvOut
);
644 if (SUCCEEDED(hr
) && !pObj
)
648 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
652 /**************************************************************************
653 * CDrivesFolder::GetDisplayNameOf
655 HRESULT WINAPI
CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
660 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
666 if (!_ILIsPidlSimple (pidl
))
668 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
670 else if (_ILIsSpecialFolder(pidl
))
672 return m_regFolder
->GetDisplayNameOf(pidl
, dwFlags
, strRet
);
674 else if (!_ILIsDrive(pidl
))
676 ERR("Wrong pidl type\n");
680 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
682 return E_OUTOFMEMORY
;
686 _ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
); /* append my own path */
687 /* long view "lw_name (C:)" */
688 if (!(dwFlags
& SHGDN_FORPARSING
))
690 WCHAR wszDrive
[18] = {0};
691 DWORD dwVolumeSerialNumber
, dwMaximumComponentLength
, dwFileSystemFlags
;
692 static const WCHAR wszOpenBracket
[] = {' ', '(', 0};
693 static const WCHAR wszCloseBracket
[] = {')', 0};
695 lstrcpynW(wszDrive
, pszPath
, 4);
697 GetVolumeInformationW(wszDrive
, pszPath
,
699 &dwVolumeSerialNumber
,
700 &dwMaximumComponentLength
, &dwFileSystemFlags
, NULL
, 0);
701 pszPath
[MAX_PATH
-1] = L
'\0';
702 if (!wcslen(pszPath
))
704 UINT DriveType
, ResourceId
;
705 DriveType
= GetDriveTypeW(wszDrive
);
709 ResourceId
= IDS_DRIVE_FIXED
;
712 ResourceId
= IDS_DRIVE_NETWORK
;
715 ResourceId
= IDS_DRIVE_CDROM
;
722 dwFileSystemFlags
= LoadStringW(shell32_hInstance
, ResourceId
, pszPath
, MAX_PATH
);
723 if (dwFileSystemFlags
> MAX_PATH
- 7)
724 pszPath
[MAX_PATH
-7] = L
'\0';
727 wcscat (pszPath
, wszOpenBracket
);
729 wcscat (pszPath
, wszDrive
);
730 wcscat (pszPath
, wszCloseBracket
);
735 strRet
->uType
= STRRET_WSTR
;
736 strRet
->pOleStr
= pszPath
;
739 CoTaskMemFree(pszPath
);
741 TRACE("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
745 /**************************************************************************
746 * CDrivesFolder::SetNameOf
747 * Changes the name of a file object or subfolder, possibly changing its item
748 * identifier in the process.
751 * hwndOwner [in] Owner window for output
752 * pidl [in] simple pidl of item to change
753 * lpszName [in] the items new display name
754 * dwFlags [in] SHGNO formatting flags
755 * ppidlOut [out] simple pidl returned
757 HRESULT WINAPI
CDrivesFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
,
758 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
762 if (_ILIsDrive(pidl
))
764 if (_ILSimpleGetTextW(pidl
, szName
, _countof(szName
)))
765 SetVolumeLabelW(szName
, lpName
);
767 *pPidlOut
= _ILCreateDrive(szName
);
771 return m_regFolder
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
774 HRESULT WINAPI
CDrivesFolder::GetDefaultSearchGUID(GUID
* pguid
)
776 FIXME ("(%p)\n", this);
780 HRESULT WINAPI
CDrivesFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
782 FIXME ("(%p)\n", this);
786 HRESULT WINAPI
CDrivesFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
788 TRACE ("(%p)\n", this);
797 HRESULT WINAPI
CDrivesFolder::GetDefaultColumnState(UINT iColumn
, DWORD
* pcsFlags
)
799 TRACE ("(%p)\n", this);
801 if (!pcsFlags
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
803 *pcsFlags
= MyComputerSFHeader
[iColumn
].pcsFlags
;
807 HRESULT WINAPI
CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
* pscid
, VARIANT
* pv
)
809 FIXME ("(%p)\n", this);
813 HRESULT WINAPI
CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
817 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
819 if (!psd
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
824 psd
->fmt
= MyComputerSFHeader
[iColumn
].fmt
;
825 psd
->cxChar
= MyComputerSFHeader
[iColumn
].cxChar
;
826 return SHSetStrRet(&psd
->str
, MyComputerSFHeader
[iColumn
].colnameid
);
828 else if (!_ILIsDrive(pidl
))
830 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
834 ULARGE_INTEGER ulTotalBytes
, ulFreeBytes
;
835 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
836 UINT DriveType
= GetDriveTypeA(pszDrive
);
837 if (DriveType
> DRIVE_RAMDISK
)
838 DriveType
= DRIVE_FIXED
;
843 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
846 hr
= SHSetStrRet(&psd
->str
, iDriveTypeIds
[DriveType
]);
848 case 2: /* total size */
849 case 3: /* free size */
850 psd
->str
.cStr
[0] = 0x00;
851 psd
->str
.uType
= STRRET_CSTR
;
852 if (GetVolumeInformationA(pszDrive
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
854 GetDiskFreeSpaceExA(pszDrive
, &ulFreeBytes
, &ulTotalBytes
, NULL
);
856 StrFormatByteSize64A(ulTotalBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
858 StrFormatByteSize64A(ulFreeBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
868 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
870 FIXME("(%p)\n", this);
874 /************************************************************************
875 * CDrivesFolder::GetClassID
877 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
879 TRACE ("(%p)\n", this);
884 *lpClassId
= CLSID_MyComputer
;
888 /************************************************************************
889 * CDrivesFolder::Initialize
891 * NOTES: it makes no sense to change the pidl
893 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
898 /**************************************************************************
899 * CDrivesFolder::GetCurFolder
901 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
903 TRACE("(%p)->(%p)\n", this, pidl
);
906 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
908 *pidl
= ILClone(pidlRoot
);