[SHELL32][SHDOCVW] Fix drive volume renaming (#7812)

* [SHELL32] Fix drive volume renaming

- Support renaming to empty volume name.
- Use SHGDN_FOREDITING in Explorer tree and DefView ("Volname" instead of "VolName (C:)").
- Added support for the ShowDriveLettersFirst setting.

CORE-17292

* Suggested changes
This commit is contained in:
Whindmar Saksit 2025-03-24 22:01:22 +01:00 committed by GitHub
parent 185225a5fc
commit f222c2155d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 180 additions and 111 deletions

View file

@ -87,6 +87,7 @@ CNSCBand::~CNSCBand()
ImageList_Destroy(m_hToolbarImageList); ImageList_Destroy(m_hToolbarImageList);
m_hToolbarImageList = NULL; m_hToolbarImageList = NULL;
} }
SHFree(m_OriginalRename);
SHDOCVW_UnlockModule(); SHDOCVW_UnlockModule();
} }
@ -132,10 +133,10 @@ SFGAOF CNSCBand::_GetAttributesOfItem(_In_ CItemData *pData, _In_ SFGAOF Query)
return Attributes & Query; return Attributes & Query;
} }
HRESULT CNSCBand::_GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name) HRESULT CNSCBand::_GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, UINT Flags, PWSTR Name)
{ {
STRRET strret; STRRET strret;
HRESULT hr = pSF->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret); HRESULT hr = pSF->GetDisplayNameOf(pidl, Flags, &strret);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
return hr; return hr;
hr = StrRetToBufW(&strret, pidl, Name, MAX_PATH); hr = StrRetToBufW(&strret, pidl, Name, MAX_PATH);
@ -144,6 +145,11 @@ HRESULT CNSCBand::_GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR
return hr; return hr;
} }
HRESULT CNSCBand::_GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name)
{
return _GetNameOfItem(pSF, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, Name);
}
static HRESULT static HRESULT
SHDOCVW_GetCurrentLocationFromView(_In_ IShellView& View, _In_ PIDLIST_ABSOLUTE *ppidl) SHDOCVW_GetCurrentLocationFromView(_In_ IShellView& View, _In_ PIDLIST_ABSOLUTE *ppidl)
{ {
@ -798,23 +804,31 @@ LRESULT CNSCBand::OnBeginLabelEdit(_In_ LPNMTVDISPINFO dispInfo)
CComPtr<IShellFolder> pParent; CComPtr<IShellFolder> pParent;
LPCITEMIDLIST pChild; LPCITEMIDLIST pChild;
HRESULT hr; HRESULT hr;
HWND hWndEdit = TreeView_GetEditControl(dispInfo->hdr.hwndFrom);
SHFree(m_OriginalRename);
m_OriginalRename = NULL;
CItemData *info = _GetItemData(dispInfo->item.hItem); CItemData *info = _GetItemData(dispInfo->item.hItem);
if (!info) if (!info || !hWndEdit)
return FALSE; return TRUE;
hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, &pParent), &pChild); hr = SHBindToParent(info->absolutePidl, IID_PPV_ARG(IShellFolder, &pParent), &pChild);
if (FAILED_UNEXPECTEDLY(hr)) if (FAILED_UNEXPECTEDLY(hr))
return FALSE; return TRUE;
hr = pParent->GetAttributesOf(1, &pChild, &dwAttr); hr = pParent->GetAttributesOf(1, &pChild, &dwAttr);
if (SUCCEEDED(hr) && (dwAttr & SFGAO_CANRENAME)) if (SUCCEEDED(hr) && (dwAttr & SFGAO_CANRENAME))
{ {
WCHAR szName[MAX_PATH];
if (SUCCEEDED(_GetNameOfItem(pParent, pChild, SHGDN_FOREDITING | SHGDN_INFOLDER, szName)))
{
::SetWindowTextW(hWndEdit, szName);
SHStrDupW(szName, &m_OriginalRename);
}
m_isEditing = TRUE; m_isEditing = TRUE;
m_oldSelected = NULL; m_oldSelected = NULL;
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -861,6 +875,15 @@ LRESULT CNSCBand::OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo)
if (!dispInfo->item.pszText) if (!dispInfo->item.pszText)
return FALSE; return FALSE;
if (m_OriginalRename)
{
BOOL same = !lstrcmpW(m_OriginalRename, dispInfo->item.pszText); // Case-sensitive
SHFree(m_OriginalRename);
m_OriginalRename = NULL;
if (same)
return FALSE;
}
CComPtr<IShellFolder> pParent; CComPtr<IShellFolder> pParent;
LPCITEMIDLIST pidlChild; LPCITEMIDLIST pidlChild;
BOOL RenamedCurrent = _IsCurrentLocation(info->absolutePidl) == S_OK; BOOL RenamedCurrent = _IsCurrentLocation(info->absolutePidl) == S_OK;
@ -1297,7 +1320,8 @@ STDMETHODIMP CNSCBand::HasFocusIO()
STDMETHODIMP CNSCBand::TranslateAcceleratorIO(LPMSG lpMsg) STDMETHODIMP CNSCBand::TranslateAcceleratorIO(LPMSG lpMsg)
{ {
if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F2 && !m_isEditing) BOOL SkipAccelerators = m_isEditing || (!IsChild(lpMsg->hwnd) && lpMsg->hwnd != m_hWnd);
if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F2 && !SkipAccelerators)
{ {
if (HTREEITEM hItem = m_hwndTreeView.GetNextItem(NULL, TVGN_CARET)) if (HTREEITEM hItem = m_hwndTreeView.GetNextItem(NULL, TVGN_CARET))
{ {
@ -1310,7 +1334,7 @@ STDMETHODIMP CNSCBand::TranslateAcceleratorIO(LPMSG lpMsg)
} }
} }
if (lpMsg->message == WM_SYSKEYDOWN && lpMsg->wParam == VK_RETURN && !m_isEditing) if (lpMsg->message == WM_SYSKEYDOWN && lpMsg->wParam == VK_RETURN && !SkipAccelerators)
{ {
CItemData *pItem = _GetItemData(TVGN_CARET); CItemData *pItem = _GetItemData(TVGN_CARET);
if (pItem && _GetAttributesOfItem(pItem, SFGAO_HASPROPSHEET)) if (pItem && _GetAttributesOfItem(pItem, SFGAO_HASPROPSHEET))

View file

@ -44,6 +44,7 @@ public:
CItemData* _GetItemData(_In_ HTREEITEM hItem); CItemData* _GetItemData(_In_ HTREEITEM hItem);
CItemData* _GetItemData(_In_ UINT ItemSpec = TVGN_CARET); CItemData* _GetItemData(_In_ UINT ItemSpec = TVGN_CARET);
SFGAOF _GetAttributesOfItem(_In_ CItemData *pData, _In_ SFGAOF Query); SFGAOF _GetAttributesOfItem(_In_ CItemData *pData, _In_ SFGAOF Query);
HRESULT _GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, UINT Flags, PWSTR Name);
HRESULT _GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name); HRESULT _GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name);
// *** IOleWindow methods *** // *** IOleWindow methods ***
@ -147,6 +148,7 @@ protected:
HTREEITEM m_oldSelected = NULL; HTREEITEM m_oldSelected = NULL;
DWORD m_adviseCookie = 0; DWORD m_adviseCookie = 0;
ULONG m_shellRegID = 0; ULONG m_shellRegID = 0;
PWSTR m_OriginalRename = NULL;
// *** Drop target information *** // *** Drop target information ***
CComPtr<IDropTarget> m_pDropTarget; CComPtr<IDropTarget> m_pDropTarget;

View file

@ -2781,45 +2781,45 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
break; break;
case LVN_BEGINLABELEDITW: case LVN_BEGINLABELEDITW:
{ {
DWORD dwAttr = SFGAO_CANRENAME;
pidl = _PidlByItem(lpdi->item);
TRACE("-- LVN_BEGINLABELEDITW %p\n", this); TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
HWND hEdit = ListView_GetEditControl(m_ListView);
m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr); pidl = _PidlByItem(lpdi->item);
if (SFGAO_CANRENAME & dwAttr) DWORD fAttr = pidl ? GetItemAttributes(pidl, SFGAO_CANRENAME | SFGAO_FOLDER | SFGAO_FILESYSTEM) : 0;
if (!hEdit || !(fAttr & SFGAO_CANRENAME))
{ {
HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL)); MessageBeep(0xffffffff);
SHLimitInputEdit(hEdit, m_pSFParent); return TRUE;
// smartass-renaming: See CORE-15242
if (!(dwAttr & SFGAO_FOLDER) && (dwAttr & SFGAO_FILESYSTEM) &&
(lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename())
{
WCHAR szFullPath[MAX_PATH];
PIDLIST_ABSOLUTE pidlFull = ILCombine(m_pidlParent, pidl);
SHGetPathFromIDListW(pidlFull, szFullPath);
INT cchLimit = 0;
_DoFolderViewCB(SFVM_GETNAMELENGTH, (WPARAM)pidlFull, (LPARAM)&cchLimit);
if (cchLimit)
::SendMessageW(hEdit, EM_SETLIMITTEXT, cchLimit, 0);
if (!SHELL_FS_HideExtension(szFullPath))
{
LPWSTR pszText = lpdi->item.pszText;
LPWSTR pchDotExt = PathFindExtensionW(pszText);
::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText);
::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0);
}
ILFree(pidlFull);
}
m_isEditing = TRUE;
return FALSE;
} }
return TRUE;
WCHAR szName[MAX_PATH], *pszText = lpdi->item.pszText;
if (SUCCEEDED(Shell_DisplayNameOf(m_pSFParent, pidl, SHGDN_FOREDITING | SHGDN_INFOLDER,
szName, _countof(szName))))
{
pszText = szName;
::SetWindowText(hEdit, pszText);
}
// smartass-renaming: See CORE-15242
if (!(fAttr & SFGAO_FOLDER) && (fAttr & SFGAO_FILESYSTEM) &&
(lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename())
{
CComHeapPtr<ITEMIDLIST_RELATIVE> pidlFull(ILCombine(m_pidlParent, pidl));
WCHAR szFullPath[MAX_PATH];
if (SHGetPathFromIDListW(pidlFull, szFullPath) && !SHELL_FS_HideExtension(szFullPath))
{
LPWSTR pchDotExt = PathFindExtensionW(pszText);
::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText);
::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0);
}
}
INT cchLimit = 0;
_DoFolderViewCB(SFVM_GETNAMELENGTH, (WPARAM)pidl, (LPARAM)&cchLimit);
if (cchLimit)
::SendMessageW(hEdit, EM_SETLIMITTEXT, cchLimit, 0);
SHLimitInputEdit(hEdit, m_pSFParent);
m_isEditing = TRUE;
return FALSE;
} }
case LVN_ENDLABELEDITW: case LVN_ENDLABELEDITW:
{ {

View file

@ -573,11 +573,15 @@ CDrvDefExt::GeneralPageProc(
if (lppsn->hdr.code == PSN_APPLY) if (lppsn->hdr.code == PSN_APPLY)
{ {
CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER)); CDrvDefExt *pDrvDefExt = reinterpret_cast<CDrvDefExt *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
WCHAR wszBuf[256];
if (GetDlgItemTextW(hwndDlg, 14000, wszBuf, _countof(wszBuf))) HRESULT hr = E_FAIL;
SetVolumeLabelW(pDrvDefExt->m_wszDrive, wszBuf); HWND hLabel = GetDlgItem(hwndDlg, 14000);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); WCHAR wszBuf[256];
*wszBuf = UNICODE_NULL;
if (GetWindowTextW(hLabel, wszBuf, _countof(wszBuf)) || GetWindowTextLengthW(hLabel) == 0)
hr = CDrivesFolder::SetDriveLabel(hwndDlg, pDrvDefExt->m_wszDrive, wszBuf);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FAILED(hr) ? PSNRET_INVALID : PSNRET_NOERROR);
return TRUE; return TRUE;
} }
} }

View file

@ -78,6 +78,27 @@ static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
return NULL; return NULL;
} }
static INT8 GetDriveNumber(PCUITEMID_CHILD pidl)
{
if (!_ILIsDrive(pidl))
return -1;
BYTE letter = ((PIDLDATA*)pidl->mkid.abID)->u.drive.szDriveName[0];
BYTE number = (letter | 32) - 'a';
return number < 26 ? number : -1;
}
template<class T> static T* GetDrivePath(PCUITEMID_CHILD pidl, T *Path)
{
int number = GetDriveNumber(pidl);
if (number < 0)
return NULL;
Path[0] = 'A' + number;
Path[1] = ':';
Path[2] = '\\';
Path[3] = '\0';
return Path;
}
BOOL _ILGetDriveType(LPCITEMIDLIST pidl) BOOL _ILGetDriveType(LPCITEMIDLIST pidl)
{ {
WCHAR szDrive[8]; WCHAR szDrive[8];
@ -409,7 +430,7 @@ getIconLocationForDrive(IShellFolder *psf, PCITEMID_CHILD pidl, UINT uFlags,
} }
static HRESULT static HRESULT
getLabelForDrive(LPWSTR wszPath, LPWSTR wszLabel) getLabelForDriveFromAutoRun(PCWSTR wszPath, LPWSTR szLabel, UINT cchMax)
{ {
WCHAR wszAutoRunInfPath[MAX_PATH]; WCHAR wszAutoRunInfPath[MAX_PATH];
WCHAR wszTemp[MAX_PATH]; WCHAR wszTemp[MAX_PATH];
@ -423,13 +444,26 @@ getLabelForDrive(LPWSTR wszPath, LPWSTR wszLabel)
if (GetPrivateProfileStringW(L"autorun", L"label", NULL, wszTemp, _countof(wszTemp), if (GetPrivateProfileStringW(L"autorun", L"label", NULL, wszTemp, _countof(wszTemp),
wszAutoRunInfPath) && wszTemp[0] != 0) wszAutoRunInfPath) && wszTemp[0] != 0)
{ {
StringCchCopyW(wszLabel, _countof(wszTemp), wszTemp); StringCchCopyW(szLabel, cchMax, wszTemp);
return S_OK; return S_OK;
} }
return E_FAIL; return E_FAIL;
} }
static inline HRESULT GetRawDriveLabel(PCWSTR DrivePath, LPWSTR szLabel, UINT cchMax)
{
if (GetVolumeInformationW(DrivePath, szLabel, cchMax, NULL, NULL, NULL, NULL, 0))
return *szLabel ? S_OK : S_FALSE;
return HResultFromWin32(GetLastError());
}
static HRESULT GetDriveLabel(PCWSTR DrivePath, LPWSTR szLabel, UINT cchMax)
{
HRESULT hr = getLabelForDriveFromAutoRun(DrivePath, szLabel, cchMax);
return hr == S_OK ? S_OK : GetRawDriveLabel(DrivePath, szLabel, cchMax);
}
BOOL IsDriveFloppyA(LPCSTR pszDriveRoot); BOOL IsDriveFloppyA(LPCSTR pszDriveRoot);
HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
@ -562,6 +596,7 @@ static const DWORD dwDriveAttributes =
CDrivesFolder::CDrivesFolder() CDrivesFolder::CDrivesFolder()
{ {
pidlRoot = NULL; pidlRoot = NULL;
m_DriveDisplayMode = -1;
} }
CDrivesFolder::~CDrivesFolder() CDrivesFolder::~CDrivesFolder()
@ -947,8 +982,7 @@ HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner,
*/ */
HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{ {
LPWSTR pszPath; WCHAR szDrive[8];
HRESULT hr = S_OK;
TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet); TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
pdump (pidl); pdump (pidl);
@ -964,81 +998,76 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
{ {
return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet); return m_regFolder->GetDisplayNameOf(pidl, dwFlags, strRet);
} }
else if (!_ILIsDrive(pidl)) else if (!GetDrivePath(pidl, szDrive))
{ {
ERR("Wrong pidl type\n"); ERR("Wrong pidl type\n");
return E_INVALIDARG; return E_INVALIDARG;
} }
pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR)); PWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath) if (!pszPath)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
pszPath[0] = UNICODE_NULL;
szDrive[0] &= ~32; // Always uppercase
pszPath[0] = 0;
_ILSimpleGetTextW(pidl, pszPath, MAX_PATH); /* append my own path */
/* long view "lw_name (C:)" */ /* long view "lw_name (C:)" */
BOOL bEditLabel = GET_SHGDN_RELATION(dwFlags) == SHGDN_INFOLDER && (dwFlags & SHGDN_FOREDITING);
if (!(dwFlags & SHGDN_FORPARSING)) if (!(dwFlags & SHGDN_FORPARSING))
{ {
WCHAR wszDrive[18] = {0}; if (m_DriveDisplayMode < 0)
lstrcpynW(wszDrive, pszPath, 4);
pszPath[0] = L'\0';
if (!SUCCEEDED(getLabelForDrive(wszDrive, pszPath)))
{ {
DWORD dwVolumeSerialNumber, dwMaximumComponentLength, dwFileSystemFlags; DWORD err, type, data, cb = sizeof(data);
err = SHRegGetUSValueW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
L"ShowDriveLettersFirst", &type, &data, &cb, FALSE, NULL, 0);
m_DriveDisplayMode = (!err && type == REG_DWORD && cb == sizeof(data)) ? (BYTE)data : 0;
}
BOOL bRemoteFirst = m_DriveDisplayMode == 1;
BOOL bNoLetter = m_DriveDisplayMode == 2;
BOOL bAllFirst = m_DriveDisplayMode == 4;
PWSTR pszLabel = pszPath;
GetVolumeInformationW(wszDrive, pszPath, if (!bNoLetter && (bAllFirst || (bRemoteFirst && GetDriveTypeW(szDrive) == DRIVE_REMOTE)))
MAX_PATH - 7, {
&dwVolumeSerialNumber, bNoLetter = TRUE; // Handling the letter now, don't append it again later
&dwMaximumComponentLength, &dwFileSystemFlags, NULL, 0); if (!bEditLabel)
pszPath[MAX_PATH-1] = L'\0'; pszLabel += wsprintfW(pszPath, L"(%c:) ", szDrive[0]);
}
if (!wcslen(pszPath)) if (GetDriveLabel(szDrive, pszLabel, MAX_PATH - 7) != S_OK && !bEditLabel)
{
UINT ResourceId = 0;
switch (GetDriveTypeW(szDrive))
{ {
UINT DriveType, ResourceId; case DRIVE_REMOVABLE: ResourceId = IDS_DRIVE_REMOVABLE; break; // TODO: Floppy (cached)
DriveType = GetDriveTypeW(wszDrive); case DRIVE_FIXED: ResourceId = IDS_DRIVE_FIXED; break;
case DRIVE_REMOTE: ResourceId = IDS_DRIVE_NETWORK; break;
switch (DriveType) case DRIVE_CDROM: ResourceId = IDS_DRIVE_CDROM; break;
{ }
case DRIVE_FIXED: if (ResourceId)
ResourceId = IDS_DRIVE_FIXED; {
break; UINT len = LoadStringW(shell32_hInstance, ResourceId, pszLabel, MAX_PATH - 7);
case DRIVE_REMOTE: if (len > MAX_PATH - 7)
ResourceId = IDS_DRIVE_NETWORK; pszLabel[MAX_PATH-7] = UNICODE_NULL;
break;
case DRIVE_CDROM:
ResourceId = IDS_DRIVE_CDROM;
break;
default:
ResourceId = 0;
}
if (ResourceId)
{
dwFileSystemFlags = LoadStringW(shell32_hInstance, ResourceId, pszPath, MAX_PATH);
if (dwFileSystemFlags > MAX_PATH - 7)
pszPath[MAX_PATH-7] = L'\0';
}
} }
} }
wcscat(pszPath, L" (");
wszDrive[2] = L'\0'; if (!*pszLabel && !bEditLabel) // No label nor fallback description, use SHGDN_FORPARSING
wcscat(pszPath, wszDrive); *pszPath = UNICODE_NULL;
wcscat(pszPath, L")"); else if (!bNoLetter && !bEditLabel)
wsprintfW(pszPath + wcslen(pszPath), L" (%c:)", szDrive[0]);
} }
if (SUCCEEDED(hr)) if (!*pszPath && !bEditLabel) // SHGDN_FORPARSING or failure above (except editing empty label)
{ {
strRet->uType = STRRET_WSTR; if (GET_SHGDN_RELATION(dwFlags) == SHGDN_INFOLDER)
strRet->pOleStr = pszPath; szDrive[2] = UNICODE_NULL; // Remove backslash
wcscpy(pszPath, szDrive);
} }
else strRet->uType = STRRET_WSTR;
CoTaskMemFree(pszPath); strRet->pOleStr = pszPath;
TRACE("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr)); TRACE("-- (%p)->(%s)\n", this, strRet->uType == STRRET_CSTR ? strRet->cStr : debugstr_w(strRet->pOleStr));
return hr; return S_OK;
} }
/************************************************************************** /**************************************************************************
@ -1056,20 +1085,27 @@ HRESULT WINAPI CDrivesFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFla
HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, HRESULT WINAPI CDrivesFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl,
LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
{ {
WCHAR szName[30];
if (_ILIsDrive(pidl)) if (_ILIsDrive(pidl))
{ {
if (_ILSimpleGetTextW(pidl, szName, _countof(szName))) WCHAR szDrive[8];
SetVolumeLabelW(szName, lpName); HRESULT hr = GetDrivePath(pidl, szDrive) ? SetDriveLabel(hwndOwner, szDrive, lpName) : E_FAIL;
if (pPidlOut) if (pPidlOut)
*pPidlOut = _ILCreateDrive(szName); *pPidlOut = SUCCEEDED(hr) ? _ILCreateDrive(szDrive) : NULL;
return S_OK; return hr;
} }
return m_regFolder->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut); return m_regFolder->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
} }
HRESULT CDrivesFolder::SetDriveLabel(HWND hwndOwner, PCWSTR DrivePath, PCWSTR Label)
{
HRESULT hr = SetVolumeLabelW(DrivePath, *Label ? Label : NULL) ? S_OK : HResultFromWin32(GetLastError());
if (SUCCEEDED(hr))
SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_PATHW, DrivePath, DrivePath); // DisplayName changed
else if (hwndOwner)
SHELL_ErrorBox(hwndOwner, hr);
return hr;
}
HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid) HRESULT WINAPI CDrivesFolder::GetDefaultSearchGUID(GUID * pguid)
{ {
FIXME("(%p)\n", this); FIXME("(%p)\n", this);

View file

@ -36,12 +36,15 @@ class CDrivesFolder :
/* both paths are parsible from the desktop */ /* both paths are parsible from the desktop */
LPITEMIDLIST pidlRoot; /* absolute pidl */ LPITEMIDLIST pidlRoot; /* absolute pidl */
CComPtr<IShellFolder2> m_regFolder; CComPtr<IShellFolder2> m_regFolder;
INT8 m_DriveDisplayMode;
public: public:
CDrivesFolder(); CDrivesFolder();
~CDrivesFolder(); ~CDrivesFolder();
HRESULT WINAPI FinalConstruct(); HRESULT WINAPI FinalConstruct();
static HRESULT SetDriveLabel(HWND hwndOwner, PCWSTR DrivePath, PCWSTR Label);
// IShellFolder // IShellFolder
STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override; STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
STDMETHOD(EnumObjects)(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override; STDMETHOD(EnumObjects)(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override;