reactos/dll/shellext/sendmail/CDeskLinkDropHandler.cpp
Katayama Hirofumi MZ 004e08383a
[SENDMAIL][INCLUDE][INF] Add sendmail.dll for DeskLink (#2092)
*.DeskLink file realizes SendTo Desktop (Create shortcut) in Windows. DeskLink is implemented in the sendmail.dll module. CORE-12562
2019-11-27 19:26:49 +09:00

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;
}