[SENDMAIL][INCLUDE][INF] Add sendmail.dll for DeskLink (#2092)
[reactos.git] / dll / shellext / sendmail / CDeskLinkDropHandler.cpp
1 /*
2 * PROJECT: sendmail
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: DeskLink implementation
5 * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8 #include "precomp.hpp"
9
10 WINE_DEFAULT_DEBUG_CHANNEL(sendmail);
11
12 CDeskLinkDropHandler::CDeskLinkDropHandler()
13 {
14 InterlockedIncrement(&g_ModuleRefCnt);
15 }
16
17 CDeskLinkDropHandler::~CDeskLinkDropHandler()
18 {
19 InterlockedDecrement(&g_ModuleRefCnt);
20 }
21
22 // IDropTarget
23 STDMETHODIMP
24 CDeskLinkDropHandler::DragEnter(IDataObject *pDataObject, DWORD dwKeyState,
25 POINTL pt, DWORD *pdwEffect)
26 {
27 TRACE("(%p)\n", this);
28
29 *pdwEffect &= DROPEFFECT_LINK;
30
31 return S_OK;
32 }
33
34 STDMETHODIMP
35 CDeskLinkDropHandler::DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
36 {
37 TRACE("(%p)\n", this);
38
39 *pdwEffect &= DROPEFFECT_LINK;
40
41 return S_OK;
42 }
43
44 STDMETHODIMP CDeskLinkDropHandler::DragLeave()
45 {
46 TRACE("(%p)\n", this);
47 return S_OK;
48 }
49
50 STDMETHODIMP
51 CDeskLinkDropHandler::Drop(IDataObject *pDataObject, DWORD dwKeyState,
52 POINTL pt, DWORD *pdwEffect)
53 {
54 TRACE("(%p)\n", this);
55
56 if (!pDataObject)
57 {
58 ERR("pDataObject is NULL\n");
59 return E_POINTER;
60 }
61
62 FORMATETC fmt;
63 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
64 fmt.ptd = NULL;
65 fmt.dwAspect = DVASPECT_CONTENT;
66 fmt.lindex = -1;
67 fmt.tymed = TYMED_HGLOBAL;
68
69 WCHAR szDir[MAX_PATH], szDest[MAX_PATH], szSrc[MAX_PATH];
70 SHGetSpecialFolderPathW(NULL, szDir, CSIDL_DESKTOPDIRECTORY, FALSE);
71
72 CComPtr<IShellFolder> pDesktop;
73 HRESULT hr = SHGetDesktopFolder(&pDesktop);
74 if (FAILED_UNEXPECTEDLY(hr))
75 return hr;
76
77 STGMEDIUM medium;
78 hr = pDataObject->GetData(&fmt, &medium);
79 if (FAILED_UNEXPECTEDLY(hr))
80 return hr;
81
82 LPIDA pida = reinterpret_cast<LPIDA>(GlobalLock(medium.hGlobal));
83 if (!pida)
84 {
85 ERR("Error locking global\n");
86 ReleaseStgMedium(&medium);
87 return E_FAIL;
88 }
89
90 LPBYTE pb = reinterpret_cast<LPBYTE>(pida);
91 LPCITEMIDLIST pidlParent = reinterpret_cast<LPCITEMIDLIST>(pb + pida->aoffset[0]);
92 for (UINT i = 1; i <= pida->cidl; ++i)
93 {
94 LPCITEMIDLIST pidlChild = reinterpret_cast<LPCITEMIDLIST>(pb + pida->aoffset[i]);
95
96 CComHeapPtr<ITEMIDLIST> pidl(ILCombine(pidlParent, pidlChild));
97 if (!pidl)
98 {
99 ERR("Out of memory\n");
100 break;
101 }
102
103 StringCbCopyW(szDest, sizeof(szDest), szDir);
104 if (SHGetPathFromIDListW(pidl, szSrc))
105 {
106 CStringW strTitle;
107 strTitle.Format(IDS_SHORTCUT, PathFindFileNameW(szSrc));
108
109 PathAppendW(szDest, strTitle);
110 PathRemoveExtensionW(szDest);
111 StringCbCatW(szDest, sizeof(szDest), L".lnk");
112
113 hr = CreateShellLink(szDest, szSrc, NULL, NULL, NULL, NULL, -1, NULL);
114 }
115 else
116 {
117 STRRET strret;
118 hr = pDesktop->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret);
119 if (FAILED_UNEXPECTEDLY(hr))
120 break;
121
122 hr = StrRetToBufW(&strret, pidl, szSrc, _countof(szSrc));
123 if (FAILED_UNEXPECTEDLY(hr))
124 break;
125
126 CStringW strTitle;
127 strTitle.Format(IDS_SHORTCUT, szSrc);
128
129 PathAppendW(szDest, strTitle);
130 PathRemoveExtensionW(szDest);
131 StringCbCatW(szDest, sizeof(szDest), L".lnk");
132
133 hr = CreateShellLink(szDest, NULL, pidl, NULL, NULL, NULL, -1, NULL);
134 }
135
136 if (FAILED_UNEXPECTEDLY(hr))
137 break;
138 }
139
140 GlobalUnlock(medium.hGlobal);
141 ReleaseStgMedium(&medium);
142
143 return hr;
144 }
145
146 // IPersistFile
147 STDMETHODIMP CDeskLinkDropHandler::GetCurFile(LPOLESTR *ppszFileName)
148 {
149 FIXME("(%p)\n", this);
150 return E_NOTIMPL;
151 }
152
153 STDMETHODIMP CDeskLinkDropHandler::IsDirty()
154 {
155 FIXME("(%p)\n", this);
156 return E_NOTIMPL;
157 }
158
159 STDMETHODIMP CDeskLinkDropHandler::Load(LPCOLESTR pszFileName, DWORD dwMode)
160 {
161 return S_OK;
162 }
163
164 STDMETHODIMP CDeskLinkDropHandler::Save(LPCOLESTR pszFileName, BOOL fRemember)
165 {
166 FIXME("(%p)\n", this);
167 return E_NOTIMPL;
168 }
169
170 STDMETHODIMP CDeskLinkDropHandler::SaveCompleted(LPCOLESTR pszFileName)
171 {
172 FIXME("(%p)\n", this);
173 return E_NOTIMPL;
174 }
175
176 // IPersist
177 STDMETHODIMP CDeskLinkDropHandler::GetClassID(CLSID * lpClassId)
178 {
179 TRACE("(%p)\n", this);
180
181 if (!lpClassId)
182 {
183 ERR("lpClassId is NULL\n");
184 return E_POINTER;
185 }
186
187 *lpClassId = CLSID_DeskLinkDropHandler;
188
189 return S_OK;
190 }