https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0f5fb4785b0dec64bef15…
commit 0f5fb4785b0dec64bef15413d0e8bd18b2844901
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Nov 18 17:11:24 2021 +0900
Commit: GitHub <noreply(a)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);