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 CHAR
* pchDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
395 PERSIST_FOLDER_TARGET_INFO pfti
= {0};
396 pfti
.dwAttributes
= -1;
398 pfti
.szTargetParsingName
[0] = *pchDrive
;
399 pfti
.szTargetParsingName
[1] = L
':';
400 pfti
.szTargetParsingName
[2] = L
'\\';
402 HRESULT hr
= SHELL32_BindToSF(pidlRoot
,
405 &CLSID_ShellFSFolder
,
408 if (FAILED_UNEXPECTEDLY(hr
))
414 /**************************************************************************
415 * CDrivesFolder::BindToStorage
417 HRESULT WINAPI
CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
419 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
420 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
426 /**************************************************************************
427 * CDrivesFolder::CompareIDs
430 HRESULT WINAPI
CDrivesFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
434 if (!pidl1
|| !pidl2
)
436 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
440 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
441 return m_regFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
443 if (!_ILIsDrive(pidl1
) || !_ILIsDrive(pidl2
) || LOWORD(lParam
) >= MYCOMPUTERSHELLVIEWCOLUMNS
)
446 CHAR
* pszDrive1
= _ILGetDataPointer(pidl1
)->u
.drive
.szDriveName
;
447 CHAR
* pszDrive2
= _ILGetDataPointer(pidl2
)->u
.drive
.szDriveName
;
450 switch(LOWORD(lParam
))
454 result
= stricmp(pszDrive1
, pszDrive2
);
455 hres
= MAKE_COMPARE_HRESULT(result
);
458 case 1: /* comments */
459 hres
= MAKE_COMPARE_HRESULT(0);
463 /* We want to return immediately because SHELL32_CompareDetails also compares children. */
464 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
467 case 4: /* Size Available */
469 ULARGE_INTEGER Drive1Available
, Drive1Total
, Drive2Available
, Drive2Total
;
471 if (GetVolumeInformationA(pszDrive1
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
472 GetDiskFreeSpaceExA(pszDrive1
, &Drive1Available
, &Drive1Total
, NULL
);
474 Drive1Available
.QuadPart
= Drive1Total
.QuadPart
= 0;
476 if (GetVolumeInformationA(pszDrive2
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
477 GetDiskFreeSpaceExA(pszDrive2
, &Drive2Available
, &Drive2Total
, NULL
);
479 Drive2Available
.QuadPart
= Drive2Total
.QuadPart
= 0;
482 if (lParam
== 3) /* Size */
483 Diff
.QuadPart
= Drive1Total
.QuadPart
- Drive2Total
.QuadPart
;
484 else /* Size available */
485 Diff
.QuadPart
= Drive1Available
.QuadPart
- Drive2Available
.QuadPart
;
487 hres
= MAKE_COMPARE_HRESULT(Diff
.QuadPart
);
494 if (HRESULT_CODE(hres
) == 0)
495 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
500 /**************************************************************************
501 * CDrivesFolder::CreateViewObject
503 HRESULT WINAPI
CDrivesFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
505 CComPtr
<IShellView
> pShellView
;
506 HRESULT hr
= E_INVALIDARG
;
508 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
509 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
516 if (IsEqualIID(riid
, IID_IDropTarget
))
518 WARN("IDropTarget not implemented\n");
521 else if (IsEqualIID(riid
, IID_IContextMenu
))
523 WARN("IContextMenu not implemented\n");
526 else if (IsEqualIID(riid
, IID_IShellView
))
528 SFV_CREATE sfvparams
= {sizeof(SFV_CREATE
), this};
529 hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**)ppvOut
);
531 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
535 static BOOL
_ILIsControlPanel(LPCITEMIDLIST pidl
)
537 GUID
*guid
= _ILGetGUIDPointer(pidl
);
539 TRACE("(%p)\n", pidl
);
542 return IsEqualIID(*guid
, CLSID_ControlPanel
);
546 /**************************************************************************
547 * CDrivesFolder::GetAttributesOf
549 HRESULT WINAPI
CDrivesFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
551 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
552 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
560 /* FIXME: always add SFGAO_CANLINK */
562 *rgfInOut
&= dwComputerAttributes
;
565 for (UINT i
= 0; i
< cidl
; ++i
)
567 if (_ILIsDrive(apidl
[i
]))
568 *rgfInOut
&= dwDriveAttributes
;
569 else if (_ILIsControlPanel(apidl
[i
]))
570 *rgfInOut
&= dwControlPanelAttributes
;
571 else if (_ILIsSpecialFolder(*apidl
))
572 m_regFolder
->GetAttributesOf(1, &apidl
[i
], rgfInOut
);
574 ERR("Got unknown pidl type!\n");
578 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
579 *rgfInOut
&= ~SFGAO_VALIDATE
;
581 TRACE ("-- result=0x%08x\n", *rgfInOut
);
585 /**************************************************************************
586 * CDrivesFolder::GetUIObjectOf
589 * hwndOwner [in] Parent window for any output
590 * cidl [in] array size
591 * apidl [in] simple pidl array
592 * riid [in] Requested Interface
593 * prgfInOut [ ] reserved
594 * ppvObject [out] Resulting Interface
597 HRESULT WINAPI
CDrivesFolder::GetUIObjectOf(HWND hwndOwner
,
598 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
599 REFIID riid
, UINT
*prgfInOut
, LPVOID
*ppvOut
)
602 HRESULT hr
= E_INVALIDARG
;
604 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
605 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
612 if (IsEqualIID (riid
, IID_IContextMenu
) && (cidl
>= 1))
614 if (_ILIsDrive(apidl
[0]))
615 hr
= CDrivesContextMenu_CreateInstance(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), (IContextMenu
**)&pObj
);
617 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
619 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
621 hr
= IDataObject_Constructor (hwndOwner
,
622 pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
624 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
626 if (_ILIsDrive(apidl
[0]))
627 hr
= CDrivesExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
629 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
631 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
== 1))
633 CComPtr
<IShellFolder
> psfChild
;
634 hr
= this->BindToObject(apidl
[0], NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
635 if (FAILED_UNEXPECTEDLY(hr
))
638 return psfChild
->CreateViewObject(NULL
, riid
, ppvOut
);
643 if (SUCCEEDED(hr
) && !pObj
)
647 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
651 /**************************************************************************
652 * CDrivesFolder::GetDisplayNameOf
654 HRESULT WINAPI
CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
659 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
665 if (!_ILIsPidlSimple (pidl
))
667 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
669 else if (_ILIsSpecialFolder(pidl
))
671 return m_regFolder
->GetDisplayNameOf(pidl
, dwFlags
, strRet
);
673 else if (!_ILIsDrive(pidl
))
675 ERR("Wrong pidl type\n");
679 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
681 return E_OUTOFMEMORY
;
685 _ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
); /* append my own path */
686 /* long view "lw_name (C:)" */
687 if (!(dwFlags
& SHGDN_FORPARSING
))
689 WCHAR wszDrive
[18] = {0};
690 DWORD dwVolumeSerialNumber
, dwMaximumComponentLength
, dwFileSystemFlags
;
691 static const WCHAR wszOpenBracket
[] = {' ', '(', 0};
692 static const WCHAR wszCloseBracket
[] = {')', 0};
694 lstrcpynW(wszDrive
, pszPath
, 4);
696 GetVolumeInformationW(wszDrive
, pszPath
,
698 &dwVolumeSerialNumber
,
699 &dwMaximumComponentLength
, &dwFileSystemFlags
, NULL
, 0);
700 pszPath
[MAX_PATH
-1] = L
'\0';
701 if (!wcslen(pszPath
))
703 UINT DriveType
, ResourceId
;
704 DriveType
= GetDriveTypeW(wszDrive
);
708 ResourceId
= IDS_DRIVE_FIXED
;
711 ResourceId
= IDS_DRIVE_NETWORK
;
714 ResourceId
= IDS_DRIVE_CDROM
;
721 dwFileSystemFlags
= LoadStringW(shell32_hInstance
, ResourceId
, pszPath
, MAX_PATH
);
722 if (dwFileSystemFlags
> MAX_PATH
- 7)
723 pszPath
[MAX_PATH
-7] = L
'\0';
726 wcscat (pszPath
, wszOpenBracket
);
728 wcscat (pszPath
, wszDrive
);
729 wcscat (pszPath
, wszCloseBracket
);
734 strRet
->uType
= STRRET_WSTR
;
735 strRet
->pOleStr
= pszPath
;
738 CoTaskMemFree(pszPath
);
740 TRACE("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
744 /**************************************************************************
745 * CDrivesFolder::SetNameOf
746 * Changes the name of a file object or subfolder, possibly changing its item
747 * identifier in the process.
750 * hwndOwner [in] Owner window for output
751 * pidl [in] simple pidl of item to change
752 * lpszName [in] the items new display name
753 * dwFlags [in] SHGNO formatting flags
754 * ppidlOut [out] simple pidl returned
756 HRESULT WINAPI
CDrivesFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
,
757 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
761 if (_ILIsDrive(pidl
))
763 if (_ILSimpleGetTextW(pidl
, szName
, _countof(szName
)))
764 SetVolumeLabelW(szName
, lpName
);
766 *pPidlOut
= _ILCreateDrive(szName
);
770 return m_regFolder
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
773 HRESULT WINAPI
CDrivesFolder::GetDefaultSearchGUID(GUID
* pguid
)
775 FIXME ("(%p)\n", this);
779 HRESULT WINAPI
CDrivesFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
781 FIXME ("(%p)\n", this);
785 HRESULT WINAPI
CDrivesFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
787 TRACE ("(%p)\n", this);
796 HRESULT WINAPI
CDrivesFolder::GetDefaultColumnState(UINT iColumn
, DWORD
* pcsFlags
)
798 TRACE ("(%p)\n", this);
800 if (!pcsFlags
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
802 *pcsFlags
= MyComputerSFHeader
[iColumn
].pcsFlags
;
806 HRESULT WINAPI
CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
* pscid
, VARIANT
* pv
)
808 FIXME ("(%p)\n", this);
812 HRESULT WINAPI
CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
816 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
818 if (!psd
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
823 psd
->fmt
= MyComputerSFHeader
[iColumn
].fmt
;
824 psd
->cxChar
= MyComputerSFHeader
[iColumn
].cxChar
;
825 return SHSetStrRet(&psd
->str
, MyComputerSFHeader
[iColumn
].colnameid
);
827 else if (!_ILIsDrive(pidl
))
829 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
833 ULARGE_INTEGER ulTotalBytes
, ulFreeBytes
;
834 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
835 UINT DriveType
= GetDriveTypeA(pszDrive
);
836 if (DriveType
> DRIVE_RAMDISK
)
837 DriveType
= DRIVE_FIXED
;
842 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
844 case 1: /* FIXME: comments */
845 hr
= SHSetStrRet(&psd
->str
, "");
848 hr
= SHSetStrRet(&psd
->str
, iDriveTypeIds
[DriveType
]);
850 case 3: /* total size */
851 case 4: /* free size */
852 psd
->str
.cStr
[0] = 0x00;
853 psd
->str
.uType
= STRRET_CSTR
;
854 if (GetVolumeInformationA(pszDrive
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
856 GetDiskFreeSpaceExA(pszDrive
, &ulFreeBytes
, &ulTotalBytes
, NULL
);
858 StrFormatByteSize64A(ulTotalBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
860 StrFormatByteSize64A(ulFreeBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
870 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
872 FIXME("(%p)\n", this);
876 /************************************************************************
877 * CDrivesFolder::GetClassID
879 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
881 TRACE ("(%p)\n", this);
886 *lpClassId
= CLSID_MyComputer
;
890 /************************************************************************
891 * CDrivesFolder::Initialize
893 * NOTES: it makes no sense to change the pidl
895 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
900 /**************************************************************************
901 * CDrivesFolder::GetCurFolder
903 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
905 TRACE("(%p)->(%p)\n", this, pidl
);
908 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
910 *pidl
= ILClone(pidlRoot
);