From 56e7afe56c82d211fe45a2424fd36eafa6926631 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Fri, 21 Mar 2025 13:51:45 +0100 Subject: [PATCH] [SHDOCVW][SHELL32] Rename RegItem to empty name must reset the name to the default (#7794) CORE-18839 --- dll/win32/shdocvw/CExplorerBand.cpp | 2 +- dll/win32/shdocvw/CFavBand.cpp | 2 +- dll/win32/shdocvw/CNSCBand.cpp | 138 ++++++++++++++++----- dll/win32/shdocvw/CNSCBand.h | 7 +- dll/win32/shell32/CDefView.cpp | 72 ++++++----- dll/win32/shell32/folders/CDesktopFolder.h | 2 +- dll/win32/shell32/folders/CRegFolder.cpp | 30 ++--- dll/win32/shell32/shell32.spec | 1 + dll/win32/shell32/shfldr.h | 8 ++ dll/win32/shell32/shlfolder.cpp | 12 ++ dll/win32/shell32/wine/pidl.c | 11 +- 11 files changed, 201 insertions(+), 84 deletions(-) diff --git a/dll/win32/shdocvw/CExplorerBand.cpp b/dll/win32/shdocvw/CExplorerBand.cpp index aa70c06c5c2..6ac5f14ae61 100644 --- a/dll/win32/shdocvw/CExplorerBand.cpp +++ b/dll/win32/shdocvw/CExplorerBand.cpp @@ -235,7 +235,7 @@ CExplorerBand::_NavigateToPIDL( HTREEITEM hParent = NULL, tmp; while (TRUE) { - CItemData *pItemData = GetItemData(hItem); + CItemData *pItemData = _GetItemData(hItem); if (!pItemData) { ERR("Something has gone wrong, no data associated to node\n"); diff --git a/dll/win32/shdocvw/CFavBand.cpp b/dll/win32/shdocvw/CFavBand.cpp index b79f2e27be2..de8938e8b86 100644 --- a/dll/win32/shdocvw/CFavBand.cpp +++ b/dll/win32/shdocvw/CFavBand.cpp @@ -146,7 +146,7 @@ STDMETHODIMP CFavBand::OnSelectionChanged(_In_ PCIDLIST_ABSOLUTE pidl) if (attrs & SFGAO_FOLDER) { HTREEITEM hItem = TreeView_GetSelection(m_hwndTreeView); - CItemData *pItemData = GetItemData(hItem); + CItemData *pItemData = _GetItemData(hItem); if (pItemData && !pItemData->expanded) { _InsertSubitems(hItem, pItemData->absolutePidl); diff --git a/dll/win32/shdocvw/CNSCBand.cpp b/dll/win32/shdocvw/CNSCBand.cpp index 5e5894d84ed..636425e5433 100644 --- a/dll/win32/shdocvw/CNSCBand.cpp +++ b/dll/win32/shdocvw/CNSCBand.cpp @@ -99,7 +99,7 @@ VOID CNSCBand::OnFinalMessage(HWND) // *** helper methods *** -CNSCBand::CItemData* CNSCBand::GetItemData(_In_ HTREEITEM hItem) +CNSCBand::CItemData* CNSCBand::_GetItemData(_In_ HTREEITEM hItem) { if (hItem == TVI_ROOT) return NULL; @@ -111,6 +111,39 @@ CNSCBand::CItemData* CNSCBand::GetItemData(_In_ HTREEITEM hItem) return reinterpret_cast(tvItem.lParam); } +CNSCBand::CItemData* CNSCBand::_GetItemData(_In_ UINT ItemSpec) +{ + HTREEITEM hItem = m_hwndTreeView.GetNextItem(NULL, ItemSpec); + return hItem ? _GetItemData(hItem) : NULL; +} + +SFGAOF CNSCBand::_GetAttributesOfItem(_In_ CItemData *pData, _In_ SFGAOF Query) +{ + if (!pData) + return 0; + CComPtr pFolder; + LPCITEMIDLIST pidlChild; + HRESULT hr = SHBindToParent(pData->absolutePidl, IID_PPV_ARG(IShellFolder, &pFolder), &pidlChild); + if (FAILED_UNEXPECTEDLY(hr)) + return 0; + SFGAOF Attributes = Query; + if (FAILED_UNEXPECTEDLY(hr = pFolder->GetAttributesOf(1, &pidlChild, &Attributes))) + return 0; + return Attributes & Query; +} + +HRESULT CNSCBand::_GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name) +{ + STRRET strret; + HRESULT hr = pSF->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + hr = StrRetToBufW(&strret, pidl, Name, MAX_PATH); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + return hr; +} + static HRESULT SHDOCVW_GetCurrentLocationFromView(_In_ IShellView& View, _In_ PIDLIST_ABSOLUTE *ppidl) { @@ -260,7 +293,7 @@ CNSCBand::_IsTreeItemInEnum( _In_ HTREEITEM hItem, _In_ IEnumIDList *pEnum) { - CItemData* pItemData = GetItemData(hItem); + CItemData* pItemData = _GetItemData(hItem); if (!pItemData) return FALSE; @@ -286,7 +319,7 @@ CNSCBand::_TreeItemHasThisChild( for (hItem = TreeView_GetChild(m_hwndTreeView, hItem); hItem; hItem = TreeView_GetNextSibling(m_hwndTreeView, hItem)) { - CItemData* pItemData = GetItemData(hItem); + CItemData* pItemData = _GetItemData(hItem); if (ILIsEqual(pItemData->relativePidl, pidlChild)) return TRUE; } @@ -316,7 +349,7 @@ CNSCBand::_GetItemEnum( } else { - CItemData* pItemData = GetItemData(hItem); + CItemData* pItemData = _GetItemData(hItem); if (!pItemData && hItem == TVI_ROOT && !_WantsRootItem()) hr = psfDesktop->BindToObject(m_pidlRoot, NULL, IID_PPV_ARG(IShellFolder, ppFolder)); else @@ -358,7 +391,7 @@ void CNSCBand::_RefreshRecurse(_In_ HTREEITEM hTarget) pEnum = NULL; hrEnum = _GetItemEnum(pEnum, hTarget); - CItemData* pItemData = ((hTarget == TVI_ROOT) ? NULL : GetItemData(hTarget)); + CItemData* pItemData = ((hTarget == TVI_ROOT) ? NULL : _GetItemData(hTarget)); // Insert new items and update items if (SUCCEEDED(hrEnum)) @@ -461,19 +494,12 @@ CNSCBand::_InsertItem( if (FAILED_UNEXPECTEDLY(hr)) return NULL; - /* Get the name of the node */ WCHAR wszDisplayName[MAX_PATH]; - STRRET strret; - hr = psfParent->GetDisplayNameOf(pEltRelative, SHGDN_INFOLDER, &strret); - if (FAILED_UNEXPECTEDLY(hr)) + if (FAILED_UNEXPECTEDLY(hr = _GetNameOfItem(psfParent, pEltRelative, wszDisplayName))) return NULL; - hr = StrRetToBufW(&strret, pEltRelative, wszDisplayName, MAX_PATH); - if (FAILED_UNEXPECTEDLY(hr)) - return NULL; - - /* Get the icon of the node */ - INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, NULL); + INT iSelIcon = -1; + INT iIcon = SHMapPIDLToSystemImageListIndex(psfParent, pEltRelative, &iSelIcon); CItemData* pChildInfo = new CItemData; if (!pChildInfo) @@ -489,7 +515,8 @@ CNSCBand::_InsertItem( tvInsert.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN; tvInsert.item.cchTextMax = MAX_PATH; tvInsert.item.pszText = wszDisplayName; - tvInsert.item.iImage = tvInsert.item.iSelectedImage = iIcon; + tvInsert.item.iImage = iIcon; + tvInsert.item.iSelectedImage = iSelIcon >= 0 ? iSelIcon : iIcon; tvInsert.item.lParam = (LPARAM)pChildInfo; if (!(attrs & SFGAO_STREAM) && (attrs & SFGAO_HASSUBFOLDER)) @@ -684,7 +711,7 @@ BOOL CNSCBand::OnTreeItemExpanding(_In_ LPNMTREEVIEW pnmtv) if (pnmtv->action == TVE_EXPAND) { // Grab our directory PIDL - pItemData = GetItemData(pnmtv->itemNew.hItem); + pItemData = _GetItemData(pnmtv->itemNew.hItem); // We have it, let's try if (pItemData && !pItemData->expanded) { @@ -713,7 +740,7 @@ BOOL CNSCBand::OnTreeItemDeleted(_In_ LPNMTREEVIEW pnmtv) TreeView_SelectItem(m_hwndTreeView, hParent); /* Destroy memory associated to our node */ - CItemData* pItemData = GetItemData(hItem); + CItemData* pItemData = _GetItemData(hItem); if (!pItemData) return FALSE; @@ -727,14 +754,14 @@ void CNSCBand::_OnSelectionChanged(_In_ LPNMTREEVIEW pnmtv) HTREEITEM hItem = pnmtv->itemNew.hItem; if (!hItem) return; - CItemData* pItemData = GetItemData(hItem); + CItemData* pItemData = _GetItemData(hItem); if (pItemData) OnSelectionChanged(pItemData->absolutePidl); } void CNSCBand::OnTreeItemDragging(_In_ LPNMTREEVIEW pnmtv, _In_ BOOL isRightClick) { - CItemData* pItemData = GetItemData(pnmtv->itemNew.hItem); + CItemData* pItemData = _GetItemData(pnmtv->itemNew.hItem); if (!pItemData) return; @@ -772,7 +799,7 @@ LRESULT CNSCBand::OnBeginLabelEdit(_In_ LPNMTVDISPINFO dispInfo) LPCITEMIDLIST pChild; HRESULT hr; - CItemData *info = GetItemData(dispInfo->item.hItem); + CItemData *info = _GetItemData(dispInfo->item.hItem); if (!info) return FALSE; @@ -791,7 +818,7 @@ LRESULT CNSCBand::OnBeginLabelEdit(_In_ LPNMTVDISPINFO dispInfo) return TRUE; } -HRESULT CNSCBand::_UpdateBrowser(LPCITEMIDLIST pidlGoto) +HRESULT CNSCBand::_UpdateBrowser(LPCITEMIDLIST pidlGoto, BOOL IgnoreSelfNavigation) { CComPtr pBrowserService; HRESULT hr = IUnknown_QueryService(m_pSite, SID_STopLevelBrowser, @@ -799,6 +826,17 @@ HRESULT CNSCBand::_UpdateBrowser(LPCITEMIDLIST pidlGoto) if (FAILED_UNEXPECTEDLY(hr)) return hr; + if (_IsCurrentLocation(pidlGoto) == S_OK) // Don't add duplicates to the travel log + { + if (IgnoreSelfNavigation) + return S_FALSE; + + CComPtr psv; + if (SUCCEEDED(hr = pBrowserService->QueryActiveShellView(&psv))) + hr = psv->Refresh(); + if (SUCCEEDED(hr)) + return hr; + } hr = pBrowserService->BrowseObject(pidlGoto, SBSP_SAMEBROWSER | SBSP_ABSOLUTE); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -808,8 +846,9 @@ HRESULT CNSCBand::_UpdateBrowser(LPCITEMIDLIST pidlGoto) LRESULT CNSCBand::OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo) { - CItemData *info = GetItemData(dispInfo->item.hItem); + CItemData *info = _GetItemData(dispInfo->item.hItem); HRESULT hr; + BOOL AllowTreeSetNewName = TRUE; m_isEditing = FALSE; if (m_oldSelected) @@ -847,7 +886,19 @@ LRESULT CNSCBand::OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo) CComHeapPtr pidlNewAbs(ILCombine(pidlParent, pidlNew)); if (RenamedCurrent) { - _UpdateBrowser(pidlNewAbs); + // Get the new item name from the folder because RegItems can be renamed to their + // default name by the folder (which is not the string we have in NMTVDISPINFO). + WCHAR wszDisplayName[MAX_PATH]; + if (SUCCEEDED(_GetNameOfItem(pParent, pidlNew, wszDisplayName))) + { + TVITEMW tvi; + tvi.mask = TVIF_TEXT; + tvi.hItem = dispInfo->item.hItem; + tvi.pszText = wszDisplayName; + AllowTreeSetNewName = !m_hwndTreeView.SetItem(&tvi); + } + + _UpdateBrowser(pidlNewAbs, TRUE); } else { @@ -855,7 +906,7 @@ LRESULT CNSCBand::OnEndLabelEdit(_In_ LPNMTVDISPINFO dispInfo) SHChangeNotify(SHCNE_RENAMEFOLDER, SHCNF_IDLIST, info->absolutePidl, pidlNewAbs); } - return TRUE; + return AllowTreeSetNewName; } return FALSE; @@ -961,7 +1012,7 @@ LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b ClientToScreen(&pt); } - CItemData *info = GetItemData(hItem); + CItemData *info = _GetItemData(hItem); if (!info) { ERR("No node data, something has gone wrong\n"); @@ -1246,14 +1297,45 @@ STDMETHODIMP CNSCBand::HasFocusIO() STDMETHODIMP CNSCBand::TranslateAcceleratorIO(LPMSG lpMsg) { + if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_F2 && !m_isEditing) + { + if (HTREEITEM hItem = m_hwndTreeView.GetNextItem(NULL, TVGN_CARET)) + { + if (_GetAttributesOfItem(_GetItemData(hItem), SFGAO_CANRENAME)) + { + m_hwndTreeView.SetFocus(); + m_hwndTreeView.EditLabel(hItem); + return S_OK; + } + } + } + + if (lpMsg->message == WM_SYSKEYDOWN && lpMsg->wParam == VK_RETURN && !m_isEditing) + { + CItemData *pItem = _GetItemData(TVGN_CARET); + if (pItem && _GetAttributesOfItem(pItem, SFGAO_HASPROPSHEET)) + { + SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_INVOKEIDLIST, m_hwndTreeView }; + sei.lpVerb = L"properties"; + sei.lpIDList = pItem->absolutePidl; + sei.nShow = SW_SHOW; + ShellExecuteExW(&sei); + return S_OK; + } + else + { + MessageBeep(0xFFFFFFFF); + } + } + if (lpMsg->hwnd == m_hWnd || (m_isEditing && IsChild(lpMsg->hwnd))) { + // TODO: Why is it doing this for m_hWnd for all messages?! TranslateMessage(lpMsg); DispatchMessage(lpMsg); return S_OK; } - return S_FALSE; } @@ -1413,7 +1495,7 @@ STDMETHODIMP CNSCBand::DragOver(DWORD glfKeyState, POINTL pt, DWORD *pdwEffect) if (info.hItem != m_childTargetNode) { - CItemData *pItemData = GetItemData(info.hItem); + CItemData *pItemData = _GetItemData(info.hItem); if (!pItemData) return E_FAIL; diff --git a/dll/win32/shdocvw/CNSCBand.h b/dll/win32/shdocvw/CNSCBand.h index f6c06afeb98..52efb83efb9 100644 --- a/dll/win32/shdocvw/CNSCBand.h +++ b/dll/win32/shdocvw/CNSCBand.h @@ -41,7 +41,10 @@ public: CComHeapPtr relativePidl; BOOL expanded = FALSE; }; - CItemData* GetItemData(_In_ HTREEITEM hItem); + CItemData* _GetItemData(_In_ HTREEITEM hItem); + CItemData* _GetItemData(_In_ UINT ItemSpec = TVGN_CARET); + SFGAOF _GetAttributesOfItem(_In_ CItemData *pData, _In_ SFGAOF Query); + HRESULT _GetNameOfItem(IShellFolder *pSF, PCUITEMID_CHILD pidl, PWSTR Name); // *** IOleWindow methods *** STDMETHODIMP GetWindow(HWND *lphwnd) override; @@ -189,7 +192,7 @@ protected: _In_ LPCITEMIDLIST pEltRelative, _In_ BOOL bSort); BOOL _InsertSubitems(HTREEITEM hItem, LPCITEMIDLIST entry); - HRESULT _UpdateBrowser(LPCITEMIDLIST pidlGoto); + HRESULT _UpdateBrowser(LPCITEMIDLIST pidlGoto, BOOL IgnoreSelfNavigation = FALSE); HRESULT _GetCurrentLocation(_Out_ PIDLIST_ABSOLUTE *ppidl); HRESULT _IsCurrentLocation(_In_ PCIDLIST_ABSOLUTE pidl); void _Refresh(); diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index 60301182694..0833e5c38fc 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -324,7 +324,8 @@ public: int LV_AddItem(PCUITEMID_CHILD pidl); BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl); BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew); - BOOLEAN LV_UpdateItem(PCUITEMID_CHILD pidl); + BOOL LV_UpdateItem(INT nItem, PCUITEMID_CHILD pidl); + BOOL LV_UpdateItem(PCUITEMID_CHILD pidl); void LV_RefreshIcon(INT iItem); void LV_RefreshIcons(); static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); @@ -1434,18 +1435,11 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew return FALSE; } -BOOLEAN CDefView::LV_UpdateItem(PCUITEMID_CHILD pidl) +BOOL CDefView::LV_UpdateItem(INT nItem, PCUITEMID_CHILD pidl) { - int nItem; + BOOL bResult = FALSE; LVITEMW lvItem; - - TRACE("(%p)(pidl=%p)\n", this, pidl); - - ASSERT(m_ListView); - - nItem = LV_FindItemByPidl(pidl); - - if (-1 != nItem) + if (nItem >= 0) { _DoFolderViewCB(SFVM_UPDATINGOBJECT, nItem, (LPARAM)pidl); @@ -1459,13 +1453,20 @@ BOOLEAN CDefView::LV_UpdateItem(PCUITEMID_CHILD pidl) PCUITEMID_CHILD pidlOld = _PidlByItem(nItem); if (pidlOld && (lvItem.lParam = reinterpret_cast(ILClone(pidl))) != NULL) lvItem.mask |= LVIF_PARAM; - if (m_ListView.SetItem(&lvItem) && lvItem.lParam && pidlOld) + bResult = m_ListView.SetItem(&lvItem); + if (bResult && lvItem.lParam && pidlOld) ILFree(const_cast(pidlOld)); for (UINT i = 0; m_ListView.SetItemText(nItem, i, LPSTR_TEXTCALLBACK); ++i) {} // Update all columns - return TRUE; } + return bResult; +} - return FALSE; +BOOL CDefView::LV_UpdateItem(PCUITEMID_CHILD pidl) +{ + TRACE("(%p)(pidl=%p)\n", this, pidl); + ASSERT(m_ListView); + INT nItem = LV_FindItemByPidl(pidl); + return nItem >= 0 ? LV_UpdateItem(nItem, pidl) : FALSE; } void CDefView::LV_RefreshIcon(INT iItem) @@ -2824,29 +2825,32 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl { TRACE("-- LVN_ENDLABELEDITW %p\n", this); m_isEditing = FALSE; + if (!lpdi->item.pszText) + return TRUE; - if (lpdi->item.pszText) + pidl = _PidlByItem(lpdi->item); + // We have to copy the old PIDL because SetNameOf might generate a SHCNE_UPDATEITEM + // and that notification can cause us to call LV_UpdateItem and free the old PIDL too soon. + CComHeapPtr pidlOld(ILClone(pidl)); + if (!pidlOld) { - HRESULT hr; - LVITEMW lvItem; - - pidl = _PidlByItem(lpdi->item); - PITEMID_CHILD pidlNew = NULL; - hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew); - - if (SUCCEEDED(hr) && pidlNew) - { - lvItem.mask = LVIF_PARAM|LVIF_IMAGE; - lvItem.iItem = lpdi->item.iItem; - lvItem.iSubItem = 0; - lvItem.lParam = reinterpret_cast(pidlNew); - lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); - m_ListView.SetItem(&lvItem); - m_ListView.Update(lpdi->item.iItem); - return TRUE; - } + SHELL_ErrorBox(lpdi->hdr.hwndFrom, E_OUTOFMEMORY); + return FALSE; + } + PITEMID_CHILD pidlNew = NULL; + HRESULT hr = m_pSFParent->SetNameOf(0, pidlOld, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew); + if (SUCCEEDED(hr) && pidlNew) + { + int iNew = LV_FindItemByPidl(pidlNew); + if (iNew != lpdi->item.iItem && iNew >= 0) + ILFree(pidlNew);// A SHCNE has updated the item already + else if (!LV_UpdateItem(lpdi->item.iItem, pidlNew)) + ILFree(pidlNew); + } + else + { + ::PostMessageW(m_ListView, LVM_EDITLABEL, lpdi->item.iItem, 0); // Renaming failed, let the user try again } - return FALSE; } default: diff --git a/dll/win32/shell32/folders/CDesktopFolder.h b/dll/win32/shell32/folders/CDesktopFolder.h index 0f8ea5a35a2..b749d7a00ee 100644 --- a/dll/win32/shell32/folders/CDesktopFolder.h +++ b/dll/win32/shell32/folders/CDesktopFolder.h @@ -125,7 +125,7 @@ class CDesktopFolder : } if (ppwszInvalidChars) { - SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars); + return SHStrDupW(INVALID_FILETITLE_CHARACTERSW, ppwszInvalidChars); } return S_OK; } diff --git a/dll/win32/shell32/folders/CRegFolder.cpp b/dll/win32/shell32/folders/CRegFolder.cpp index ece1845838d..efaf4711f86 100644 --- a/dll/win32/shell32/folders/CRegFolder.cpp +++ b/dll/win32/shell32/folders/CRegFolder.cpp @@ -755,33 +755,35 @@ HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, HRESULT WINAPI CRegFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */ LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) { - GUID const *clsid = _ILGetGUIDPointer (pidl); - LPOLESTR pStr; - HRESULT hr; + GUID const *clsid = IsRegItem(pidl); WCHAR szName[100]; + if (!lpName || (*lpName && IsIllegalFsFileName(lpName))) // Note: Must allow empty name + return E_INVALIDARG; + if (!clsid) { ERR("Pidl is not reg item!\n"); return E_FAIL; } + FormatGUIDKey(szName, _countof(szName), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", clsid); - hr = StringFromCLSID(*clsid, &pStr); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr); - + BOOL bEmpty = StrIsNullOrEmpty(lpName); // Empty resets to the default name DWORD cbData = (wcslen(lpName) + 1) * sizeof(WCHAR); - LONG res = SHSetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, lpName, cbData); - - CoTaskMemFree(pStr); + LONG res = bEmpty ? SHDeleteValueW(HKEY_CURRENT_USER, szName, NULL) + : SHSetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, lpName, cbData); if (res == ERROR_SUCCESS) { - return pPidlOut ? SHILClone(pidl, pPidlOut) : S_OK; + HRESULT hr = pPidlOut ? SHILClone(pidl, pPidlOut) : S_OK; // Copy the PIDL before SHChangeNotify + PIDLIST_ABSOLUTE pidlAbs; + if (SUCCEEDED(SHELL_CreateAbsolutePidl(m_pOuterFolder, pidl, &pidlAbs))) + { + SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_IDLIST, pidlAbs, NULL); + ILFree(pidlAbs); + } + return hr; } - return E_FAIL; } diff --git a/dll/win32/shell32/shell32.spec b/dll/win32/shell32/shell32.spec index 2784c946de8..3cc3e0d97f8 100644 --- a/dll/win32/shell32/shell32.spec +++ b/dll/win32/shell32/shell32.spec @@ -307,6 +307,7 @@ 307 stdcall SHGetFolderPathW(long long long long ptr) 308 stdcall SHGetIconOverlayIndexA(str long) 309 stdcall SHGetIconOverlayIndexW(wstr long) +@ stdcall -version=0x600+ SHGetIDListFromObject(ptr ptr) 310 stdcall SHGetInstanceExplorer(long) 311 stdcall SHGetMalloc(ptr) 312 stdcall SHGetNewLinkInfo(str str ptr long long) SHGetNewLinkInfoA diff --git a/dll/win32/shell32/shfldr.h b/dll/win32/shell32/shfldr.h index b9cd4012864..2ab941e494c 100644 --- a/dll/win32/shell32/shfldr.h +++ b/dll/win32/shell32/shfldr.h @@ -94,6 +94,9 @@ SHELL_GetDefaultFolderEnumSHCONTF(); BOOL SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGAOF Query, SHCONTF Flags); +HRESULT +SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl); + HRESULT Shell_NextElement( _Inout_ LPWSTR *ppch, @@ -154,6 +157,11 @@ static __inline int SHELL32_GUIDToStringW (REFGUID guid, LPWSTR str) void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags); BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath); +static inline BOOL IsIllegalFsFileName(PCWSTR Name) +{ + return StrIsNullOrEmpty(Name) || StrPBrkW(Name, INVALID_FILETITLE_CHARACTERSW); +} + void CloseRegKeyArray(HKEY* array, UINT cKeys); LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys); LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys); diff --git a/dll/win32/shell32/shlfolder.cpp b/dll/win32/shell32/shlfolder.cpp index c6f28b80a0c..268eadb238a 100644 --- a/dll/win32/shell32/shlfolder.cpp +++ b/dll/win32/shell32/shlfolder.cpp @@ -54,6 +54,18 @@ BOOL SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGA return TRUE; } +HRESULT SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl) +{ + PIDLIST_ABSOLUTE pidlFolder; + HRESULT hr = SHGetIDListFromObject(pSF, &pidlFolder); + if (SUCCEEDED(hr)) + { + hr = SHILCombine(pidlFolder, pidlChild, ppPidl); + ILFree(pidlFolder); + } + return hr; +} + HRESULT Shell_NextElement( _Inout_ LPWSTR *ppch, diff --git a/dll/win32/shell32/wine/pidl.c b/dll/win32/shell32/wine/pidl.c index 94d9a22387a..576a623c545 100644 --- a/dll/win32/shell32/wine/pidl.c +++ b/dll/win32/shell32/wine/pidl.c @@ -1623,7 +1623,14 @@ HRESULT WINAPI SHGetNameFromIDList(PCIDLIST_ABSOLUTE pidl, SIGDN sigdnName, PWST return ret; } -#ifndef __REACTOS__ +/************************************************************************* + * SHGetItemFromDataObject [SHELL32.@] + */ +HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj, DATAOBJ_GET_ITEM_FLAGS dwFlags, + REFIID riid, void **ppv) +{ + return E_NOTIMPL; // FIXME +} /************************************************************************* * SHGetIDListFromObject [SHELL32.@] @@ -1701,8 +1708,6 @@ HRESULT WINAPI SHGetIDListFromObject(IUnknown *punk, PIDLIST_ABSOLUTE *ppidl) return ret; } -#endif /* !__REACTOS__ */ - /************************************************************************** * * internal functions