ReactOS  0.4.15-dev-1177-g6cb3b62
CMoveToMenu.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: MoveTo implementation
5  * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 
8 #include "precomp.h"
9 
11 
13  m_idCmdFirst(0),
14  m_idCmdLast(0),
15  m_idCmdMoveTo(-1),
16  m_fnOldWndProc(NULL),
17  m_bIgnoreTextBoxChange(FALSE)
18 {
19 }
20 
22 {
23 }
24 
25 static LRESULT CALLBACK
27 {
29  CMoveToMenu *this_ =
30  reinterpret_cast<CMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
31 
32  switch (uMsg)
33  {
34  case WM_COMMAND:
35  {
36  switch (LOWORD(wParam))
37  {
39  {
40  if (HIWORD(wParam) == EN_CHANGE)
41  {
42  if (!this_->m_bIgnoreTextBoxChange)
43  {
44  // get the text
46  StrTrimW(szPath, L" \t");
47 
48  // update OK button
50  SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid);
51 
52  return 0;
53  }
54 
55  // reset flag
57  }
58  break;
59  }
60  }
61  break;
62  }
63  }
64  return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, lParam);
65 }
66 
67 static int CALLBACK
69 {
70  CMoveToMenu *this_ =
71  reinterpret_cast<CMoveToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
72 
73  switch (uMsg)
74  {
75  case BFFM_INITIALIZED:
76  {
78  this_ = reinterpret_cast<CMoveToMenu *>(lpData);
79 
80  // Select initial directory
82  reinterpret_cast<LPARAM>(static_cast<LPCITEMIDLIST>(this_->m_pidlFolder)));
83 
84  // Set caption
86  SetWindowTextW(hwnd, strCaption);
87 
88  // Set OK button text
90  SetDlgItemText(hwnd, IDOK, strMove);
91 
92  // Subclassing
93  this_->m_fnOldWndProc =
94  reinterpret_cast<WNDPROC>(
95  SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WindowProc)));
96 
97  // Disable OK
99  break;
100  }
101  case BFFM_SELCHANGED:
102  {
104  LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(lParam);
105 
106  szPath[0] = 0;
108 
109  if (ILIsEqual(pidl, this_->m_pidlFolder))
111  else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
113  else
115 
116  // the text box will be updated later soon, ignore it
117  this_->m_bIgnoreTextBoxChange = TRUE;
118  break;
119  }
120  }
121 
122  return FALSE;
123 }
124 
126 {
127  CComHeapPtr<CIDA> pCIDA;
129  if (FAILED_UNEXPECTEDLY(hr))
130  return hr;
131 
132  PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
133  if (!pidlParent)
134  {
135  ERR("HIDA_GetPIDLFolder failed\n");
136  return E_FAIL;
137  }
138 
139  CStringW strFiles;
141  for (UINT n = 0; n < pCIDA->cidl; ++n)
142  {
143  PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, n);
144  if (!pidlRelative)
145  continue;
146 
147  CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
148  if (!pidl)
149  return E_FAIL;
150 
151  SHGetPathFromIDListW(pidlCombine, szPath);
152 
153  if (n > 0)
154  strFiles += L'|';
155  strFiles += szPath;
156  }
157 
158  strFiles += L'|'; // double null-terminated
159  strFiles.Replace(L'|', L'\0');
160 
161  if (_ILIsDesktop(pidl))
163  else
165  INT cchPath = lstrlenW(szPath);
166  if (cchPath + 1 < MAX_PATH)
167  {
168  szPath[cchPath + 1] = 0; // double null-terminated
169  }
170  else
171  {
172  ERR("Too long path\n");
173  return E_FAIL;
174  }
175 
176  SHFILEOPSTRUCTW op = { lpici->hwnd };
177  op.wFunc = FO_MOVE;
178  op.pFrom = strFiles;
179  op.pTo = szPath;
180  op.fFlags = FOF_ALLOWUNDO;
181  int res = SHFileOperationW(&op);
182  if (res)
183  {
184  ERR("SHFileOperationW failed with 0x%x\n", res);
185  return E_FAIL;
186  }
187  return S_OK;
188 }
189 
191 {
192  CStringW ret = L"(file)";
193 
194  CComHeapPtr<CIDA> pCIDA;
196  if (FAILED_UNEXPECTEDLY(hr))
197  return ret;
198 
199  PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
200  if (!pidlParent)
201  {
202  ERR("HIDA_GetPIDLFolder failed\n");
203  return ret;
204  }
205 
207  PCUIDLIST_RELATIVE pidlRelative = HIDA_GetPIDLItem(pCIDA, 0);
208  if (!pidlRelative)
209  {
210  ERR("HIDA_GetPIDLItem failed\n");
211  return ret;
212  }
213 
214  CComHeapPtr<ITEMIDLIST> pidlCombine(ILCombine(pidlParent, pidlRelative));
215 
216  if (SHGetPathFromIDListW(pidlCombine, szPath))
218  else
219  ERR("Cannot get path\n");
220 
221  if (pCIDA->cidl > 1)
222  ret += L" ...";
223 
224  return ret;
225 }
226 
228 {
229  WCHAR wszPath[MAX_PATH];
230  HRESULT hr = E_FAIL;
231 
232  TRACE("DoMoveToFolder(%p)\n", lpici);
233 
234  if (!SHGetPathFromIDListW(m_pidlFolder, wszPath))
235  {
236  ERR("SHGetPathFromIDListW failed\n");
237  return hr;
238  }
239 
240  CStringW strFileTitle = DoGetFileTitle();
241  CStringW strTitle;
242  strTitle.Format(IDS_MOVETOTITLE, static_cast<LPCWSTR>(strFileTitle));
243 
244  BROWSEINFOW info = { lpici->hwnd };
245  info.pidlRoot = NULL;
246  info.lpszTitle = strTitle;
248  info.lpfn = BrowseCallbackProc;
249  info.lParam = reinterpret_cast<LPARAM>(this);
251  if (pidl)
252  {
253  hr = DoRealMove(lpici, pidl);
254  }
255 
256  return hr;
257 }
258 
261  UINT indexMenu,
262  UINT idCmdFirst,
263  UINT idCmdLast,
264  UINT uFlags)
265 {
266  MENUITEMINFOW mii;
267  UINT Count = 0;
268 
269  TRACE("CMoveToMenu::QueryContextMenu(%p, %u, %u, %u, %u)\n",
270  hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
271 
272  m_idCmdFirst = m_idCmdLast = idCmdFirst;
273 
274  // insert separator if necessary
276  WCHAR szBuff[128];
277  ZeroMemory(&mii, sizeof(mii));
278  mii.cbSize = sizeof(mii);
279  mii.fMask = MIIM_TYPE;
280  mii.dwTypeData = szBuff;
281  mii.cch = _countof(szBuff);
282  if (GetMenuItemInfoW(hMenu, indexMenu - 1, TRUE, &mii) &&
283  mii.fType != MFT_SEPARATOR &&
284  !(mii.fType == MFT_STRING && CStringW(szBuff) == strCopyTo))
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 "Move 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, Count);
314 }
315 
318 {
319  HRESULT hr = E_FAIL;
320  TRACE("CMoveToMenu::InvokeCommand(%p)\n", lpici);
321 
322  if (HIWORD(lpici->lpVerb) == 0)
323  {
324  if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdMoveTo)
325  {
326  hr = DoMoveToFolder(lpici);
327  }
328  }
329  else
330  {
331  if (::lstrcmpiA(lpici->lpVerb, "moveto") == 0)
332  {
333  hr = DoMoveToFolder(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 }
#define IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT
Definition: shresdef.h:387
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1702
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
virtual HRESULT WINAPI GetSite(REFIID riid, void **ppvSite)
UINT WINAPI GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
Definition: dialog.c:2271
#define MFT_STRING
Definition: winuser.h:741
#define REFIID
Definition: guiddef.h:118
#define IDOK
Definition: winuser.h:824
virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
BOOL m_bIgnoreTextBoxChange
HRESULT DoRealMove(LPCMINVOKECOMMANDINFO lpici, PCUIDLIST_ABSOLUTE pidl)
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
HRESULT hr
Definition: shlfolder.c:183
#define PathIsRelative
Definition: shlwapi.h:951
#define TRUE
Definition: types.h:120
REFIID riid
Definition: precomp.h:44
WINE_DEFAULT_DEBUG_CHANNEL(shell)
LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:699
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1294
#define CALLBACK
Definition: compat.h:35
static PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const *pida, SIZE_T i)
Definition: shellutils.h:543
#define BFFM_INITIALIZED
Definition: shlobj.h:1163
GLdouble n
Definition: glext.h:7729
#define FOF_ALLOWUNDO
Definition: shellapi.h:144
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
#define ZeroMemory
Definition: winbase.h:1648
HRESULT _GetCidlFromDataObject(IDataObject *pDataObject, CIDA **ppcida)
Definition: CFontMenu.cpp:14
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:716
CComHeapPtr< ITEMIDLIST > m_pidlFolder
LPWSTR dwTypeData
Definition: winuser.h:3244
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:535
UINT_PTR WPARAM
Definition: windef.h:207
UINT uFlags
Definition: api.c:59
char * LPSTR
Definition: xmlstorage.h:182
#define lstrlenW
Definition: compat.h:498
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:58
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1918
#define SetWindowLongPtr
Definition: treelist.c:70
WPARAM wParam
Definition: combotst.c:138
#define IDS_MOVEITEMS
Definition: shresdef.h:306
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define IDS_MOVETOTITLE
Definition: shresdef.h:305
CComPtr< IUnknown > m_pSite
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
#define FO_MOVE
Definition: shellapi.h:133
#define IDS_MOVETOMENU
Definition: shresdef.h:304
#define FALSE
Definition: types.h:117
#define BFFM_SETSELECTION
Definition: shlobj.h:1183
unsigned int BOOL
Definition: ntddk_ex.h:94
CComPtr< IDataObject > m_pDataObject
#define FIXME(fmt,...)
Definition: debug.h:111
#define GWLP_USERDATA
Definition: treelist.c:63
smooth NULL
Definition: ftsmooth.c:416
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: CMoveToMenu.cpp:26
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:389
LONG_PTR LPARAM
Definition: windef.h:208
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1756
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
Definition: CBandSite.h:24
#define SHBrowseForFolder
Definition: shlobj.h:1180
#define MIIM_ID
Definition: winuser.h:717
BOOL WINAPI GetMenuItemInfoW(_In_ HMENU, _In_ UINT, _In_ BOOL, _Inout_ LPMENUITEMINFOW)
#define TRACE(s)
Definition: solgame.cpp:4
#define IDS_MOVEBUTTON
Definition: shresdef.h:307
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
Definition: CMoveToMenu.cpp:68
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:79
#define _countof(array)
Definition: sndvol32.h:68
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:71
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
UINT cidl
Definition: shlobj.h:499
virtual HRESULT WINAPI SetSite(IUnknown *pUnkSite)
UINT op
Definition: effect.c:224
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define BIF_USENEWUI
Definition: shlobj.h:1151
HRESULT DoMoveToFolder(LPCMINVOKECOMMANDINFO lpici)
#define SetDlgItemText
Definition: winuser.h:5824
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
UINT cchMax
#define MFT_SEPARATOR
Definition: winuser.h:739
int ret
static const WCHAR L[]
Definition: oid.c:1250
#define MIIM_TYPE
Definition: winuser.h:720
static PCUIDLIST_ABSOLUTE HIDA_GetPIDLFolder(CIDA const *pida)
Definition: shellutils.h:538
#define WM_COMMAND
Definition: winuser.h:1722
CStringW DoGetFileTitle()
#define GWLP_WNDPROC
Definition: treelist.c:66
#define ERR(fmt,...)
Definition: debug.h:110
int Replace(PCXSTR pszOld, PCXSTR pszNew)
Definition: cstringt.h:774
#define BFFM_ENABLEOK
Definition: shlobj.h:1171
#define S_OK
Definition: intsafe.h:51
const ITEMIDLIST_ABSOLUTE UNALIGNED * PCUIDLIST_ABSOLUTE
Definition: shtypes.idl:63
#define BIF_RETURNONLYFSDIRS
Definition: shlobj.h:1144
WNDPROC m_fnOldWndProc
BOOL WINAPI SHGetSpecialFolderPathW(HWND hwndOwner, LPWSTR szPath, int nFolder, BOOL bCreate)
Definition: shellpath.c:2709
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
LPCWSTR szPath
Definition: env.c:35
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:228
#define BFFM_SELCHANGED
Definition: shlobj.h:1164
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define E_NOTIMPL
Definition: ddrawi.h:99
virtual HRESULT WINAPI Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1869
const ITEMIDLIST_RELATIVE UNALIGNED * PCUIDLIST_RELATIVE
Definition: shtypes.idl:57
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
GLuint res
Definition: glext.h:9613
LRESULT WINAPI CallWindowProcW(_In_ WNDPROC, _In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define HIWORD(l)
Definition: typedefs.h:247
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define CSIDL_DESKTOPDIRECTORY
Definition: shlobj.h:2027
#define GetWindowLongPtr
Definition: treelist.c:73
LONG_PTR LRESULT
Definition: windef.h:209
#define IDS_COPYTOMENU
Definition: shresdef.h:300
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
LPARAM lParam
Definition: combotst.c:139
#define LOWORD(l)
Definition: pedump.c:82
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
#define EN_CHANGE
Definition: winuser.h:2004