mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 22:28:36 +00:00
![Katayama Hirofumi MZ](/assets/img/avatar_default.png)
*.DeskLink file realizes SendTo Desktop (Create shortcut) in Windows. DeskLink is implemented in the sendmail.dll module. CORE-12562
191 lines
4.5 KiB
C++
191 lines
4.5 KiB
C++
/*
|
|
* PROJECT: sendmail
|
|
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
|
* PURPOSE: DeskLink implementation
|
|
* COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
|
*/
|
|
|
|
#include "precomp.hpp"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(sendmail);
|
|
|
|
CDeskLinkDropHandler::CDeskLinkDropHandler()
|
|
{
|
|
InterlockedIncrement(&g_ModuleRefCnt);
|
|
}
|
|
|
|
CDeskLinkDropHandler::~CDeskLinkDropHandler()
|
|
{
|
|
InterlockedDecrement(&g_ModuleRefCnt);
|
|
}
|
|
|
|
// IDropTarget
|
|
STDMETHODIMP
|
|
CDeskLinkDropHandler::DragEnter(IDataObject *pDataObject, DWORD dwKeyState,
|
|
POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
TRACE("(%p)\n", this);
|
|
|
|
*pdwEffect &= DROPEFFECT_LINK;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDeskLinkDropHandler::DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
TRACE("(%p)\n", this);
|
|
|
|
*pdwEffect &= DROPEFFECT_LINK;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CDeskLinkDropHandler::DragLeave()
|
|
{
|
|
TRACE("(%p)\n", this);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDeskLinkDropHandler::Drop(IDataObject *pDataObject, DWORD dwKeyState,
|
|
POINTL pt, DWORD *pdwEffect)
|
|
{
|
|
TRACE("(%p)\n", this);
|
|
|
|
if (!pDataObject)
|
|
{
|
|
ERR("pDataObject is NULL\n");
|
|
return E_POINTER;
|
|
}
|
|
|
|
FORMATETC fmt;
|
|
fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
|
|
fmt.ptd = NULL;
|
|
fmt.dwAspect = DVASPECT_CONTENT;
|
|
fmt.lindex = -1;
|
|
fmt.tymed = TYMED_HGLOBAL;
|
|
|
|
WCHAR szDir[MAX_PATH], szDest[MAX_PATH], szSrc[MAX_PATH];
|
|
SHGetSpecialFolderPathW(NULL, szDir, CSIDL_DESKTOPDIRECTORY, FALSE);
|
|
|
|
CComPtr<IShellFolder> pDesktop;
|
|
HRESULT hr = SHGetDesktopFolder(&pDesktop);
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
return hr;
|
|
|
|
STGMEDIUM medium;
|
|
hr = pDataObject->GetData(&fmt, &medium);
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
return hr;
|
|
|
|
LPIDA pida = reinterpret_cast<LPIDA>(GlobalLock(medium.hGlobal));
|
|
if (!pida)
|
|
{
|
|
ERR("Error locking global\n");
|
|
ReleaseStgMedium(&medium);
|
|
return E_FAIL;
|
|
}
|
|
|
|
LPBYTE pb = reinterpret_cast<LPBYTE>(pida);
|
|
LPCITEMIDLIST pidlParent = reinterpret_cast<LPCITEMIDLIST>(pb + pida->aoffset[0]);
|
|
for (UINT i = 1; i <= pida->cidl; ++i)
|
|
{
|
|
LPCITEMIDLIST pidlChild = reinterpret_cast<LPCITEMIDLIST>(pb + pida->aoffset[i]);
|
|
|
|
CComHeapPtr<ITEMIDLIST> pidl(ILCombine(pidlParent, pidlChild));
|
|
if (!pidl)
|
|
{
|
|
ERR("Out of memory\n");
|
|
break;
|
|
}
|
|
|
|
StringCbCopyW(szDest, sizeof(szDest), szDir);
|
|
if (SHGetPathFromIDListW(pidl, szSrc))
|
|
{
|
|
CStringW strTitle;
|
|
strTitle.Format(IDS_SHORTCUT, PathFindFileNameW(szSrc));
|
|
|
|
PathAppendW(szDest, strTitle);
|
|
PathRemoveExtensionW(szDest);
|
|
StringCbCatW(szDest, sizeof(szDest), L".lnk");
|
|
|
|
hr = CreateShellLink(szDest, szSrc, NULL, NULL, NULL, NULL, -1, NULL);
|
|
}
|
|
else
|
|
{
|
|
STRRET strret;
|
|
hr = pDesktop->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret);
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
break;
|
|
|
|
hr = StrRetToBufW(&strret, pidl, szSrc, _countof(szSrc));
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
break;
|
|
|
|
CStringW strTitle;
|
|
strTitle.Format(IDS_SHORTCUT, szSrc);
|
|
|
|
PathAppendW(szDest, strTitle);
|
|
PathRemoveExtensionW(szDest);
|
|
StringCbCatW(szDest, sizeof(szDest), L".lnk");
|
|
|
|
hr = CreateShellLink(szDest, NULL, pidl, NULL, NULL, NULL, -1, NULL);
|
|
}
|
|
|
|
if (FAILED_UNEXPECTEDLY(hr))
|
|
break;
|
|
}
|
|
|
|
GlobalUnlock(medium.hGlobal);
|
|
ReleaseStgMedium(&medium);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IPersistFile
|
|
STDMETHODIMP CDeskLinkDropHandler::GetCurFile(LPOLESTR *ppszFileName)
|
|
{
|
|
FIXME("(%p)\n", this);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CDeskLinkDropHandler::IsDirty()
|
|
{
|
|
FIXME("(%p)\n", this);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CDeskLinkDropHandler::Load(LPCOLESTR pszFileName, DWORD dwMode)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CDeskLinkDropHandler::Save(LPCOLESTR pszFileName, BOOL fRemember)
|
|
{
|
|
FIXME("(%p)\n", this);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CDeskLinkDropHandler::SaveCompleted(LPCOLESTR pszFileName)
|
|
{
|
|
FIXME("(%p)\n", this);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IPersist
|
|
STDMETHODIMP CDeskLinkDropHandler::GetClassID(CLSID * lpClassId)
|
|
{
|
|
TRACE("(%p)\n", this);
|
|
|
|
if (!lpClassId)
|
|
{
|
|
ERR("lpClassId is NULL\n");
|
|
return E_POINTER;
|
|
}
|
|
|
|
*lpClassId = CLSID_DeskLinkDropHandler;
|
|
|
|
return S_OK;
|
|
}
|