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
, 0x7ABC, MFT_STRING
, MAKEINTRESOURCEW(IDS_FORMATDRIVE
), MFS_ENABLED
);
83 else if (uMsg
== DFM_INVOKECOMMAND
)
87 SHFormatDrive(hwnd
, szDrive
[0] - 'A', SHFMT_ID_DEFAULT
, 0);
89 else if (wParam
== DFM_CMD_PROPERTIES
)
92 wcscpy(wszBuf
, L
"A:\\");
93 wszBuf
[0] = (WCHAR
)szDrive
[0];
94 if (!SH_ShowDriveProperties(wszBuf
, pidlFolder
, apidl
))
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_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 IDropTarget
* pDt
= NULL
;
637 hr
= this->QueryInterface(IID_PPV_ARG(IDropTarget
, &pDt
));
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 (_ILIsSpecialFolder(pidl
))
829 return m_regFolder
->GetDetailsOf(pidl
, iColumn
, psd
);
833 char szPath
[MAX_PATH
];
834 ULARGE_INTEGER ulBytes
;
836 psd
->str
.cStr
[0] = 0x00;
837 psd
->str
.uType
= STRRET_CSTR
;
841 hr
= GetDisplayNameOf(pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
844 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
846 case 2: /* total size */
847 _ILSimpleGetText (pidl
, szPath
, MAX_PATH
);
848 if (GetVolumeInformationA(szPath
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
850 GetDiskFreeSpaceExA(szPath
, NULL
, &ulBytes
, NULL
);
851 StrFormatByteSize64A(ulBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
854 case 3: /* free size */
855 _ILSimpleGetText (pidl
, szPath
, MAX_PATH
);
856 if (GetVolumeInformationA(szPath
, NULL
, 0, NULL
, NULL
, NULL
, NULL
, 0))
858 GetDiskFreeSpaceExA(szPath
, &ulBytes
, NULL
, NULL
);
859 StrFormatByteSize64A(ulBytes
.QuadPart
, psd
->str
.cStr
, MAX_PATH
);
869 HRESULT WINAPI
CDrivesFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
* pscid
)
871 FIXME("(%p)\n", this);
875 /************************************************************************
876 * CDrivesFolder::GetClassID
878 HRESULT WINAPI
CDrivesFolder::GetClassID(CLSID
*lpClassId
)
880 TRACE ("(%p)\n", this);
885 *lpClassId
= CLSID_MyComputer
;
889 /************************************************************************
890 * CDrivesFolder::Initialize
892 * NOTES: it makes no sense to change the pidl
894 HRESULT WINAPI
CDrivesFolder::Initialize(LPCITEMIDLIST pidl
)
899 /**************************************************************************
900 * CDrivesFolder::GetCurFolder
902 HRESULT WINAPI
CDrivesFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
904 TRACE("(%p)->(%p)\n", this, pidl
);
907 return E_INVALIDARG
; /* xp doesn't have this check and crashes on NULL */
909 *pidl
= ILClone(pidlRoot
);