ReactOS 0.4.15-dev-6661-gcc6e444
CCopyToMenu.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: shell32
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: CopyTo implementation
5 * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8#include "precomp.h"
9
11
12
14 m_idCmdFirst(0),
15 m_idCmdLast(0),
16 m_idCmdCopyTo(-1),
17 m_fnOldWndProc(NULL),
18 m_bIgnoreTextBoxChange(FALSE)
19{
20}
21
23{
24}
25
26static LRESULT CALLBACK
28{
30 CCopyToMenu *this_ =
31 reinterpret_cast<CCopyToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
32
33 switch (uMsg)
34 {
35 case WM_COMMAND:
36 {
37 switch (LOWORD(wParam))
38 {
40 {
41 if (HIWORD(wParam) == EN_CHANGE)
42 {
43 if (!this_->m_bIgnoreTextBoxChange)
44 {
45 // get the text
47 StrTrimW(szPath, L" \t");
48
49 // update OK button
51 SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid);
52
53 return 0;
54 }
55
56 // reset flag
58 }
59 break;
60 }
61 }
62 break;
63 }
64 }
65 return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, lParam);
66}
67
68static int CALLBACK
70{
71 CCopyToMenu *this_ =
72 reinterpret_cast<CCopyToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
73
74 switch (uMsg)
75 {
77 {
79 this_ = reinterpret_cast<CCopyToMenu *>(lpData);
80
81 // Select initial directory
83 reinterpret_cast<LPARAM>(static_cast<LPCITEMIDLIST>(this_->m_pidlFolder)));
84
85 // Set caption
87 SetWindowTextW(hwnd, strCaption);
88
89 // Set OK button text
91 SetDlgItemText(hwnd, IDOK, strCopy);
92
93 // Subclassing
94 this_->m_fnOldWndProc =
95 reinterpret_cast<WNDPROC>(
97
98 // Disable OK
100 break;
101 }
102 case BFFM_SELCHANGED:
103 {
104 if (!this_)
105 break;
106
108 LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(lParam);
109
110 szPath[0] = 0;
112
113 if (ILIsEqual(pidl, this_->m_pidlFolder))
115 else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
117 else
119
120 // the text box will be updated later soon, ignore it
122 break;
123 }
124 }
125
126 return FALSE;
127}
128
130{
131 CDataObjectHIDA pCIDA(m_pDataObject);
132 if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
133 return pCIDA.hr();
134
135 PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
136 if (!pidlParent)
137 {
138 ERR("HIDA_GetPIDLFolder failed\n");
139 return E_FAIL;
140 }
141
142 CStringW strFiles;
144 for (UINT n = 0; n < pCIDA->cidl; ++n)
145 {
146 PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, n);
147 if (!pidlRelative)
148 continue;
149
150 CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
151 if (!pidl)
152 return E_FAIL;
153
154 SHGetPathFromIDListW(pidlCombine, szPath);
155
156 if (n > 0)
157 strFiles += L'|';
158 strFiles += szPath;
159 }
160
161 strFiles += L'|'; // double null-terminated
162 strFiles.Replace(L'|', L'\0');
163
164 if (_ILIsDesktop(pidl))
166 else
168 INT cchPath = lstrlenW(szPath);
169 if (cchPath + 1 < MAX_PATH)
170 {
171 szPath[cchPath + 1] = 0; // double null-terminated
172 }
173 else
174 {
175 ERR("Too long path\n");
176 return E_FAIL;
177 }
178
179 SHFILEOPSTRUCTW op = { lpici->hwnd };
180 op.wFunc = FO_COPY;
181 op.pFrom = strFiles;
182 op.pTo = szPath;
183 op.fFlags = FOF_ALLOWUNDO;
184 int res = SHFileOperationW(&op);
185 if (res)
186 {
187 ERR("SHFileOperationW failed with 0x%x\n", res);
188 return E_FAIL;
189 }
190 return S_OK;
191}
192
194{
195 CStringW ret = L"(file)";
196
197 CDataObjectHIDA pCIDA(m_pDataObject);
198 if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
199 return ret;
200
201 PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
202 if (!pidlParent)
203 {
204 ERR("HIDA_GetPIDLFolder failed\n");
205 return ret;
206 }
207
209 PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, 0);
210 if (!pidlRelative)
211 {
212 ERR("HIDA_GetPIDLItem failed\n");
213 return ret;
214 }
215
216 CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
217
218 if (SHGetPathFromIDListW(pidlCombine, szPath))
220 else
221 ERR("Cannot get path\n");
222
223 if (pCIDA->cidl > 1)
224 ret += L" ...";
225
226 return ret;
227}
228
230{
231 WCHAR wszPath[MAX_PATH];
232 HRESULT hr = E_FAIL;
233
234 TRACE("DoCopyToFolder(%p)\n", lpici);
235
236 if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
237 {
238 ERR("SHGetPathFromIDListW failed\n");
239 return hr;
240 }
241
242 CStringW strFileTitle = DoGetFileTitle();
243 CStringW strTitle;
244 strTitle.Format(IDS_COPYTOTITLE, static_cast<LPCWSTR>(strFileTitle));
245
246 BROWSEINFOW info = { lpici->hwnd };
247 info.pidlRoot = NULL;
248 info.lpszTitle = strTitle;
251 info.lParam = reinterpret_cast<LPARAM>(this);
253 if (pidl)
254 {
255 hr = DoRealCopy(lpici, pidl);
256 }
257
258 return hr;
259}
260
263 UINT indexMenu,
264 UINT idCmdFirst,
265 UINT idCmdLast,
266 UINT uFlags)
267{
268 MENUITEMINFOW mii;
269 UINT Count = 0;
270
271 TRACE("CCopyToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
272 hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
273
274 if (uFlags & (CMF_NOVERBS | CMF_VERBSONLY))
275 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst);
276
277 m_idCmdFirst = m_idCmdLast = idCmdFirst;
278
279 // insert separator if necessary
280 ZeroMemory(&mii, sizeof(mii));
281 mii.cbSize = sizeof(mii);
282 mii.fMask = MIIM_TYPE;
283 if (GetMenuItemInfoW(hMenu, indexMenu - 1, TRUE, &mii) &&
284 mii.fType != MFT_SEPARATOR)
285 {
286 ZeroMemory(&mii, sizeof(mii));
287 mii.cbSize = sizeof(mii);
288 mii.fMask = MIIM_TYPE;
289 mii.fType = MFT_SEPARATOR;
290 if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
291 {
292 ++indexMenu;
293 ++Count;
294 }
295 }
296
297 // insert "Copy to folder..."
299 ZeroMemory(&mii, sizeof(mii));
300 mii.cbSize = sizeof(mii);
301 mii.fMask = MIIM_ID | MIIM_TYPE;
302 mii.fType = MFT_STRING;
303 mii.dwTypeData = strText.GetBuffer();
304 mii.cch = wcslen(mii.dwTypeData);
305 mii.wID = m_idCmdLast;
306 if (InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
307 {
309 ++indexMenu;
310 ++Count;
311 }
312
313 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdFirst + Count);
314}
315
318{
319 HRESULT hr = E_FAIL;
320 TRACE("CCopyToMenu::InvokeCommand(%p)\n", lpici);
321
322 if (HIWORD(lpici->lpVerb) == 0)
323 {
324 if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdCopyTo)
325 {
326 hr = DoCopyToFolder(lpici);
327 }
328 }
329 else
330 {
331 if (::lstrcmpiA(lpici->lpVerb, "copyto") == 0)
332 {
333 hr = DoCopyToFolder(lpici);
334 }
335 }
336
337 return hr;
338}
339
342 UINT uType,
343 UINT *pwReserved,
344 LPSTR pszName,
345 UINT cchMax)
346{
347 FIXME("%p %lu %u %p %p %u\n", this,
348 idCmd, uType, pwReserved, pszName, cchMax);
349
350 return E_NOTIMPL;
351}
352
355{
356 TRACE("This %p uMsg %x\n", this, uMsg);
357 return E_NOTIMPL;
358}
359
362 IDataObject *pdtobj, HKEY hkeyProgID)
363{
364 m_pidlFolder.Attach(ILClone(pidlFolder));
365 m_pDataObject = pdtobj;
366 return S_OK;
367}
368
370{
371 m_pSite = pUnkSite;
372 return S_OK;
373}
374
376{
377 if (!m_pSite)
378 return E_FAIL;
379
380 return m_pSite->QueryInterface(riid, ppvSite);
381}
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
Definition: CCopyToMenu.cpp:69
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: CCopyToMenu.cpp:27
UINT cchMax
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
int Replace(PCXSTR pszOld, PCXSTR pszNew)
Definition: cstringt.h:886
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:818
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
CComPtr< IDataObject > m_pDataObject
BOOL m_bIgnoreTextBoxChange
CComPtr< IUnknown > m_pSite
CComHeapPtr< ITEMIDLIST > m_pidlFolder
CStringW DoGetFileTitle()
virtual HRESULT WINAPI GetSite(REFIID riid, void **ppvSite)
HRESULT DoRealCopy(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl)
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
WNDPROC m_fnOldWndProc
HRESULT DoCopyToFolder(LPCMINVOKECOMMANDINFO lpici)
virtual HRESULT WINAPI Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
virtual HRESULT WINAPI SetSite(IUnknown *pUnkSite)
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
UINT uFlags
Definition: api.c:59
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI SHGetSpecialFolderPathW(HWND hwndOwner, LPWSTR szPath, int nFolder, BOOL bCreate)
Definition: shellpath.c:3061
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1723
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1869
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
unsigned int BOOL
Definition: ntddk_ex.h:94
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
LPCWSTR szPath
Definition: env.c:37
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int UINT
Definition: ndis.h:50
static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
Definition: wizard.c:583
int Count
Definition: noreturn.cpp:7
#define L(x)
Definition: ntvdm.h:50
#define LOWORD(l)
Definition: pedump.c:82
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:228
LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:703
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1298
BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:539
#define REFIID
Definition: guiddef.h:118
#define FOF_ALLOWUNDO
Definition: shellapi.h:144
#define FO_COPY
Definition: shellapi.h:134
static PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const *pida, SIZE_T i)
Definition: shellutils.h:569
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:82
static PCUIDLIST_ABSOLUTE HIDA_GetPIDLFolder(CIDA const *pida)
Definition: shellutils.h:564
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:2035
HRESULT hr
Definition: shlfolder.c:183
#define CSIDL_DESKTOPDIRECTORY
Definition: shlobj.h:2044
#define BFFM_SELCHANGED
Definition: shlobj.h:1168
#define BIF_RETURNONLYFSDIRS
Definition: shlobj.h:1148
#define BFFM_ENABLEOK
Definition: shlobj.h:1175
#define BFFM_SETSELECTION
Definition: shlobj.h:1187
#define BIF_USENEWUI
Definition: shlobj.h:1155
#define SHBrowseForFolder
Definition: shlobj.h:1184
#define BFFM_INITIALIZED
Definition: shlobj.h:1167
#define PathIsRelative
Definition: shlwapi.h:951
#define IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT
Definition: shresdef.h:421
#define IDS_COPYBUTTON
Definition: shresdef.h:331
#define IDS_COPYITEMS
Definition: shresdef.h:330
#define IDS_COPYTOMENU
Definition: shresdef.h:328
#define IDS_COPYTOTITLE
Definition: shresdef.h:329
const ITEMIDLIST_ABSOLUTE UNALIGNED * PCUIDLIST_ABSOLUTE
Definition: shtypes.idl:63
const ITEMIDLIST_RELATIVE UNALIGNED * PCUIDLIST_RELATIVE
Definition: shtypes.idl:57
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:68
#define TRACE(s)
Definition: solgame.cpp:4
LPWSTR dwTypeData
Definition: winuser.h:3259
#define GetWindowLongPtr
Definition: treelist.c:73
#define SetWindowLongPtr
Definition: treelist.c:70
#define GWLP_WNDPROC
Definition: treelist.c:66
#define GWLP_USERDATA
Definition: treelist.c:63
int32_t INT
Definition: typedefs.h:58
#define HIWORD(l)
Definition: typedefs.h:247
int ret
UINT WINAPI GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
Definition: dialog.c:2263
#define ZeroMemory
Definition: winbase.h:1700
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define MIIM_ID
Definition: winuser.h:717
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_COMMAND
Definition: winuser.h:1730
#define MFT_SEPARATOR
Definition: winuser.h:739
#define IDOK
Definition: winuser.h:824
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
BOOL WINAPI GetMenuItemInfoW(_In_ HMENU, _In_ UINT, _In_ BOOL, _Inout_ LPMENUITEMINFOW)
#define MFT_STRING
Definition: winuser.h:741
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2896
LRESULT WINAPI CallWindowProcW(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SetDlgItemText
Definition: winuser.h:5839
#define MIIM_TYPE
Definition: winuser.h:720
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
#define EN_CHANGE
Definition: winuser.h:2012
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185