mirror of
https://github.com/reactos/reactos.git
synced 2025-05-01 11:39:58 +00:00
[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
This commit is contained in:
parent
f8010947fe
commit
0f5fb4785b
2 changed files with 81 additions and 60 deletions
|
@ -134,7 +134,7 @@ CFSDropTarget::~CFSDropTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
CFSDropTarget::_GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
|
CFSDropTarget::_GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut)
|
||||||
{
|
{
|
||||||
WCHAR wszLink[40];
|
WCHAR wszLink[40];
|
||||||
|
|
||||||
|
@ -549,104 +549,125 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject,
|
||||||
|
|
||||||
if (bLinking)
|
if (bLinking)
|
||||||
{
|
{
|
||||||
WCHAR wszTargetPath[MAX_PATH];
|
|
||||||
WCHAR wszPath[MAX_PATH];
|
WCHAR wszPath[MAX_PATH];
|
||||||
WCHAR wszTarget[MAX_PATH];
|
WCHAR wszTarget[MAX_PATH];
|
||||||
|
|
||||||
wcscpy(wszTargetPath, m_sPathTarget);
|
TRACE("target path = %s\n", debugstr_w(m_sPathTarget));
|
||||||
|
|
||||||
TRACE("target path = %s", debugstr_w(wszTargetPath));
|
|
||||||
|
|
||||||
/* We need to create a link for each pidl in the copied items, so step through the pidls from the clipboard */
|
/* 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++)
|
for (UINT i = 0; i < lpcida->cidl; i++)
|
||||||
{
|
{
|
||||||
//Find out which file we're copying
|
// Find out which file we're linking.
|
||||||
STRRET strFile;
|
STRRET strFile;
|
||||||
hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile);
|
hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_FORPARSING, &strFile);
|
||||||
if (FAILED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
{
|
|
||||||
ERR("Error source obtaining path");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath));
|
hr = StrRetToBufW(&strFile, apidl[i], wszPath, _countof(wszPath));
|
||||||
if (FAILED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
{
|
|
||||||
ERR("Error putting source path into buffer");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
TRACE("source path = %s", debugstr_w(wszPath));
|
|
||||||
|
|
||||||
// Creating a buffer to hold the combined path
|
TRACE("source path = %s\n", debugstr_w(wszPath));
|
||||||
WCHAR buffer_1[MAX_PATH] = L"";
|
|
||||||
WCHAR *lpStr1;
|
|
||||||
lpStr1 = buffer_1;
|
|
||||||
|
|
||||||
|
WCHAR wszDisplayName[MAX_PATH];
|
||||||
LPWSTR pwszFileName = PathFindFileNameW(wszPath);
|
LPWSTR pwszFileName = PathFindFileNameW(wszPath);
|
||||||
LPWSTR pwszExt = PathFindExtensionW(wszPath);
|
if (PathIsRootW(wszPath)) // Drive?
|
||||||
LPWSTR placementPath = PathCombineW(lpStr1, m_sPathTarget, pwszFileName);
|
|
||||||
CComPtr<IPersistFile> ppf;
|
|
||||||
|
|
||||||
//Check to see if it's already a link.
|
|
||||||
if (!wcsicmp(pwszExt, L".lnk"))
|
|
||||||
{
|
{
|
||||||
//It's a link so, we create a new one which copies the old.
|
hr = psfFrom->GetDisplayNameOf(apidl[i], SHGDN_NORMAL, &strFile);
|
||||||
if(!_GetUniqueFileName(placementPath, pwszExt, wszTarget, TRUE))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
hr = StrRetToBufW(&strFile, apidl[i], wszDisplayName, _countof(wszDisplayName));
|
||||||
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Delete a ':' in wszDisplayName.
|
||||||
|
LPWSTR pch0 = wcschr(wszDisplayName, L':');
|
||||||
|
if (pch0)
|
||||||
{
|
{
|
||||||
ERR("Error getting unique file name");
|
do
|
||||||
hr = E_FAIL;
|
{
|
||||||
break;
|
*pch0 = *(pch0 + 1);
|
||||||
}
|
++pch0;
|
||||||
hr = IShellLink_ConstructFromPath(wszPath, IID_PPV_ARG(IPersistFile, &ppf));
|
} while (*pch0);
|
||||||
if (FAILED(hr)) {
|
|
||||||
ERR("Error constructing link from file");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = ppf->Save(wszTarget, FALSE);
|
pwszFileName = wszDisplayName; // Use wszDisplayName
|
||||||
if (FAILED(hr))
|
}
|
||||||
|
else if (wszPath[0] == L':' && wszPath[1] == L':') // ::{GUID}?
|
||||||
|
{
|
||||||
|
CLSID clsid;
|
||||||
|
hr = ::CLSIDFromString(&wszPath[2], &clsid);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
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;
|
break;
|
||||||
SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//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))
|
|
||||||
{
|
|
||||||
ERR("Error creating unique file name");
|
|
||||||
hr = E_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
CComPtr<IShellLinkW> pLink;
|
CComPtr<IShellLinkW> pLink;
|
||||||
hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
|
hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellLinkW, &pLink));
|
||||||
if (FAILED(hr)) {
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
ERR("Error instantiating IShellLinkW");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR szDirPath[MAX_PATH], *pwszFile;
|
WCHAR szDirPath[MAX_PATH], *pwszFile;
|
||||||
GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile);
|
GetFullPathName(wszPath, MAX_PATH, szDirPath, &pwszFile);
|
||||||
if (pwszFile) pwszFile[0] = 0;
|
if (pwszFile)
|
||||||
|
pwszFile[0] = 0;
|
||||||
|
|
||||||
hr = pLink->SetPath(wszPath);
|
hr = pLink->SetPath(wszPath);
|
||||||
if(FAILED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
hr = pLink->SetWorkingDirectory(szDirPath);
|
hr = pLink->SetWorkingDirectory(szDirPath);
|
||||||
if(FAILED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
|
hr = pLink->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf));
|
||||||
if(FAILED(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
break;
|
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
|
else
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CFSDropTarget :
|
||||||
BOOL _QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
|
BOOL _QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
|
||||||
HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
|
HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
|
||||||
HRESULT _CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
|
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);
|
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter);
|
||||||
HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects);
|
HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects);
|
||||||
HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt);
|
HRESULT _RepositionItems(IShellFolderView *psfv, IDataObject *pDataObject, POINTL pt);
|
||||||
|
|
Loading…
Reference in a new issue