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 /***********************************************************************
39 * IShellFolder implementation
42 HRESULT CALLBACK
DrivesContextMenuCallback(IShellFolder
*psf
,
49 if (uMsg
!= DFM_MERGECONTEXTMENU
&& uMsg
!= DFM_INVOKECOMMAND
)
52 PIDLIST_ABSOLUTE pidlFolder
;
53 PUITEMID_CHILD
*apidl
;
55 HRESULT hr
= SH_GetApidlFromDataObject(pdtobj
, &pidlFolder
, &apidl
, &cidl
);
56 if (FAILED_UNEXPECTEDLY(hr
))
59 char szDrive
[8] = {0};
60 if (!_ILGetDrive(apidl
[0], szDrive
, sizeof(szDrive
)))
62 ERR("pidl is not a drive\n");
64 _ILFreeaPidl(apidl
, cidl
);
68 if (uMsg
== DFM_MERGECONTEXTMENU
)
70 QCMINFO
*pqcminfo
= (QCMINFO
*)lParam
;
73 if (GetVolumeInformationA(szDrive
, NULL
, 0, NULL
, NULL
, &dwFlags
, NULL
, 0))
75 /* Disable format if read only */
76 if (!(dwFlags
& FILE_READ_ONLY_VOLUME
) && GetDriveTypeA(szDrive
) != DRIVE_REMOTE
)
78 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
79 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, pqcminfo
->idCmdFirst
++, MFT_STRING
, MAKEINTRESOURCEW(IDS_FORMATDRIVE
), MFS_ENABLED
);
83 else if (uMsg
== DFM_INVOKECOMMAND
)
85 if (wParam
== DFM_CMD_PROPERTIES
)
88 wcscpy(wszBuf
, L
"A:\\");
89 wszBuf
[0] = (WCHAR
)szDrive
[0];
90 if (!SH_ShowDriveProperties(wszBuf
, pidlFolder
, apidl
))
95 SHFormatDrive(hwnd
, szDrive
[0] - 'A', SHFMT_ID_DEFAULT
, 0);
100 _ILFreeaPidl(apidl
, cidl
);
105 HRESULT
CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder
,
108 PCUITEMID_CHILD_ARRAY apidl
,
114 AddClassKeyToArray(L
"Drive", hKeys
, &cKeys
);
115 AddClassKeyToArray(L
"Folder", hKeys
, &cKeys
);
117 return CDefFolderMenu_Create2(pidlFolder
, hwnd
, cidl
, apidl
, psf
, DrivesContextMenuCallback
, cKeys
, hKeys
, ppcm
);
120 HRESULT
CDrivesExtractIcon_CreateInstance(IShellFolder
* psf
, LPCITEMIDLIST pidl
, REFIID riid
, LPVOID
* ppvOut
)
122 CComPtr
<IDefaultExtractIconInit
> initIcon
;
123 HRESULT hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
, &initIcon
));
124 if (FAILED_UNEXPECTEDLY(hr
))
127 CHAR
* pszDrive
= _ILGetDataPointer(pidl
)->u
.drive
.szDriveName
;
128 WCHAR wTemp
[MAX_PATH
];
133 switch(GetDriveTypeA(pszDrive
))
135 case DRIVE_REMOVABLE
:
136 icon_idx
= IDI_SHELL_3_14_FLOPPY
;
139 icon_idx
= IDI_SHELL_CDROM
;
142 icon_idx
= IDI_SHELL_NETDRIVE
;
145 icon_idx
= IDI_SHELL_RAMDISK
;
147 case DRIVE_NO_ROOT_DIR
:
148 icon_idx
= IDI_SHELL_CDROM
;
155 initIcon
->SetNormalIcon(swShell32Name
, -icon_idx
);
159 if (HCR_GetIconW(L
"Drive", wTemp
, NULL
, MAX_PATH
, &icon_idx
))
160 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
162 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_DRIVE
);
165 return initIcon
->QueryInterface(riid
, ppvOut
);
168 class CDrivesFolderEnum
:
169 public CEnumIDListBase
173 ~CDrivesFolderEnum();
174 HRESULT WINAPI
Initialize(HWND hwndOwner
, DWORD dwFlags
);
175 BOOL
CreateMyCompEnumList(DWORD dwFlags
);
177 BEGIN_COM_MAP(CDrivesFolderEnum
)
178 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
182 /***********************************************************************
183 * IShellFolder [MyComputer] implementation
186 static const shvheader MyComputerSFHeader
[] = {
187 {IDS_SHV_COLUMN1
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
188 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
189 {IDS_SHV_COLUMN6
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
190 {IDS_SHV_COLUMN7
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
193 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
195 static const DWORD dwComputerAttributes
=
196 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
197 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
198 static const DWORD dwControlPanelAttributes
=
199 SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
| SFGAO_CANLINK
;
200 static const DWORD dwDriveAttributes
=
201 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
202 SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANRENAME
| SFGAO_CANLINK
;
204 CDrivesFolderEnum::CDrivesFolderEnum()
208 CDrivesFolderEnum::~CDrivesFolderEnum()
212 HRESULT WINAPI
CDrivesFolderEnum::Initialize(HWND hwndOwner
, DWORD dwFlags
)
214 if (CreateMyCompEnumList(dwFlags
) == FALSE
)
220 /**************************************************************************
221 * CDrivesFolderEnum::CreateMyCompEnumList()
224 BOOL
CDrivesFolderEnum::CreateMyCompEnumList(DWORD dwFlags
)
227 static const WCHAR MyComputer_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\Namespace";
229 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
231 /* enumerate the folders */
232 if (dwFlags
& SHCONTF_FOLDERS
)
234 WCHAR wszDriveName
[] = {'A', ':', '\\', '\0'};
235 DWORD dwDrivemap
= GetLogicalDrives();
239 while (bRet
&& wszDriveName
[0] <= 'Z')
241 if(dwDrivemap
& 0x00000001L
)
242 bRet
= AddToEnumList(_ILCreateDrive(wszDriveName
));
244 dwDrivemap
= dwDrivemap
>> 1;
247 TRACE("-- (%p)-> enumerate (mycomputer shell extensions)\n", this);
248 for (i
= 0; i
< 2; i
++)
250 if (bRet
&& ERROR_SUCCESS
== RegOpenKeyExW(i
== 0 ? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
251 MyComputer_NameSpaceW
, 0, KEY_READ
, &hKey
))
260 dwSize
= sizeof(wszBuf
) / sizeof(wszBuf
[0]);
261 ErrorCode
= RegEnumKeyExW(hKey
, j
, wszBuf
, &dwSize
, 0, NULL
, NULL
, NULL
);
262 if (ERROR_SUCCESS
== ErrorCode
)
264 if (wszBuf
[0] != L
'{')
266 dwSize
= sizeof(wszBuf
);
267 RegGetValueW(hKey
, wszBuf
, NULL
, RRF_RT_REG_SZ
, NULL
, wszBuf
, &dwSize
);
270 /* FIXME: shell extensions - the type should be PT_SHELLEXT (tested) */
271 pidl
= _ILCreateGuidFromStrW(wszBuf
);
273 bRet
= AddToEnumList(pidl
);
275 ERR("Invalid MyComputer namespace extesion: %s\n", wszBuf
);
278 else if (ERROR_NO_MORE_ITEMS
== ErrorCode
)
290 CDrivesFolder::CDrivesFolder()
295 CDrivesFolder::~CDrivesFolder()
297 TRACE ("-- destroying IShellFolder(%p)\n", this);
301 HRESULT WINAPI
CDrivesFolder::FinalConstruct()
303 pidlRoot
= _ILCreateMyComputer(); /* my qualified pidl */
304 if (pidlRoot
== NULL
)
305 return E_OUTOFMEMORY
;
307 HRESULT hr
= CRegFolder_CreateInstance(&CLSID_MyComputer
,
309 L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
310 IID_PPV_ARG(IShellFolder2
, &m_regFolder
));
315 /**************************************************************************
316 * CDrivesFolder::ParseDisplayName
318 HRESULT WINAPI
CDrivesFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
319 DWORD
* pchEaten
, PIDLIST_RELATIVE
* ppidl
, DWORD
* pdwAttributes
)
321 HRESULT hr
= E_INVALIDARG
;
322 LPCWSTR szNext
= NULL
;
323 LPITEMIDLIST pidlTemp
= NULL
;
325 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
326 hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
327 pchEaten
, ppidl
, pdwAttributes
);
331 *pchEaten
= 0; /* strange but like the original */
333 /* handle CLSID paths */
334 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
335 return m_regFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
337 if (PathGetDriveNumberW(lpszDisplayName
) < 0)
340 pidlTemp
= _ILCreateDrive(lpszDisplayName
);
342 return E_OUTOFMEMORY
;
344 if (lpszDisplayName
[2] == L
'\\')
346 szNext
= &lpszDisplayName
[3];
349 if (szNext
&& *szNext
)
351 hr
= SHELL32_ParseNextElement (this, hwndOwner
, pbc
, &pidlTemp
,
352 (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
357 if (pdwAttributes
&& *pdwAttributes
)
359 if (_ILIsDrive(pidlTemp
))
360 *pdwAttributes
&= dwDriveAttributes
;
361 else if (_ILIsSpecialFolder(pidlTemp
))
362 m_regFolder
->GetAttributesOf(1, &pidlTemp
, pdwAttributes
);
364 ERR("Got an unkown pidl here!\n");
370 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
375 /**************************************************************************
376 * CDrivesFolder::EnumObjects
378 HRESULT WINAPI
CDrivesFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
380 return ShellObjectCreatorInit
<CDrivesFolderEnum
>(hwndOwner
, dwFlags
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
383 /**************************************************************************
384 * CDrivesFolder::BindToObject
386 HRESULT WINAPI
CDrivesFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
388 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this,
389 pidl
, pbcReserved
, shdebugstr_guid(&riid
), ppvOut
);
391 if (_ILIsSpecialFolder(pidl
))
392 return m_regFolder
->BindToObject(pidl
, pbcReserved
, riid
, ppvOut
);
394 LPITEMIDLIST pidlChild
= ILCloneFirst (pidl
);
396 return E_OUTOFMEMORY
;
398 CComPtr
<IShellFolder
> psf
;
399 HRESULT hr
= SHELL32_CoCreateInitSF(pidlRoot
,
402 &CLSID_ShellFSFolder
,
404 IID_PPV_ARG(IShellFolder
, &psf
));
411 if (_ILIsPidlSimple (pidl
))
413 return psf
->QueryInterface(riid
, ppvOut
);
417 return psf
->BindToObject(ILGetNext (pidl
), pbcReserved
, riid
, ppvOut
);
421 /**************************************************************************
422 * CDrivesFolder::BindToStorage
424 HRESULT WINAPI
CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
426 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
427 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
433 /**************************************************************************
434 * CDrivesFolder::CompareIDs
437 HRESULT WINAPI
CDrivesFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
441 if (!pidl1
|| !pidl2
)
443 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
447 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
448 return m_regFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
450 if (!_ILIsDrive(pidl1
) || !_ILIsDrive(pidl2
) || LOWORD(lParam
) >= MYCOMPUTERSHELLVIEWCOLUMNS
)
453 CHAR
* pszDrive1
= _ILGetDataPointer(pidl1
)->u
.drive
.szDriveName
;
454 CHAR
* pszDrive2
= _ILGetDataPointer(pidl2
)->u
.drive
.szDriveName
;
457 switch(LOWORD(lParam
))
461 result
= stricmp(pszDrive1
, pszDrive2
);
462 hres
= MAKE_COMPARE_HRESULT(result
);
467 /* We want to return immediately because SHELL32_CompareDetails also compares children. */
468 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
471 case 3: /* Size Available */
473 ULARGE_INTEGER Drive1Available
, Drive1Total
, Drive2Available
, Drive2Total
;
475 if (GetVolumeInformationA(pszDrive1
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
476 GetDiskFreeSpaceExA(pszDrive1
, &Drive1Available
, &Drive1Total
, NULL
);
478 Drive1Available
.QuadPart
= Drive1Total
.QuadPart
= 0;
480 if (GetVolumeInformationA(pszDrive2
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
481 GetDiskFreeSpaceExA(pszDrive2
, &Drive2Available
, &Drive2Total
, NULL
);
483 Drive2Available
.QuadPart
= Drive2Total
.QuadPart
= 0;
486 if (lParam
== 2) /* Size */
487 Diff
.QuadPart
= Drive1Total
.QuadPart
- Drive2Total
.QuadPart
;
488 else /* Size available */
489 Diff
.QuadPart
= Drive1Available
.QuadPart
- Drive2Available
.QuadPart
;
491 hres
= MAKE_COMPARE_HRESULT(Diff
.QuadPart
);
498 if (HRESULT_CODE(hres
) == 0)
499 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
504 /**************************************************************************
505 * CDrivesFolder::CreateViewObject
507 HRESULT WINAPI
CDrivesFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
* ppvOut
)
509 CComPtr
<IShellView
> pShellView
;
510 HRESULT hr
= E_INVALIDARG
;
512 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
513 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
520 if (IsEqualIID(riid
, IID_IDropTarget
))
522 WARN("IDropTarget not implemented\n");
525 else if (IsEqualIID(riid
, IID_IContextMenu
))
527 WARN("IContextMenu not implemented\n");
530 else if (IsEqualIID(riid
, IID_IShellView
))
532 hr
= CDefView_Constructor(this, riid
, ppvOut
);
534 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
538 static BOOL
_ILIsControlPanel(LPCITEMIDLIST pidl
)
540 GUID
*guid
= _ILGetGUIDPointer(pidl
);
542 TRACE("(%p)\n", pidl
);
545 return IsEqualIID(*guid
, CLSID_ControlPanel
);
549 /**************************************************************************
550 * CDrivesFolder::GetAttributesOf
552 HRESULT WINAPI
CDrivesFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
554 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
555 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
563 /* FIXME: always add SFGAO_CANLINK */
565 *rgfInOut
&= dwComputerAttributes
;
568 for (UINT i
= 0; i
< cidl
; ++i
)
570 if (_ILIsDrive(apidl
[i
]))
571 *rgfInOut
&= dwDriveAttributes
;
572 else if (_ILIsControlPanel(apidl
[i
]))
573 *rgfInOut
&= dwControlPanelAttributes
;
574 else if (_ILIsSpecialFolder(*apidl
))
575 m_regFolder
->GetAttributesOf(1, &apidl
[i
], rgfInOut
);
577 ERR("Got unknown pidl type!\n");
581 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
582 *rgfInOut
&= ~SFGAO_VALIDATE
;
584 TRACE ("-- result=0x%08x\n", *rgfInOut
);
588 /**************************************************************************
589 * CDrivesFolder::GetUIObjectOf
592 * hwndOwner [in] Parent window for any output
593 * cidl [in] array size
594 * apidl [in] simple pidl array
595 * riid [in] Requested Interface
596 * prgfInOut [ ] reserved
597 * ppvObject [out] Resulting Interface
600 HRESULT WINAPI
CDrivesFolder::GetUIObjectOf(HWND hwndOwner
,
601 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
602 REFIID riid
, UINT
*prgfInOut
, LPVOID
*ppvOut
)
605 HRESULT hr
= E_INVALIDARG
;
607 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
608 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
615 if (IsEqualIID (riid
, IID_IContextMenu
) && (cidl
>= 1))
617 if (_ILIsDrive(apidl
[0]))
618 hr
= CDrivesContextMenu_CreateInstance(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), (IContextMenu
**)&pObj
);
620 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
622 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
624 hr
= IDataObject_Constructor (hwndOwner
,
625 pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
627 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
629 if (_ILIsDrive(apidl
[0]))
630 hr
= CDrivesExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
632 hr
= m_regFolder
->GetUIObjectOf(hwndOwner
, cidl
, apidl
, riid
, prgfInOut
, &pObj
);
634 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
== 1))
636 CComPtr
<IShellFolder
> psfChild
;
637 hr
= this->BindToObject(apidl
[0], NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
638 if (FAILED_UNEXPECTEDLY(hr
))
641 return psfChild
->CreateViewObject(NULL
, riid
, ppvOut
);
646 if (SUCCEEDED(hr
) && !pObj
)
650 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
654 /**************************************************************************
655 * CDrivesFolder::GetDisplayNameOf
657 HRESULT WINAPI
CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
662 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
668 if (!_ILIsPidlSimple (pidl
))
670 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
672 else if (_ILIsSpecialFolder(pidl
))
674 return m_regFolder
->GetDisplayNameOf(pidl
, dwFlags
, strRet
);
676 else if (!_ILIsDrive(pidl
))
678 ERR("Wrong pidl type\n");
682 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
684 return E_OUTOFMEMORY
;
688 _ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
); /* append my own path */
689 /* long view "lw_name (C:)" */
690 if (!(dwFlags
& SHGDN_FORPARSING
))
692 WCHAR wszDrive
[18] = {0};
693 DWORD dwVolumeSerialNumber
, dwMaximumComponentLength
, dwFileSystemFlags
;
694 static const WCHAR wszOpenBracket
[] = {' ', '(', 0};
695 static const WCHAR wszCloseBracket
[] = {')', 0};
697 lstrcpynW(wszDrive
, pszPath
, 4);
699 GetVolumeInformationW(wszDrive
, pszPath
,
701 &dwVolumeSerialNumber
,
702 &dwMaximumComponentLength
, &dwFileSystemFlags
, NULL
, 0);
703 pszPath
[MAX_PATH
-1] = L
'\0';
704 if (!wcslen(pszPath
))
706 UINT DriveType
, ResourceId
;
707 DriveType
= GetDriveTypeW(wszDrive
);
711 ResourceId
= IDS_DRIVE_FIXED
;
714 ResourceId
= IDS_DRIVE_NETWORK
;
717 ResourceId
= IDS_DRIVE_CDROM
;
724 dwFileSystemFlags
= LoadStringW(shell32_hInstance
, ResourceId
, pszPath
, MAX_PATH
);
725 if (dwFileSystemFlags
> MAX_PATH
- 7)
726 pszPath
[MAX_PATH
-7] = L
'\0';
729 wcscat (pszPath
, wszOpenBracket
);
731 wcscat (pszPath
, wszDrive
);
732 wcscat (pszPath
, wszCloseBracket
);
737 strRet
->uType
= STRRET_WSTR
;
738 strRet
->pOleStr
= pszPath
;
741 CoTaskMemFree(pszPath
);
743 TRACE("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
747 /**************************************************************************
748 * CDrivesFolder::SetNameOf
749 * Changes the name of a file object or subfolder, possibly changing its item
750 * identifier in the process.
753 * hwndOwner [in] Owner window for output
754 * pidl [in] simple pidl of item to change
755 * lpszName [in] the items new display name
756 * dwFlags [in] SHGNO formatting flags
757 * ppidlOut [out] simple pidl returned
759 HRESULT WINAPI
CDrivesFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
,
760 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
764 if (_ILIsDrive(pidl
))
766 if (_ILSimpleGetTextW(pidl
, szName
, _countof(szName
)))
767 SetVolumeLabelW(szName
, lpName
);
769 *pPidlOut
= _ILCreateDrive(szName
);
773 return m_regFolder
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
776 HRESULT WINAPI
CDrivesFolder::GetDefaultSearchGUID(GUID
* pguid
)
778 FIXME ("(%p)\n", this);
782 HRESULT WINAPI
CDrivesFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
784 FIXME ("(%p)\n", this);
788 HRESULT WINAPI
CDrivesFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
790 TRACE ("(%p)\n", this);
799 HRESULT WINAPI
CDrivesFolder::GetDefaultColumnState(UINT iColumn
, DWORD
* pcsFlags
)
801 TRACE ("(%p)\n", this);
803 if (!pcsFlags
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
805 *pcsFlags
= MyComputerSFHeader
[iColumn
].pcsFlags
;
809 HRESULT WINAPI
CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
* pscid
, VARIANT
* pv
)
811 FIXME ("(%p)\n", this);
815 HRESULT WINAPI
CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
819 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
821 if (!psd
|| iColumn
>= MYCOMPUTERSHELLVIEWCOLUMNS
)
826 psd
->fmt
= MyComputerSFHeader
[iColumn
].fmt
;
827 psd
->cxChar
= MyComputerSFHeader
[iColumn
].cxChar
;
828 return SHSetStrRet(&psd
->str
, MyComputerSFHeader
[iColumn
].colnameid
);
830 else if (_ILIsSpecialFolder(pidl
))
832 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
836 char szPath
[MAX_PATH
];
837 ULARGE_INTEGER ulBytes
;
839 psd
->str
.cStr
[0] = 0x00;
840 psd
->str
.uType
= STRRET_CSTR
;
844 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
847 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
849 case 2: /* total size */
850 _ILSimpleGetText (pidl
, szPath
, MAX_PATH
);
851 if (GetVolumeInformationA(szPath
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
853 GetDiskFreeSpaceExA(szPath
, NULL
, &ulBytes
, NULL
);
854 StrFormatByteSize64A(ulBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
857 case 3: /* free size */
858 _ILSimpleGetText (pidl
, szPath
, MAX_PATH
);
859 if (GetVolumeInformationA(szPath
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
861 GetDiskFreeSpaceExA(szPath
, &ulBytes
, NULL
, NULL
);
862 StrFormatByteSize64A(ulBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
872 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
874 FIXME("(%p)\n", this);
878 /************************************************************************
879 * CDrivesFolder::GetClassID
881 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
883 TRACE ("(%p)\n", this);
888 *lpClassId
= CLSID_MyComputer
;
892 /************************************************************************
893 * CDrivesFolder::Initialize
895 * NOTES: it makes no sense to change the pidl
897 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
902 /**************************************************************************
903 * CDrivesFolder::GetCurFolder
905 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
907 TRACE("(%p)->(%p)\n", this, pidl
);
910 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
912 *pidl
= ILClone(pidlRoot
);