mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[0.4.15][SHELL32] Allow DnD to create shortcuts across different drives (#7607)
Fixes CORE-17871 and CORE-18271.
This is a cherry pick of commit:
aebaa14
[SHELL32] Allow DnD to create shortcuts across different drives (#7607)
Co-Authored-By: Whindmar Saksit <whindsaks@proton.me>
This commit is contained in:
parent
914a10714d
commit
83a108399b
4 changed files with 49 additions and 27 deletions
|
@ -24,6 +24,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL (shell);
|
||||
|
||||
#define D_NONE DROPEFFECT_NONE
|
||||
#define D_COPY DROPEFFECT_COPY
|
||||
#define D_MOVE DROPEFFECT_MOVE
|
||||
#define D_LINK DROPEFFECT_LINK
|
||||
|
||||
static void SHELL_StripIllegalFsNameCharacters(_Inout_ LPWSTR Buf)
|
||||
{
|
||||
for (LPWSTR src = Buf, dst = src;;)
|
||||
|
@ -38,6 +43,17 @@ static void SHELL_StripIllegalFsNameCharacters(_Inout_ LPWSTR Buf)
|
|||
}
|
||||
}
|
||||
|
||||
static bool PathIsSameDrive(LPCWSTR Path1, LPCWSTR Path2)
|
||||
{
|
||||
int d1 = PathGetDriveNumberW(Path1), d2 = PathGetDriveNumberW(Path2);
|
||||
return d1 == d2 && d2 >= 0;
|
||||
}
|
||||
|
||||
static bool PathIsDriveRoot(LPCWSTR Path)
|
||||
{
|
||||
return PathIsRootW(Path) && PathGetDriveNumberW(Path) >= 0;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHELL_LimitDropEffectToItemAttributes(_In_ IDataObject *pDataObject, _Inout_ PDWORD pdwEffect)
|
||||
{
|
||||
|
@ -134,7 +150,8 @@ CFSDropTarget::CFSDropTarget():
|
|||
m_fAcceptFmt(FALSE),
|
||||
m_sPathTarget(NULL),
|
||||
m_hwndSite(NULL),
|
||||
m_grfKeyState(0)
|
||||
m_grfKeyState(0),
|
||||
m_AllowedEffects(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -147,13 +164,7 @@ HRESULT CFSDropTarget::Initialize(LPWSTR PathTarget)
|
|||
if (!m_cfShellIDList)
|
||||
return E_FAIL;
|
||||
|
||||
m_sPathTarget = (WCHAR *)SHAlloc((wcslen(PathTarget) + 1) * sizeof(WCHAR));
|
||||
if (!m_sPathTarget)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
wcscpy(m_sPathTarget, PathTarget);
|
||||
|
||||
return S_OK;
|
||||
return SHStrDupW(PathTarget, &m_sPathTarget);
|
||||
}
|
||||
|
||||
CFSDropTarget::~CFSDropTarget()
|
||||
|
@ -202,7 +213,13 @@ BOOL CFSDropTarget::_QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
|
|||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
|
||||
*pdwEffect = KeyStateToDropEffect (dwKeyState);
|
||||
*pdwEffect = KeyStateToDropEffect(dwKeyState);
|
||||
|
||||
// Transform disallowed move to a copy
|
||||
if ((*pdwEffect & D_MOVE) && (m_AllowedEffects & (D_MOVE | D_COPY)) == D_COPY)
|
||||
*pdwEffect = D_COPY;
|
||||
|
||||
*pdwEffect &= m_AllowedEffects;
|
||||
|
||||
if (*pdwEffect == DROPEFFECT_NONE)
|
||||
*pdwEffect = dwEffect;
|
||||
|
@ -320,6 +337,9 @@ HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
|
|||
{
|
||||
TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
|
||||
|
||||
const BOOL bAnyKeyMod = dwKeyState & (MK_SHIFT | MK_CONTROL);
|
||||
m_AllowedEffects = *pdwEffect;
|
||||
|
||||
if (*pdwEffect == DROPEFFECT_NONE)
|
||||
return S_OK;
|
||||
|
||||
|
@ -337,11 +357,9 @@ HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
|
|||
|
||||
m_grfKeyState = dwKeyState;
|
||||
|
||||
#define D_NONE DROPEFFECT_NONE
|
||||
#define D_COPY DROPEFFECT_COPY
|
||||
#define D_MOVE DROPEFFECT_MOVE
|
||||
#define D_LINK DROPEFFECT_LINK
|
||||
m_dwDefaultEffect = *pdwEffect;
|
||||
SHELL_LimitDropEffectToItemAttributes(pDataObject, pdwEffect);
|
||||
m_AllowedEffects = *pdwEffect;
|
||||
m_dwDefaultEffect = m_AllowedEffects;
|
||||
switch (*pdwEffect & (D_COPY | D_MOVE | D_LINK))
|
||||
{
|
||||
case D_COPY | D_MOVE:
|
||||
|
@ -378,19 +396,24 @@ HRESULT WINAPI CFSDropTarget::DragEnter(IDataObject *pDataObject,
|
|||
WCHAR wstrFirstFile[MAX_PATH];
|
||||
if (DragQueryFileW((HDROP)medium.hGlobal, 0, wstrFirstFile, _countof(wstrFirstFile)))
|
||||
{
|
||||
/* Check if the drive letter is different */
|
||||
if (wstrFirstFile[0] != m_sPathTarget[0])
|
||||
if (!PathIsSameDrive(wstrFirstFile, m_sPathTarget) && m_dwDefaultEffect != D_LINK)
|
||||
{
|
||||
m_dwDefaultEffect = DROPEFFECT_COPY;
|
||||
}
|
||||
|
||||
if (!bAnyKeyMod && PathIsDriveRoot(wstrFirstFile) && (m_AllowedEffects & DROPEFFECT_LINK))
|
||||
{
|
||||
m_dwDefaultEffect = DROPEFFECT_LINK; // Don't copy a drive by default
|
||||
}
|
||||
}
|
||||
ReleaseStgMedium(&medium);
|
||||
}
|
||||
|
||||
if (!m_fAcceptFmt)
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
m_AllowedEffects = DROPEFFECT_NONE;
|
||||
else
|
||||
*pdwEffect = m_dwDefaultEffect;
|
||||
*pdwEffect &= m_AllowedEffects;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -471,7 +494,7 @@ HRESULT WINAPI CFSDropTarget::Drop(IDataObject *pDataObject,
|
|||
data->pt = pt;
|
||||
// Need to dereference as pdweffect gets freed.
|
||||
data->pdwEffect = *pdwEffect;
|
||||
SHCreateThread(CFSDropTarget::_DoDropThreadProc, data, NULL, NULL);
|
||||
SHCreateThread(CFSDropTarget::_DoDropThreadProc, data, CTF_COINIT | CTF_PROCESS_REF, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
@ -726,7 +749,6 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject,
|
|||
|
||||
DWORD WINAPI CFSDropTarget::_DoDropThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
_DoDropData *data = static_cast<_DoDropData*>(lpParameter);
|
||||
CComPtr<IDataObject> pDataObject;
|
||||
HRESULT hr = CoGetInterfaceAndReleaseStream (data->pStream, IID_PPV_ARG(IDataObject, &pDataObject));
|
||||
|
@ -744,7 +766,6 @@ DWORD WINAPI CFSDropTarget::_DoDropThreadProc(LPVOID lpParameter)
|
|||
data->This->Release();
|
||||
//Release the parameter from the heap.
|
||||
HeapFree(GetProcessHeap(), 0, data);
|
||||
CoUninitialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class CFSDropTarget :
|
|||
HWND m_hwndSite;
|
||||
DWORD m_grfKeyState;
|
||||
DWORD m_dwDefaultEffect;
|
||||
DWORD m_AllowedEffects;
|
||||
CComPtr<IUnknown> m_site;
|
||||
|
||||
BOOL _QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
|
||||
|
|
|
@ -657,7 +657,7 @@ static const DWORD dwControlPanelAttributes =
|
|||
SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CANLINK;
|
||||
static const DWORD dwDriveAttributes =
|
||||
SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
|
||||
SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK;
|
||||
SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANCOPY;
|
||||
|
||||
CDrivesFolder::CDrivesFolder()
|
||||
{
|
||||
|
@ -711,10 +711,9 @@ HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLEST
|
|||
pdwAttributes);
|
||||
}
|
||||
|
||||
if (lpszDisplayName[0] &&
|
||||
((L'A' <= lpszDisplayName[0] && lpszDisplayName[0] <= L'Z') ||
|
||||
if (((L'A' <= lpszDisplayName[0] && lpszDisplayName[0] <= L'Z') ||
|
||||
(L'a' <= lpszDisplayName[0] && lpszDisplayName[0] <= L'z')) &&
|
||||
lpszDisplayName[1] == L':' && lpszDisplayName[2] == L'\\')
|
||||
lpszDisplayName[1] == L':' && (lpszDisplayName[2] == L'\\' || !lpszDisplayName[2]))
|
||||
{
|
||||
// "C:\..."
|
||||
WCHAR szRoot[8];
|
||||
|
@ -730,7 +729,7 @@ HRESULT WINAPI CDrivesFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLEST
|
|||
if (!pidlTemp)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (lpszDisplayName[3])
|
||||
if (lpszDisplayName[2] && lpszDisplayName[3])
|
||||
{
|
||||
CComPtr<IShellFolder> pChildFolder;
|
||||
hr = BindToObject(pidlTemp, pbc, IID_PPV_ARG(IShellFolder, &pChildFolder));
|
||||
|
|
|
@ -77,8 +77,9 @@ HRESULT WINAPI SHGetAttributesFromDataObject(IDataObject* pDataObject, DWORD dwA
|
|||
data.dwAttributes = rgfInOut & dwQueryAttributes;
|
||||
data.cItems = apidl.GetSize();
|
||||
|
||||
hr = DataObject_SetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data));
|
||||
FAILED_UNEXPECTEDLY(hr);
|
||||
HRESULT hr2;
|
||||
hr2 = DataObject_SetData(pDataObject, g_DataObjectAttributes, &data, sizeof(data));
|
||||
FAILED_UNEXPECTEDLY(hr2); // Report cache failure but don't fail the function
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue