https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0f5fb4785b0dec64bef154...
commit 0f5fb4785b0dec64bef15413d0e8bd18b2844901 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Thu Nov 18 17:11:24 2021 +0900 Commit: GitHub noreply@github.com CommitDate: Thu Nov 18 17:11:24 2021 +0900
[SHELL32] Drop a shortcut of the drive (#4072)
- If the Right-dropped item was a drive, then get the display name of the drive and use it. - Use FAILED_UNEXPECTEDLY instead of FAILED macro. - Accept ::{GUID}. CORE-17813 --- dll/win32/shell32/droptargets/CFSDropTarget.cpp | 135 ++++++++++++++---------- dll/win32/shell32/droptargets/CFSDropTarget.h | 2 +- 2 files changed, 79 insertions(+), 58 deletions(-)
diff --git a/dll/win32/shell32/droptargets/CFSDropTarget.cpp b/dll/win32/shell32/droptargets/CFSDropTarget.cpp index 2660ff84785..14d1d20a67d 100644 --- a/dll/win32/shell32/droptargets/CFSDropTarget.cpp +++ b/dll/win32/shell32/droptargets/CFSDropTarget.cpp @@ -134,7 +134,7 @@ CFSDropTarget::~CFSDropTarget() }
BOOL -CFSDropTarget::_GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut) +CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut) { WCHAR wszLink[40];
@@ -549,104 +549,125 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject,
if (bLinking) { - WCHAR wszTargetPath[MAX_PATH]; WCHAR wszPath[MAX_PATH]; WCHAR wszTarget[MAX_PATH];
- wcscpy(wszTargetPath, m_sPathTarget); - - TRACE("target path = %s", debugstr_w(wszTargetPath)); + TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
/* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */ for (UINT i = 0; i < lpcida->cidl; i++) { - //Find out which file we're copying + // Find out which file we're linking. STRRET strFile; hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile); - if (FAILED(hr)) - { - ERR("Error source obtaining path"); + if (FAILED_UNEXPECTEDLY(hr)) break; - }
hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath)); - if (FAILED(hr)) - { - ERR("Error putting source path into buffer"); + if (FAILED_UNEXPECTEDLY(hr)) break; - } - TRACE("source path = %s", debugstr_w(wszPath));
- // Creating a buffer to hold the combined path - WCHAR buffer_1[MAX_PATH] = L""; - WCHAR *lpStr1; - lpStr1 = buffer_1; + TRACE("source path = %s\n", debugstr_w(wszPath));
+ WCHAR wszDisplayName[MAX_PATH]; LPWSTR pwszFileName = PathFindFileNameW(wszPath); - LPWSTR pwszExt = PathFindExtensionW(wszPath); - LPWSTR placementPath = PathCombineW(lpStr1, m_sPathTarget, pwszFileName); - CComPtr<IPersistFile> ppf; - - //Check to see if it's already a link. - if (!wcsicmp(pwszExt, L".lnk")) + if (PathIsRootW(wszPath)) // Drive? { - //It's a link so, we create a new one which copies the old. - if(!_GetUniqueFileName(placementPath, pwszExt, wszTarget, TRUE)) - { - ERR("Error getting unique file name"); - hr = E_FAIL; + hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_NORMAL, &strFile); + if (FAILED_UNEXPECTEDLY(hr)) break; - } - hr = IShellLink_ConstructFromPath(wszPath, IID_PPV_ARG(IPersistFile, &ppf)); - if (FAILED(hr)) { - ERR("Error constructing link from file"); + + hr = StrRetToBufW(&strFile, apidl[i], wszDisplayName, _countof(wszDisplayName)); + if (FAILED_UNEXPECTEDLY(hr)) break; + + // Delete a ':' in wszDisplayName. + LPWSTR pch0 = wcschr(wszDisplayName, L':'); + if (pch0) + { + do + { + *pch0 = *(pch0 + 1); + ++pch0; + } while (*pch0); }
- hr = ppf->Save(wszTarget, FALSE); - if (FAILED(hr)) - break; - SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); + pwszFileName = wszDisplayName; // Use wszDisplayName } - else + else if (wszPath[0] == L':' && wszPath[1] == L':') // ::{GUID}? { - //It's not a link, so build a new link using the creator class and fill it in. - //Create a file name for the link - if (!_GetUniqueFileName(placementPath, L".lnk", wszTarget, TRUE)) + CLSID clsid; + hr = ::CLSIDFromString(&wszPath[2], &clsid); + if (SUCCEEDED(hr)) { - ERR("Error creating unique file name"); - hr = E_FAIL; - break; + LPITEMIDLIST pidl = ILCreateFromPathW(wszPath); + if (pidl) + { + SHFILEINFOW fi = { NULL }; + SHGetFileInfoW((LPCWSTR)pidl, 0, &fi, sizeof(fi), + SHGFI_DISPLAYNAME | SHGFI_PIDL); + if (fi.szDisplayName[0]) + { + lstrcpynW(wszDisplayName, fi.szDisplayName, _countof(wszDisplayName)); + pwszFileName = wszDisplayName; // Use wszDisplayName + } + ILFree(pidl); + } } + }
+ // Creating a buffer to hold the combined path. + WCHAR wszCombined[MAX_PATH]; + PathCombineW(wszCombined, m_sPathTarget, pwszFileName); + + // Check to see if the source is a link + BOOL fSourceIsLink = FALSE; + if (!wcsicmp(PathFindExtensionW(wszPath), L".lnk")) + { + fSourceIsLink = TRUE; + PathRemoveExtensionW(wszCombined); + } + + // Create a pathname to save the new link. + _GetUniqueFileName(wszCombined, L".lnk", wszTarget, TRUE); + + CComPtr<IPersistFile> ppf; + if (fSourceIsLink) + { + hr = IShellLink_ConstructFromPath(wszPath, IID_PPV_ARG(IPersistFile, &ppf)); + if (FAILED_UNEXPECTEDLY(hr)) + break; + } + else + { CComPtr<IShellLinkW> pLink; hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink)); - if (FAILED(hr)) { - ERR("Error instantiating IShellLinkW"); + if (FAILED_UNEXPECTEDLY(hr)) break; - }
WCHAR szDirPath[MAX_PATH], *pwszFile; GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile); - if (pwszFile) pwszFile[0] = 0; + if (pwszFile) + pwszFile[0] = 0;
hr = pLink->SetPath(wszPath); - if(FAILED(hr)) + if (FAILED_UNEXPECTEDLY(hr)) break;
hr = pLink->SetWorkingDirectory(szDirPath); - if(FAILED(hr)) + if (FAILED_UNEXPECTEDLY(hr)) break;
hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf)); - if(FAILED(hr)) + if (FAILED_UNEXPECTEDLY(hr)) break; - - hr = ppf->Save(wszTarget, TRUE); - if (FAILED(hr)) - break; - SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } + + hr = ppf->Save(wszTarget, !fSourceIsLink); + if (FAILED_UNEXPECTEDLY(hr)) + break; + + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } } else diff --git a/dll/win32/shell32/droptargets/CFSDropTarget.h b/dll/win32/shell32/droptargets/CFSDropTarget.h index 3da45bae68d..6d0cd9691cd 100644 --- a/dll/win32/shell32/droptargets/CFSDropTarget.h +++ b/dll/win32/shell32/droptargets/CFSDropTarget.h @@ -40,7 +40,7 @@ class CFSDropTarget : BOOL _QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect); HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); HRESULT _CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy); - BOOL _GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut); + BOOL _GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut); static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter); HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects); HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt);