https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0f5fb4785b0dec64bef15413d0e8bd18b2844901

commit 0f5fb4785b0dec64bef15413d0e8bd18b2844901
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Thu Nov 18 17:11:24 2021 +0900
Commit:     GitHub <[email protected]>
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);

Reply via email to