ReactOS  0.4.15-dev-1206-g731eddf
shlfileop.cpp
Go to the documentation of this file.
1 /*
2  * SHFileOperation
3  *
4  * Copyright 2000 Juergen Schmied
5  * Copyright 2002 Andriy Palamarchuk
6  * Copyright 2004 Dietrich Teickner (from Odin)
7  * Copyright 2004 Rolf Kalbermatter
8  * Copyright 2019 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include "precomp.h"
26 
28 
29 #define IsAttrib(x, y) ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y)))
30 #define IsAttribFile(x) (!((x) & FILE_ATTRIBUTE_DIRECTORY))
31 #define IsAttribDir(x) IsAttrib(x, FILE_ATTRIBUTE_DIRECTORY)
32 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
33 
34 #define FO_MASK 0xF
35 
36 #define NEW_FILENAME_ON_COPY_TRIES 100
37 
38 static const WCHAR wWildcardFile[] = {'*',0};
39 static const WCHAR wWildcardChars[] = {'*','?',0};
40 
41 typedef struct
42 {
47  IProgressDialog *progress;
50  WCHAR szBuilderString[50];
52 
53 #define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026
54 
55 typedef struct
56 {
64 } FILE_ENTRY;
65 
66 typedef struct
67 {
74 } FILE_LIST;
75 
81 static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly);
82 static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo);
83 static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo);
84 
86 static BOOL _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks);
87 
88 /* Confirm dialogs with an optional "Yes To All" as used in file operations confirmations
89  */
90 static const WCHAR CONFIRM_MSG_PROP[] = {'W','I','N','E','_','C','O','N','F','I','R','M',0};
91 
93 {
98 };
99 
100 /* as some buttons may be hidden and the dialog height may change we may need
101  * to move the controls */
102 static void confirm_msg_move_button(HWND hDlg, INT iId, INT *xPos, INT yOffset, BOOL bShow)
103 {
104  HWND hButton = GetDlgItem(hDlg, iId);
105  RECT r;
106 
107  if (bShow)
108  {
109  POINT pt;
110  int width;
111 
112  GetWindowRect(hButton, &r);
113  width = r.right - r.left;
114  pt.x = r.left;
115  pt.y = r.top;
116  ScreenToClient(hDlg, &pt);
117  MoveWindow(hButton, *xPos - width, pt.y - yOffset, width, r.bottom - r.top, FALSE);
118  *xPos -= width + 5;
119  }
120  else
121  ShowWindow(hButton, SW_HIDE);
122 }
123 
124 /* Note: we paint the text manually and don't use the static control to make
125  * sure the text has the same height as the one computed in WM_INITDIALOG
126  */
128 {
129  PAINTSTRUCT ps;
130  HFONT hOldFont;
131  RECT r;
132  HDC hdc;
133 
134  BeginPaint(hDlg, &ps);
135  hdc = ps.hdc;
137 
139  /* this will remap the rect to dialog coords */
143  SelectObject(hdc, hOldFont);
144  EndPaint(hDlg, &ps);
145 
146  return TRUE;
147 }
148 
150 {
151  struct confirm_msg_info *info = (struct confirm_msg_info *)lParam;
152  INT xPos, yOffset;
153  int width, height;
154  HFONT hOldFont;
155  HDC hdc;
156  RECT r;
157 
158  SetWindowTextW(hDlg, info->lpszCaption);
160  SetPropW(hDlg, CONFIRM_MSG_PROP, info->lpszText);
162 
163  /* compute the text height and resize the dialog */
165  hdc = GetDC(hDlg);
166  yOffset = r.bottom;
169  SelectObject(hdc, hOldFont);
170  yOffset -= r.bottom;
171  yOffset = min(yOffset, 35); /* don't make the dialog too small */
172  ReleaseDC(hDlg, hdc);
173 
174  GetClientRect(hDlg, &r);
175  xPos = r.right - 7;
176  GetWindowRect(hDlg, &r);
177  width = r.right - r.left;
178  height = r.bottom - r.top - yOffset;
181 
182  confirm_msg_move_button(hDlg, IDCANCEL, &xPos, yOffset, info->bYesToAll);
183  confirm_msg_move_button(hDlg, IDNO, &xPos, yOffset, TRUE);
184  confirm_msg_move_button(hDlg, IDC_YESTOALL, &xPos, yOffset, info->bYesToAll);
185  confirm_msg_move_button(hDlg, IDYES, &xPos, yOffset, TRUE);
186 
187  return TRUE;
188 }
189 
191 {
192  switch (uMsg)
193  {
194  case WM_INITDIALOG:
195  return ConfirmMsgBox_Init(hDlg, lParam);
196  case WM_PAINT:
197  return ConfirmMsgBox_Paint(hDlg);
198  case WM_COMMAND:
199  EndDialog(hDlg, wParam);
200  break;
201  case WM_CLOSE:
202  EndDialog(hDlg, IDCANCEL);
203  break;
204  }
205  return FALSE;
206 }
207 
209 {
210  struct confirm_msg_info info;
211 
212  info.lpszText = lpszText;
213  info.lpszCaption = lpszCaption;
214  info.hIcon = hIcon;
215  info.bYesToAll = bYesToAll;
217 }
218 
219 /* confirmation dialogs content */
220 typedef struct
221 {
224  UINT caption_resource_id, text_resource_id;
226 
227 static BOOL SHELL_ConfirmIDs(int nKindOfDialog, SHELL_ConfirmIDstruc *ids)
228 {
229  ids->hIconInstance = shell32_hInstance;
230  switch (nKindOfDialog)
231  {
232  case ASK_DELETE_FILE:
233  ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
234  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
235  ids->text_resource_id = IDS_DELETEITEM_TEXT;
236  return TRUE;
237 
238  case ASK_DELETE_FOLDER:
239  ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
240  ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION;
241  ids->text_resource_id = IDS_DELETEITEM_TEXT;
242  return TRUE;
243 
245  ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
246  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
247  ids->text_resource_id = IDS_DELETEMULTIPLE_TEXT;
248  return TRUE;
249 
250  case ASK_TRASH_FILE:
251  ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
252  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
253  ids->text_resource_id = IDS_TRASHITEM_TEXT;
254  return TRUE;
255 
256  case ASK_TRASH_FOLDER:
257  ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
258  ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION;
259  ids->text_resource_id = IDS_TRASHFOLDER_TEXT;
260  return TRUE;
261 
263  ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
264  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
265  ids->text_resource_id = IDS_TRASHMULTIPLE_TEXT;
266  return TRUE;
267 
268  case ASK_CANT_TRASH_ITEM:
269  ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
270  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
271  ids->text_resource_id = IDS_CANTTRASH_TEXT;
272  return TRUE;
273 
274  case ASK_DELETE_SELECTED:
275  ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
276  ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
277  ids->text_resource_id = IDS_DELETESELECTED_TEXT;
278  return TRUE;
279 
280  case ASK_OVERWRITE_FILE:
281  ids->icon_resource_id = IDI_SHELL_FOLDER_MOVE2;
282  ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
283  ids->text_resource_id = IDS_OVERWRITEFILE_TEXT;
284  return TRUE;
285 
287  ids->icon_resource_id = IDI_SHELL_FOLDER_MOVE2;
288  ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
289  ids->text_resource_id = IDS_OVERWRITEFOLDER_TEXT;
290  return TRUE;
291 
292  default:
293  FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
294  }
295  return FALSE;
296 }
297 
298 static BOOL SHELL_ConfirmDialogW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir, FILE_OPERATION *op)
299 {
300  WCHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
302  DWORD_PTR args[1];
303  HICON hIcon;
304  int ret;
305 
306  assert(nKindOfDialog >= 0 && nKindOfDialog < 32);
307  if (op && (op->dwYesToAllMask & (1 << nKindOfDialog)))
308  return TRUE;
309 
310  if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) return FALSE;
311 
312  LoadStringW(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)/sizeof(WCHAR));
313  LoadStringW(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)/sizeof(WCHAR));
314 
315  args[0] = (DWORD_PTR)szDir;
317  szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)args);
318  hIcon = LoadIconW(ids.hIconInstance, (LPWSTR)MAKEINTRESOURCE(ids.icon_resource_id));
319 
320  ret = SHELL_ConfirmMsgBox(hWnd, szBuffer, szCaption, hIcon, op && op->bManyItems);
321  if (op)
322  {
323  if (ret == IDC_YESTOALL)
324  {
325  op->dwYesToAllMask |= (1 << nKindOfDialog);
326  ret = IDYES;
327  }
328  if (ret == IDCANCEL)
329  op->bCancelled = TRUE;
330  if (ret != IDYES)
331  op->req->fAnyOperationsAborted = TRUE;
332  }
333  return ret == IDYES;
334 }
335 
336 BOOL SHELL_ConfirmYesNoW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir)
337 {
338  return SHELL_ConfirmDialogW(hWnd, nKindOfDialog, szDir, NULL);
339 }
340 
341 static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minChars)
342 {
343  DWORD len = MultiByteToWideChar(CP_ACP, 0, aPath, -1, NULL, 0);
344 
345  if (len < minChars)
346  len = minChars;
347 
348  *wPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
349  if (*wPath)
350  {
351  MultiByteToWideChar(CP_ACP, 0, aPath, -1, *wPath, len);
352  return NO_ERROR;
353  }
354  return E_OUTOFMEMORY;
355 }
356 
357 static void SHELL32_FreeUnicodeBuf(LPWSTR wPath)
358 {
359  HeapFree(GetProcessHeap(), 0, wPath);
360 }
361 
363 {
364  FIXME("(%s, %p) stub\n", debugstr_w(path), status);
365  return E_FAIL;
366 }
367 
368 /**************************************************************************
369  * SHELL_DeleteDirectory() [internal]
370  *
371  * Asks for confirmation when bShowUI is true and deletes the directory and
372  * all its subdirectories and files if necessary.
373  */
375 {
376  BOOL ret = TRUE;
377  HANDLE hFind;
378  WIN32_FIND_DATAW wfd;
379  WCHAR szTemp[MAX_PATH];
380 
381  /* Make sure the directory exists before eventually prompting the user */
383  hFind = FindFirstFileW(szTemp, &wfd);
384  if (hFind == INVALID_HANDLE_VALUE)
385  return FALSE;
386 
387  if (!bShowUI || (ret = SHELL_ConfirmDialogW(op->req->hwnd, ASK_DELETE_FOLDER, pszDir, NULL)))
388  {
389  do
390  {
391  if (IsDotDir(wfd.cFileName))
392  continue;
393  PathCombineW(szTemp, pszDir, wfd.cFileName);
394  if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
395  ret = SHELL_DeleteDirectoryW(op, szTemp, FALSE);
396  else
397  ret = (SHNotifyDeleteFileW(op, szTemp) == ERROR_SUCCESS);
398 
399  if (op->progress != NULL)
400  op->bCancelled |= op->progress->HasUserCancelled();
401  } while (ret && FindNextFileW(hFind, &wfd) && !op->bCancelled);
402  }
403  FindClose(hFind);
404  if (ret)
406  return ret;
407 }
408 
409 /**************************************************************************
410  * Win32CreateDirectory [SHELL32.93]
411  *
412  * Creates a directory. Also triggers a change notify if one exists.
413  *
414  * PARAMS
415  * path [I] path to directory to create
416  *
417  * RETURNS
418  * TRUE if successful, FALSE otherwise
419  */
420 
422 {
423  TRACE("(%s, %p)\n", debugstr_w(path), sec);
424 
425  if (CreateDirectoryW(path, sec))
426  {
428  return ERROR_SUCCESS;
429  }
430  return GetLastError();
431 }
432 
433 /**********************************************************************/
434 
436 {
437  return (SHNotifyCreateDirectoryW(path, sec) == ERROR_SUCCESS);
438 }
439 
440 /************************************************************************
441  * Win32RemoveDirectory [SHELL32.94]
442  *
443  * Deletes a directory. Also triggers a change notify if one exists.
444  *
445  * PARAMS
446  * path [I] path to directory to delete
447  *
448  * RETURNS
449  * TRUE if successful, FALSE otherwise
450  */
452 {
453  BOOL ret;
454  TRACE("(%s)\n", debugstr_w(path));
455 
457  if (!ret)
458  {
459  /* Directory may be write protected */
460  DWORD dwAttr = GetFileAttributesW(path);
461  if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY))
464  }
465  if (ret)
466  {
468  return ERROR_SUCCESS;
469  }
470  return GetLastError();
471 }
472 
473 /***********************************************************************/
474 
476 {
478 }
479 
481  if (op->progress == NULL)
482  return;
483  WCHAR szTitle[50], szPreflight[50];
484  UINT animation_id = NULL;
485 
486  switch (op->req->wFunc)
487  {
488  case FO_COPY:
490  LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM_TO, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
491  animation_id = IDA_SHELL_COPY;
492  break;
493  case FO_DELETE:
495  LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
496  animation_id = IDA_SHELL_DELETE;
497  break;
498  case FO_MOVE:
500  LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM_TO, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
501  animation_id = IDA_SHELL_COPY;
502  break;
503  default:
504  return;
505  }
506  LoadStringW(shell32_hInstance, IDS_FILEOOP_PREFLIGHT, szPreflight, sizeof(szPreflight)/sizeof(WCHAR));
507 
508  op->progress->SetTitle(szTitle);
509  op->progress->SetLine(1, szPreflight, false, NULL);
510  op->progress->SetAnimation(shell32_hInstance, animation_id);
511 }
512 
514  if (op->progress == NULL || src == NULL)
515  return;
516  LPWSTR fileSpecS, pathSpecS, fileSpecD, pathSpecD;
517  WCHAR szFolderS[50], szFolderD[50], szFinalString[260];
518 
519  DWORD_PTR args[2];
520 
521  fileSpecS = (pathSpecS = (LPWSTR) src);
522  fileSpecD = (pathSpecD = (LPWSTR) dest);
523 
524  // March across the string to get the file path and it's parent dir.
525  for (LPWSTR ptr = (LPWSTR) src; *ptr; ptr++) {
526  if (*ptr == '\\') {
527  pathSpecS = fileSpecS;
528  fileSpecS = ptr+1;
529  }
530  }
531  lstrcpynW(szFolderS, pathSpecS, min(50, fileSpecS - pathSpecS));
532  args[0] = (DWORD_PTR) szFolderS;
533 
534  switch (op->req->wFunc)
535  {
536  case FO_COPY:
537  case FO_MOVE:
538  if (dest == NULL)
539  return;
540  for (LPWSTR ptr = (LPWSTR) dest; *ptr; ptr++) {
541  if (*ptr == '\\') {
542  pathSpecD = fileSpecD;
543  fileSpecD = ptr + 1;
544  }
545  }
546  lstrcpynW(szFolderD, pathSpecD, min(50, fileSpecD - pathSpecD));
547  args[1] = (DWORD_PTR) szFolderD;
548  break;
549  case FO_DELETE:
550  break;
551  default:
552  return;
553  }
554 
556  op->szBuilderString, 0, 0, szFinalString, sizeof(szFinalString), (va_list*)args);
557 
558  op->progress->SetLine(1, fileSpecS, false, NULL);
559  op->progress->SetLine(2, szFinalString, false, NULL);
560 }
561 
562 
564  LARGE_INTEGER TotalFileSize,
565  LARGE_INTEGER TotalBytesTransferred,
566  LARGE_INTEGER StreamSize,
567  LARGE_INTEGER StreamBytesTransferred,
568  DWORD dwStreamNumber,
569  DWORD dwCallbackReason,
570  HANDLE hSourceFile,
571  HANDLE hDestinationFile,
572  LPVOID lpData
573 ) {
574  FILE_OPERATION *op = (FILE_OPERATION *) lpData;
575 
576  if (op->progress) {
577  /*
578  * This is called at the start of each file. To keop less state,
579  * I'm adding the file to the completed size here, and the re-subtracting
580  * it when drawing the progress bar.
581  */
582  if (dwCallbackReason & CALLBACK_STREAM_SWITCH)
583  op->completedSize.QuadPart += TotalFileSize.QuadPart;
584 
585  op->progress->SetProgress64(op->completedSize.QuadPart -
586  TotalFileSize.QuadPart +
587  TotalBytesTransferred.QuadPart
588  , op->totalSize.QuadPart);
589 
590 
591  op->bCancelled = op->progress->HasUserCancelled();
592  }
593 
594  return 0;
595 }
596 
597 
598 /************************************************************************
599  * SHNotifyDeleteFileW [internal]
600  *
601  * Deletes a file. Also triggers a change notify if one exists.
602  *
603  * PARAMS
604  * op [I] File Operation context
605  * path [I] path to source file to move
606  *
607  * RETURNS
608  * ERORR_SUCCESS if successful
609  */
611 {
612  BOOL ret;
613 
614  TRACE("(%s)\n", debugstr_w(path));
615 
617 
619  FileSize.QuadPart = 0;
620 
621  WIN32_FIND_DATAW wfd;
622  HANDLE hFile = FindFirstFileW(path, &wfd);
623  if (hFile != INVALID_HANDLE_VALUE && IsAttribFile(wfd.dwFileAttributes)) {
624  ULARGE_INTEGER tmp;
625  tmp.u.LowPart = wfd.nFileSizeLow;
626  tmp.u.HighPart = wfd.nFileSizeHigh;
627  FileSize.QuadPart = tmp.QuadPart;
628  }
629  FindClose(hFile);
630 
631  ret = DeleteFileW(path);
632  if (!ret)
633  {
634  /* File may be write protected or a system file */
635  DWORD dwAttr = GetFileAttributesW(path);
638  ret = DeleteFileW(path);
639  }
640  if (ret)
641  {
642  // Bit of a hack to make the progress bar move. We don't have progress inside the file, so inform when done.
645  return ERROR_SUCCESS;
646  }
647  return GetLastError();
648 }
649 
650 /************************************************************************
651  * Win32DeleteFile [SHELL32.164]
652  *
653  * Deletes a file. Also triggers a change notify if one exists.
654  *
655  * PARAMS
656  * path [I] path to file to delete
657  *
658  * RETURNS
659  * TRUE if successful, FALSE otherwise
660  */
662 {
664 }
665 
666 /************************************************************************
667  * SHNotifyMoveFile [internal]
668  *
669  * Moves a file. Also triggers a change notify if one exists.
670  *
671  * PARAMS
672  * op [I] File Operation context
673  * src [I] path to source file to move
674  * dest [I] path to target file to move to
675  *
676  * RETURNS
677  * ERROR_SUCCESS if successful
678  */
680 {
681  BOOL ret;
682 
683  TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest));
684 
686 
688 
689  /* MOVEFILE_REPLACE_EXISTING fails with dirs, so try MoveFile */
690  if (!ret)
691  ret = MoveFileW(src, dest);
692 
693  if (!ret)
694  {
695  DWORD dwAttr;
696 
697  dwAttr = SHFindAttrW(dest, FALSE);
698  if (INVALID_FILE_ATTRIBUTES == dwAttr)
699  {
700  /* Source file may be write protected or a system file */
701  dwAttr = GetFileAttributesW(src);
704  ret = MoveFileW(src, dest);
705  }
706  }
707  if (ret)
708  {
711  return ERROR_SUCCESS;
712  }
713  return GetLastError();
714 }
715 
716 /************************************************************************
717  * SHNotifyCopyFile [internal]
718  *
719  * Copies a file. Also triggers a change notify if one exists.
720  *
721  * PARAMS
722  * src [I] path to source file to move
723  * dest [I] path to target file to move to
724  * bFailIfExists [I] if TRUE, the target file will not be overwritten if
725  * a file with this name already exists
726  *
727  * RETURNS
728  * ERROR_SUCCESS if successful
729  */
731 {
732  BOOL ret;
733  DWORD attribs;
734 
735  TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : "");
736 
738 
739  /* Destination file may already exist with read only attribute */
743 
745  {
748  {
749  TRACE("[shell32, SHNotifyCopyFileW] STILL SHIT\n");
750  }
751  }
752 
753  ret = CopyFileExW(src, dest, SHCopyProgressRoutine, op, &op->bCancelled, bFailIfExists);
754  if (ret)
755  {
757  return ERROR_SUCCESS;
758  }
759 
760  return GetLastError();
761 }
762 
763 /*************************************************************************
764  * SHCreateDirectory [SHELL32.165]
765  *
766  * This function creates a file system folder whose fully qualified path is
767  * given by path. If one or more of the intermediate folders do not exist,
768  * they will be created as well.
769  *
770  * PARAMS
771  * hWnd [I]
772  * path [I] path of directory to create
773  *
774  * RETURNS
775  * ERROR_SUCCESS or one of the following values:
776  * ERROR_BAD_PATHNAME if the path is relative
777  * ERROR_FILE_EXISTS when a file with that name exists
778  * ERROR_PATH_NOT_FOUND can't find the path, probably invalid
779  * ERROR_INVALID_NAME if the path contains invalid chars
780  * ERROR_ALREADY_EXISTS when the directory already exists
781  * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
782  *
783  * NOTES
784  * exported by ordinal
785  * Win9x exports ANSI
786  * WinNT/2000 exports Unicode
787  */
789 {
791 }
792 
793 /*************************************************************************
794  * SHCreateDirectoryExA [SHELL32.@]
795  *
796  * This function creates a file system folder whose fully qualified path is
797  * given by path. If one or more of the intermediate folders do not exist,
798  * they will be created as well.
799  *
800  * PARAMS
801  * hWnd [I]
802  * path [I] path of directory to create
803  * sec [I] security attributes to use or NULL
804  *
805  * RETURNS
806  * ERROR_SUCCESS or one of the following values:
807  * ERROR_BAD_PATHNAME or ERROR_PATH_NOT_FOUND if the path is relative
808  * ERROR_INVALID_NAME if the path contains invalid chars
809  * ERROR_FILE_EXISTS when a file with that name exists
810  * ERROR_ALREADY_EXISTS when the directory already exists
811  * ERROR_FILENAME_EXCED_RANGE if the filename was too long to process
812  *
813  * FIXME: Not implemented yet;
814  * SHCreateDirectoryEx also verifies that the files in the directory will be visible
815  * if the path is a network path to deal with network drivers which might have a limited
816  * but unknown maximum path length. If not:
817  *
818  * If hWnd is set to a valid window handle, a message box is displayed warning
819  * the user that the files may not be accessible. If the user chooses not to
820  * proceed, the function returns ERROR_CANCELLED.
821  *
822  * If hWnd is set to NULL, no user interface is displayed and the function
823  * returns ERROR_CANCELLED.
824  */
826 {
827  LPWSTR wPath;
828  DWORD retCode;
829 
830  TRACE("(%s, %p)\n", debugstr_a(path), sec);
831 
832  retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
833  if (!retCode)
834  {
835  retCode = SHCreateDirectoryExW(hWnd, wPath, sec);
836  SHELL32_FreeUnicodeBuf(wPath);
837  }
838  return retCode;
839 }
840 
841 /*************************************************************************
842  * SHCreateDirectoryExW [SHELL32.@]
843  *
844  * See SHCreateDirectoryExA.
845  */
847 {
848  int ret = ERROR_BAD_PATHNAME;
849  TRACE("(%p, %s, %p)\n", hWnd, debugstr_w(path), sec);
850 
851  if (PathIsRelativeW(path))
852  {
853  SetLastError(ret);
854  }
855  else
856  {
858  /* Refuse to work on certain error codes before trying to create directories recursively */
859  if (ret != ERROR_SUCCESS &&
860  ret != ERROR_FILE_EXISTS &&
863  {
864  WCHAR *pEnd, *pSlash, szTemp[MAX_PATH + 1]; /* extra for PathAddBackslash() */
865 
866  lstrcpynW(szTemp, path, MAX_PATH);
867  pEnd = PathAddBackslashW(szTemp);
868  pSlash = szTemp + 3;
869 
870  while (*pSlash)
871  {
872  while (*pSlash && *pSlash != '\\') pSlash++;
873  if (*pSlash)
874  {
875  *pSlash = 0; /* terminate path at separator */
876 
877  ret = SHNotifyCreateDirectoryW(szTemp, pSlash + 1 == pEnd ? sec : NULL);
878  }
879  *pSlash++ = '\\'; /* put the separator back */
880  }
881  }
882 
883  if (ret && hWnd && (ERROR_CANCELLED != ret && ERROR_ALREADY_EXISTS != ret))
884  {
888  }
889  }
890 
891  return ret;
892 }
893 
894 /*************************************************************************
895  * SHFindAttrW [internal]
896  *
897  * Get the Attributes for a file or directory. The difference to GetAttributes()
898  * is that this function will also work for paths containing wildcard characters
899  * in its filename.
900 
901  * PARAMS
902  * path [I] path of directory or file to check
903  * fileOnly [I] TRUE if only files should be found
904  *
905  * RETURNS
906  * INVALID_FILE_ATTRIBUTES if the path does not exist, the actual attributes of
907  * the first file or directory found otherwise
908  */
909 static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly)
910 {
911  WIN32_FIND_DATAW wfd;
912  BOOL b_FileMask = fileOnly && (NULL != StrPBrkW(pName, wWildcardChars));
914  HANDLE hFind = FindFirstFileW(pName, &wfd);
915 
916  TRACE("%s %d\n", debugstr_w(pName), fileOnly);
917  if (INVALID_HANDLE_VALUE != hFind)
918  {
919  do
920  {
921  if (b_FileMask && IsAttribDir(wfd.dwFileAttributes))
922  continue;
923  dwAttr = wfd.dwFileAttributes;
924  break;
925  } while (FindNextFileW(hFind, &wfd));
926 
927  FindClose(hFind);
928  }
929  return dwAttr;
930 }
931 
932 /*************************************************************************
933  *
934  * _ConvertAtoW helper function for SHFileOperationA
935  *
936  * Converts a string or string-list to unicode.
937  */
938 static DWORD _ConvertAtoW(PCSTR strSrc, PCWSTR* pStrDest, BOOL isList)
939 {
940  *pStrDest = NULL;
941 
942  // If the input is null, nothing to convert.
943  if (!strSrc)
944  return 0;
945 
946  // Measure the total size, depending on if it's a zero-terminated list.
947  int sizeA = 0;
948  if (isList)
949  {
950  PCSTR tmpSrc = strSrc;
951  int size;
952  do
953  {
954  size = lstrlenA(tmpSrc) + 1;
955  sizeA += size;
956  tmpSrc += size;
957  } while (size != 1);
958  }
959  else
960  {
961  sizeA = lstrlenA(strSrc) + 1;
962  }
963 
964  // Measure the needed allocation size.
965  int sizeW = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, NULL, 0);
966  if (!sizeW)
967  return GetLastError();
968 
969  PWSTR strDest = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
970  if (!strDest)
971  return ERROR_OUTOFMEMORY;
972 
973  int err = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, strDest, sizeW);
974  if (!err)
975  {
976  HeapFree(GetProcessHeap(), 0, strDest);
977  return GetLastError();
978  }
979 
980  *pStrDest = strDest;
981  return 0;
982 }
983 
984 /*************************************************************************
985  * SHFileOperationA [SHELL32.@]
986  *
987  * Function to copy, move, delete and create one or more files with optional
988  * user prompts.
989  *
990  * PARAMS
991  * lpFileOp [I/O] pointer to a structure containing all the necessary information
992  *
993  * RETURNS
994  * Success: ERROR_SUCCESS.
995  * Failure: ERROR_CANCELLED.
996  *
997  * NOTES
998  * exported by name
999  */
1001 {
1002  int errCode, retCode;
1003  SHFILEOPSTRUCTW nFileOp = { 0 };
1004 
1005  // Convert A information to W
1006  nFileOp.hwnd = lpFileOp->hwnd;
1007  nFileOp.wFunc = lpFileOp->wFunc;
1008  nFileOp.fFlags = lpFileOp->fFlags;
1009 
1010  errCode = _ConvertAtoW(lpFileOp->pFrom, &nFileOp.pFrom, TRUE);
1011  if (errCode != 0)
1012  goto cleanup;
1013 
1014  if (FO_DELETE != (nFileOp.wFunc & FO_MASK))
1015  {
1016  errCode = _ConvertAtoW(lpFileOp->pTo, &nFileOp.pTo, TRUE);
1017  if (errCode != 0)
1018  goto cleanup;
1019  }
1020 
1021  if (nFileOp.fFlags & FOF_SIMPLEPROGRESS)
1022  {
1023  errCode = _ConvertAtoW(lpFileOp->lpszProgressTitle, &nFileOp.lpszProgressTitle, FALSE);
1024  if (errCode != 0)
1025  goto cleanup;
1026  }
1027 
1028  // Call the actual function
1029  retCode = SHFileOperationW(&nFileOp);
1030  if (retCode)
1031  {
1032  ERR("SHFileOperationW failed with 0x%x\n", retCode);
1033  }
1034 
1035  // Cleanup
1036 cleanup:
1037  if (nFileOp.pFrom)
1038  HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pFrom);
1039  if (nFileOp.pTo)
1040  HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pTo);
1041  if (nFileOp.lpszProgressTitle)
1043 
1044  if (errCode != 0)
1045  {
1046  lpFileOp->fAnyOperationsAborted = TRUE;
1047  SetLastError(errCode);
1048 
1049  return errCode;
1050  }
1051 
1052  // Thankfully, starting with NT4 the name mappings are always unicode, so no need to convert.
1053  lpFileOp->hNameMappings = nFileOp.hNameMappings;
1054  lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted;
1055  return retCode;
1056 }
1057 
1058 static void __inline grow_list(FILE_LIST *list)
1059 {
1061  list->num_alloc * 2 * sizeof(*newx) );
1062  list->feFiles = newx;
1063  list->num_alloc *= 2;
1064 }
1065 
1066 /* adds a file to the FILE_ENTRY struct
1067  */
1068 static void add_file_to_entry(FILE_ENTRY *feFile, LPCWSTR szFile)
1069 {
1070  DWORD dwLen = lstrlenW(szFile) + 1;
1071  LPCWSTR ptr;
1072  LPCWSTR ptr2;
1073 
1074  feFile->szFullPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1075  lstrcpyW(feFile->szFullPath, szFile);
1076 
1077  ptr = StrRChrW(szFile, NULL, '\\');
1078  ptr2 = StrRChrW(szFile, NULL, '/');
1079  if (!ptr || ptr < ptr2)
1080  ptr = ptr2;
1081  if (ptr)
1082  {
1083  dwLen = ptr - szFile + 1;
1084  feFile->szDirectory = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1085  lstrcpynW(feFile->szDirectory, szFile, dwLen);
1086 
1087  dwLen = lstrlenW(feFile->szFullPath) - dwLen + 1;
1088  feFile->szFilename = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1089  lstrcpyW(feFile->szFilename, ptr + 1); /* skip over backslash */
1090  }
1091  feFile->bFromWildcard = FALSE;
1092 }
1093 
1094 static LPWSTR wildcard_to_file(LPCWSTR szWildCard, LPCWSTR szFileName)
1095 {
1096  LPCWSTR ptr;
1097  LPCWSTR ptr2;
1098  LPWSTR szFullPath;
1099  DWORD dwDirLen, dwFullLen;
1100 
1101  ptr = StrRChrW(szWildCard, NULL, '\\');
1102  ptr2 = StrRChrW(szWildCard, NULL, '/');
1103  if (!ptr || ptr < ptr2)
1104  ptr = ptr2;
1105  dwDirLen = ptr - szWildCard + 1;
1106 
1107  dwFullLen = dwDirLen + lstrlenW(szFileName) + 1;
1108  szFullPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwFullLen * sizeof(WCHAR));
1109 
1110  lstrcpynW(szFullPath, szWildCard, dwDirLen + 1);
1111  lstrcatW(szFullPath, szFileName);
1112 
1113  return szFullPath;
1114 }
1115 
1116 static void parse_wildcard_files(FILE_LIST *flList, LPCWSTR szFile, LPDWORD pdwListIndex)
1117 {
1118  WIN32_FIND_DATAW wfd;
1119  HANDLE hFile = FindFirstFileW(szFile, &wfd);
1120  FILE_ENTRY *file;
1121  LPWSTR szFullPath;
1122  BOOL res;
1123 
1124  if (hFile == INVALID_HANDLE_VALUE) return;
1125 
1126  for (res = TRUE; res; res = FindNextFileW(hFile, &wfd))
1127  {
1128  if (IsDotDir(wfd.cFileName))
1129  continue;
1130 
1131  if (*pdwListIndex >= flList->num_alloc)
1132  grow_list( flList );
1133 
1134  szFullPath = wildcard_to_file(szFile, wfd.cFileName);
1135  file = &flList->feFiles[(*pdwListIndex)++];
1136  add_file_to_entry(file, szFullPath);
1137  file->bFromWildcard = TRUE;
1138  file->attributes = wfd.dwFileAttributes;
1139 
1140  if (IsAttribDir(file->attributes))
1141  flList->bAnyDirectories = TRUE;
1142 
1143  HeapFree(GetProcessHeap(), 0, szFullPath);
1144  }
1145 
1146  FindClose(hFile);
1147 }
1148 
1149 /* takes the null-separated file list and fills out the FILE_LIST */
1151 {
1152  LPCWSTR ptr = szFiles;
1153  WCHAR szCurFile[MAX_PATH];
1154  DWORD i = 0;
1155 
1156  if (!szFiles)
1157  return ERROR_INVALID_PARAMETER;
1158 
1159  flList->bAnyFromWildcard = FALSE;
1160  flList->bAnyDirectories = FALSE;
1161  flList->bAnyDontExist = FALSE;
1162  flList->num_alloc = 32;
1163  flList->dwNumFiles = 0;
1164 
1165  /* empty list */
1166  if (!szFiles[0])
1167  return ERROR_ACCESS_DENIED;
1168 
1170  flList->num_alloc * sizeof(FILE_ENTRY));
1171 
1172  while (*ptr)
1173  {
1174  if (i >= flList->num_alloc) grow_list( flList );
1175 
1176  /* change relative to absolute path */
1177  if (PathIsRelativeW(ptr))
1178  {
1179  GetCurrentDirectoryW(MAX_PATH, szCurFile);
1180  PathCombineW(szCurFile, szCurFile, ptr);
1181  flList->feFiles[i].bFromRelative = TRUE;
1182  }
1183  else
1184  {
1185  lstrcpyW(szCurFile, ptr);
1186  flList->feFiles[i].bFromRelative = FALSE;
1187  }
1188 
1189  /* parse wildcard files if they are in the filename */
1190  if (StrPBrkW(szCurFile, wWildcardChars))
1191  {
1192  parse_wildcard_files(flList, szCurFile, &i);
1193  flList->bAnyFromWildcard = TRUE;
1194  i--;
1195  }
1196  else
1197  {
1198  FILE_ENTRY *file = &flList->feFiles[i];
1199  add_file_to_entry(file, szCurFile);
1200  file->attributes = GetFileAttributesW( file->szFullPath );
1201  file->bExists = (file->attributes != INVALID_FILE_ATTRIBUTES);
1202 
1203  if (!file->bExists)
1204  flList->bAnyDontExist = TRUE;
1205 
1206  if (IsAttribDir(file->attributes))
1207  flList->bAnyDirectories = TRUE;
1208  }
1209 
1210  /* advance to the next string */
1211  ptr += lstrlenW(ptr) + 1;
1212  i++;
1213  }
1214  flList->dwNumFiles = i;
1215 
1216  return S_OK;
1217 }
1218 
1219 /* free the FILE_LIST */
1220 static void destroy_file_list(FILE_LIST *flList)
1221 {
1222  DWORD i;
1223 
1224  if (!flList || !flList->feFiles)
1225  return;
1226 
1227  for (i = 0; i < flList->dwNumFiles; i++)
1228  {
1229  HeapFree(GetProcessHeap(), 0, flList->feFiles[i].szDirectory);
1230  HeapFree(GetProcessHeap(), 0, flList->feFiles[i].szFilename);
1231  HeapFree(GetProcessHeap(), 0, flList->feFiles[i].szFullPath);
1232  }
1233 
1234  HeapFree(GetProcessHeap(), 0, flList->feFiles);
1235 }
1236 
1238 {
1239  CStringW mask(szDestPath);
1240  CStringW ext(PathFindExtensionW(szDestPath));
1241 
1242  // cut off extension before inserting a "new file" mask
1243  if (!ext.IsEmpty())
1244  {
1245  mask = mask.Left(mask.GetLength() - ext.GetLength());
1246  }
1247  mask += L" (%d)" + ext;
1248 
1249  CStringW newName;
1250 
1251  // trying to find new file name
1252  for (int i = 1; i < NEW_FILENAME_ON_COPY_TRIES; i++)
1253  {
1254  newName.Format(mask, i);
1255 
1256  if (!PathFileExistsW(newName))
1257  {
1258  return newName;
1259  }
1260  }
1261 
1262  return CStringW();
1263 }
1264 
1265 static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
1266 {
1267  WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1268  FILE_LIST flFromNew, flToNew;
1269 
1270  static const WCHAR wildCardFiles[] = {'*','.','*',0};
1271 
1272  if (IsDotDir(feFrom->szFilename))
1273  return;
1274 
1275  if (PathFileExistsW(szDestPath))
1276  PathCombineW(szTo, szDestPath, feFrom->szFilename);
1277  else
1278  lstrcpyW(szTo, szDestPath);
1279 
1280 #ifdef __REACTOS__
1281  if (PathFileExistsW(szTo))
1282  {
1283  if (op->req->fFlags & FOF_RENAMEONCOLLISION)
1284  {
1285  CStringW newPath = try_find_new_name(szTo);
1286  if (!newPath.IsEmpty())
1287  {
1288  StringCchCopyW(szTo, _countof(szTo), newPath);
1289  }
1290  }
1291  else if (!(op->req->fFlags & FOF_NOCONFIRMATION))
1292 #else
1293  if (!(op->req->fFlags & FOF_NOCONFIRMATION) && PathFileExistsW(szTo))
1294  {
1295  CStringW newPath;
1296  if (lstrcmp(feFrom->szDirectory, szDestPath) == 0 && !(newPath = try_find_new_name(szTo)).IsEmpty())
1297  {
1298  StringCchCopyW(szTo, _countof(szTo), newPath);
1299  }
1300  else
1301 #endif
1302  {
1303  if (!SHELL_ConfirmDialogW(op->req->hwnd, ASK_OVERWRITE_FOLDER, feFrom->szFilename, op))
1304  {
1305  /* Vista returns an ERROR_CANCELLED even if user pressed "No" */
1306  if (!op->bManyItems)
1307  op->bCancelled = TRUE;
1308  return;
1309  }
1310  }
1311  }
1312 
1313  szTo[lstrlenW(szTo) + 1] = '\0';
1315 
1316  PathCombineW(szFrom, feFrom->szFullPath, wildCardFiles);
1317  szFrom[lstrlenW(szFrom) + 1] = '\0';
1318 
1319  ZeroMemory(&flFromNew, sizeof(FILE_LIST));
1320  ZeroMemory(&flToNew, sizeof(FILE_LIST));
1321  parse_file_list(&flFromNew, szFrom);
1322  parse_file_list(&flToNew, szTo);
1323 
1324  copy_files(op, FALSE, &flFromNew, &flToNew);
1325 
1326  destroy_file_list(&flFromNew);
1327  destroy_file_list(&flToNew);
1328 }
1329 
1331 {
1332 #ifdef __REACTOS__
1333  if (PathFileExistsW(szTo))
1334  {
1335  if (op->req->fFlags & FOF_RENAMEONCOLLISION)
1336  {
1337  CStringW newPath = try_find_new_name(szTo);
1338  if (!newPath.IsEmpty())
1339  {
1340  return SHNotifyCopyFileW(op, szFrom, newPath, FALSE) == 0;
1341  }
1342  }
1343  else if (!(op->req->fFlags & FOF_NOCONFIRMATION))
1344  {
1346  return FALSE;
1347  }
1348 #else
1349  if (!(op->req->fFlags & FOF_NOCONFIRMATION) && PathFileExistsW(szTo))
1350  {
1351  CStringW newPath;
1352  if (lstrcmp(szFrom, szTo) == 0 && !(newPath = try_find_new_name(szTo)).IsEmpty())
1353  {
1354  return SHNotifyCopyFileW(op, szFrom, newPath, FALSE) == 0;
1355  }
1356 
1358  return FALSE;
1359 #endif
1360  }
1361 
1362  return SHNotifyCopyFileW(op, szFrom, szTo, FALSE) == 0;
1363 }
1364 
1365 /* copy a file or directory to another directory */
1366 static void copy_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
1367 {
1368  if (!PathFileExistsW(feTo->szFullPath))
1370 
1371  if (IsAttribFile(feFrom->attributes))
1372  {
1373  WCHAR szDestPath[MAX_PATH];
1374 
1375  PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
1376  copy_file_to_file(op, feFrom->szFullPath, szDestPath);
1377  }
1378  else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
1379  copy_dir_to_dir(op, feFrom, feTo->szFullPath);
1380 }
1381 
1382 static void create_dest_dirs(LPCWSTR szDestDir)
1383 {
1384  WCHAR dir[MAX_PATH];
1385  LPCWSTR ptr = StrChrW(szDestDir, '\\');
1386 
1387  /* make sure all directories up to last one are created */
1388  while (ptr && (ptr = StrChrW(ptr + 1, '\\')))
1389  {
1390  lstrcpynW(dir, szDestDir, ptr - szDestDir + 1);
1391 
1392  if (!PathFileExistsW(dir))
1394  }
1395 
1396  /* create last directory */
1397  if (!PathFileExistsW(szDestDir))
1398  SHNotifyCreateDirectoryW(szDestDir, NULL);
1399 }
1400 
1401 /* the FO_COPY operation */
1402 static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo)
1403 {
1404  DWORD i;
1405  const FILE_ENTRY *entryToCopy;
1406  const FILE_ENTRY *fileDest = &flTo->feFiles[0];
1407 
1408  if (flFrom->bAnyDontExist)
1410 
1411  if (flTo->dwNumFiles == 0)
1412  {
1413  /* If the destination is empty, SHFileOperation should use the current directory */
1414  WCHAR curdir[MAX_PATH+1];
1415 
1416  GetCurrentDirectoryW(MAX_PATH, curdir);
1417  curdir[lstrlenW(curdir)+1] = 0;
1418 
1419  destroy_file_list(flTo);
1420  ZeroMemory(flTo, sizeof(FILE_LIST));
1421  parse_file_list(flTo, curdir);
1422  fileDest = &flTo->feFiles[0];
1423  }
1424 
1425  if (multiDest)
1426  {
1427  if (flFrom->bAnyFromWildcard)
1428  return ERROR_CANCELLED;
1429 
1430  if (flFrom->dwNumFiles != flTo->dwNumFiles)
1431  {
1432  if (flFrom->dwNumFiles != 1 && !IsAttribDir(fileDest->attributes))
1433  return ERROR_CANCELLED;
1434 
1435  /* Free all but the first entry. */
1436  for (i = 1; i < flTo->dwNumFiles; i++)
1437  {
1439  HeapFree(GetProcessHeap(), 0, flTo->feFiles[i].szFilename);
1440  HeapFree(GetProcessHeap(), 0, flTo->feFiles[i].szFullPath);
1441  }
1442 
1443  flTo->dwNumFiles = 1;
1444  }
1445  else if (IsAttribDir(fileDest->attributes))
1446  {
1447  for (i = 1; i < flTo->dwNumFiles; i++)
1448  if (!IsAttribDir(flTo->feFiles[i].attributes) ||
1449  !IsAttribDir(flFrom->feFiles[i].attributes))
1450  {
1451  return ERROR_CANCELLED;
1452  }
1453  }
1454  }
1455  else if (flFrom->dwNumFiles != 1)
1456  {
1457  if (flTo->dwNumFiles != 1 && !IsAttribDir(fileDest->attributes))
1458  return ERROR_CANCELLED;
1459 
1460  if (PathFileExistsW(fileDest->szFullPath) &&
1461  IsAttribFile(fileDest->attributes))
1462  {
1463  return ERROR_CANCELLED;
1464  }
1465 
1466  if (flTo->dwNumFiles == 1 && fileDest->bFromRelative &&
1467  !PathFileExistsW(fileDest->szFullPath))
1468  {
1469  return ERROR_CANCELLED;
1470  }
1471  }
1472 
1473  for (i = 0; i < flFrom->dwNumFiles; i++)
1474  {
1475  entryToCopy = &flFrom->feFiles[i];
1476 
1477  if ((multiDest) &&
1478  flTo->dwNumFiles > 1)
1479  {
1480  fileDest = &flTo->feFiles[i];
1481  }
1482 
1483  if (IsAttribDir(entryToCopy->attributes) &&
1484  !lstrcmpiW(entryToCopy->szFullPath, fileDest->szDirectory))
1485  {
1486  return ERROR_SUCCESS;
1487  }
1488 
1489  create_dest_dirs(fileDest->szDirectory);
1490 
1491  if (!lstrcmpiW(entryToCopy->szFullPath, fileDest->szFullPath))
1492  {
1493  if (IsAttribFile(entryToCopy->attributes))
1495  else
1496  return ERROR_SUCCESS;
1497  }
1498 
1499  if ((flFrom->dwNumFiles > 1 && flTo->dwNumFiles == 1) ||
1500  IsAttribDir(fileDest->attributes))
1501  {
1502  copy_to_dir(op, entryToCopy, fileDest);
1503  }
1504  else if (IsAttribDir(entryToCopy->attributes))
1505  {
1506  copy_dir_to_dir(op, entryToCopy, fileDest->szFullPath);
1507  }
1508  else
1509  {
1510  if (!copy_file_to_file(op, entryToCopy->szFullPath, fileDest->szFullPath))
1511  {
1512  op->req->fAnyOperationsAborted = TRUE;
1513  return ERROR_CANCELLED;
1514  }
1515  }
1516 
1517  if (op->progress != NULL)
1518  op->bCancelled |= op->progress->HasUserCancelled();
1519  /* Vista return code. XP would return e.g. ERROR_FILE_NOT_FOUND, ERROR_ALREADY_EXISTS */
1520  if (op->bCancelled)
1521  return ERROR_CANCELLED;
1522  }
1523 
1524  /* Vista return code. On XP if the used pressed "No" for the last item,
1525  * ERROR_ARENA_TRASHED would be returned */
1526  return ERROR_SUCCESS;
1527 }
1528 
1529 static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE_LIST *flFrom)
1530 {
1531  if (flFrom->dwNumFiles > 1)
1532  {
1533  WCHAR tmp[8];
1534  const WCHAR format[] = {'%','d',0};
1535 
1536  wnsprintfW(tmp, sizeof(tmp)/sizeof(tmp[0]), format, flFrom->dwNumFiles);
1538  }
1539  else
1540  {
1541  const FILE_ENTRY *fileEntry = &flFrom->feFiles[0];
1542 
1543  if (IsAttribFile(fileEntry->attributes))
1544  return SHELL_ConfirmDialogW(hWnd, (fTrash?ASK_TRASH_FILE:ASK_DELETE_FILE), fileEntry->szFullPath, NULL);
1545  else if (!(fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
1547  }
1548  return TRUE;
1549 }
1550 
1551 /* the FO_DELETE operation */
1553 {
1554  const FILE_ENTRY *fileEntry;
1555  DWORD i;
1556  BOOL bPathExists;
1557  BOOL bTrash;
1558 
1559  if (!flFrom->dwNumFiles)
1560  return ERROR_SUCCESS;
1561 
1562  /* Windows also checks only the first item */
1563  bTrash = (op->req->fFlags & FOF_ALLOWUNDO)
1564  && TRASH_CanTrashFile(flFrom->feFiles[0].szFullPath);
1565 
1566  if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (!bTrash && op->req->fFlags & FOF_WANTNUKEWARNING))
1567  if (!confirm_delete_list(op->req->hwnd, op->req->fFlags, bTrash, flFrom))
1568  {
1569  op->req->fAnyOperationsAborted = TRUE;
1570  return 0;
1571  }
1572 
1573  /* Check files. Do not delete one if one file does not exists */
1574  for (i = 0; i < flFrom->dwNumFiles; i++)
1575  {
1576  fileEntry = &flFrom->feFiles[i];
1577 
1578  if (fileEntry->attributes == (ULONG)-1)
1579  {
1580  // This is a windows 2003 server specific value which has been removed.
1581  // Later versions of windows return ERROR_FILE_NOT_FOUND.
1583  }
1584  }
1585 
1586  for (i = 0; i < flFrom->dwNumFiles; i++)
1587  {
1588  bPathExists = TRUE;
1589  fileEntry = &flFrom->feFiles[i];
1590 
1591  if (!IsAttribFile(fileEntry->attributes) &&
1592  (op->req->fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
1593  continue;
1594 
1595  if (bTrash)
1596  {
1597  BOOL bDelete;
1598  if (TRASH_TrashFile(fileEntry->szFullPath))
1599  {
1601  continue;
1602  }
1603 
1604  /* Note: Windows silently deletes the file in such a situation, we show a dialog */
1605  if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (op->req->fFlags & FOF_WANTNUKEWARNING))
1606  bDelete = SHELL_ConfirmDialogW(op->req->hwnd, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL);
1607  else
1608  bDelete = TRUE;
1609 
1610  if (!bDelete)
1611  {
1612  op->req->fAnyOperationsAborted = TRUE;
1613  break;
1614  }
1615  }
1616 
1617  /* delete the file or directory */
1618  if (IsAttribFile(fileEntry->attributes))
1619  {
1620  bPathExists = (ERROR_SUCCESS == SHNotifyDeleteFileW(op, fileEntry->szFullPath));
1621  }
1622  else
1623  bPathExists = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
1624 
1625  if (!bPathExists)
1626  {
1627  DWORD err = GetLastError();
1628 
1629  if (ERROR_FILE_NOT_FOUND == err)
1630  {
1631  // This is a windows 2003 server specific value which ahs been removed.
1632  // Later versions of windows return ERROR_FILE_NOT_FOUND.
1634  }
1635  else
1636  {
1637  return err;
1638  }
1639  }
1640 
1641  if (op->progress != NULL)
1642  op->bCancelled |= op->progress->HasUserCancelled();
1643  /* Should fire on progress dialog only */
1644  if (op->bCancelled)
1645  return ERROR_CANCELLED;
1646  }
1647 
1648  return ERROR_SUCCESS;
1649 }
1650 
1651 static void move_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
1652 {
1653  WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1654  FILE_LIST flFromNew, flToNew;
1655 
1656  static const WCHAR wildCardFiles[] = {'*','.','*',0};
1657 
1658  if (IsDotDir(feFrom->szFilename))
1659  return;
1660 
1661  SHNotifyCreateDirectoryW(szDestPath, NULL);
1662 
1663  PathCombineW(szFrom, feFrom->szFullPath, wildCardFiles);
1664  szFrom[lstrlenW(szFrom) + 1] = '\0';
1665 
1666  lstrcpyW(szTo, szDestPath);
1667  szTo[lstrlenW(szDestPath) + 1] = '\0';
1668 
1669  ZeroMemory(&flFromNew, sizeof(FILE_LIST));
1670  ZeroMemory(&flToNew, sizeof(FILE_LIST));
1671  parse_file_list(&flFromNew, szFrom);
1672  parse_file_list(&flToNew, szTo);
1673 
1674  move_files(op, FALSE, &flFromNew, &flToNew);
1675 
1676  destroy_file_list(&flFromNew);
1677  destroy_file_list(&flToNew);
1678 
1679  if (PathIsDirectoryEmptyW(feFrom->szFullPath))
1681 }
1682 
1683 /* moves a file or directory to another directory */
1684 static void move_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
1685 {
1686  WCHAR szDestPath[MAX_PATH];
1687 
1688  PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
1689 
1690  if (IsAttribFile(feFrom->attributes))
1691  SHNotifyMoveFileW(op, feFrom->szFullPath, szDestPath, FALSE);
1692  else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
1693  move_dir_to_dir(op, feFrom, szDestPath);
1694 }
1695 
1696 /* the FO_MOVE operation */
1697 static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1698 {
1699  DWORD i;
1700  INT mismatched = 0;
1701 
1702  const FILE_ENTRY *entryToMove;
1703  const FILE_ENTRY *fileDest;
1704 
1705  if (!flFrom->dwNumFiles)
1706  return ERROR_SUCCESS;
1707 
1708  if (!flTo->dwNumFiles)
1709  return ERROR_FILE_NOT_FOUND;
1710 
1711  if (!(multiDest) &&
1712  flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
1713  {
1714  return ERROR_CANCELLED;
1715  }
1716 
1717  if (!(multiDest) &&
1718  !flFrom->bAnyDirectories &&
1719  flFrom->dwNumFiles > flTo->dwNumFiles &&
1720  !(flTo->bAnyDirectories && flTo->dwNumFiles == 1))
1721  {
1722  return ERROR_CANCELLED;
1723  }
1724 
1725  if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
1726  return ERROR_CANCELLED;
1727 
1728  if (multiDest)
1729  mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
1730 
1731  fileDest = &flTo->feFiles[0];
1732  for (i = 0; i < flFrom->dwNumFiles; i++)
1733  {
1734  entryToMove = &flFrom->feFiles[i];
1735 
1736  if (!PathFileExistsW(fileDest->szDirectory))
1737  return ERROR_CANCELLED;
1738 
1739  if (multiDest)
1740  {
1741  if (i >= flTo->dwNumFiles)
1742  break;
1743  fileDest = &flTo->feFiles[i];
1744  if (mismatched && !fileDest->bExists)
1745  {
1747  flTo->feFiles[i].bExists = TRUE;
1749  }
1750  }
1751 
1752  if (fileDest->bExists && IsAttribDir(fileDest->attributes))
1753  move_to_dir(op, entryToMove, fileDest);
1754  else
1755  SHNotifyMoveFileW(op, entryToMove->szFullPath, fileDest->szFullPath, IsAttribDir(entryToMove->attributes));
1756 
1757  if (op->progress != NULL)
1758  op->bCancelled |= op->progress->HasUserCancelled();
1759  /* Should fire on progress dialog only */
1760  if (op->bCancelled)
1761  return ERROR_CANCELLED;
1762 
1763  }
1764 
1765  if (mismatched > 0)
1766  {
1767  if (flFrom->bAnyDirectories)
1768  return DE_DESTSAMETREE;
1769  else
1770  return DE_SAMEFILE;
1771  }
1772 
1773  return ERROR_SUCCESS;
1774 }
1775 
1776 /* the FO_RENAME files */
1777 static HRESULT rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1778 {
1779  const FILE_ENTRY *feFrom;
1780  const FILE_ENTRY *feTo;
1781 
1782  if (flFrom->dwNumFiles != 1)
1783  return ERROR_GEN_FAILURE;
1784 
1785  if (flTo->dwNumFiles != 1)
1786  return ERROR_CANCELLED;
1787 
1788  feFrom = &flFrom->feFiles[0];
1789  feTo= &flTo->feFiles[0];
1790 
1791  /* fail if destination doesn't exist */
1792  if (!feFrom->bExists)
1794 
1795  /* fail if destination already exists */
1796  if (feTo->bExists)
1797  return ERROR_ALREADY_EXISTS;
1798 
1799  return SHNotifyMoveFileW(op, feFrom->szFullPath, feTo->szFullPath, IsAttribDir(feFrom->attributes));
1800 }
1801 
1802 /* alert the user if an unsupported flag is used */
1803 static void check_flags(FILEOP_FLAGS fFlags)
1804 {
1805  WORD wUnsupportedFlags = FOF_NO_CONNECTED_ELEMENTS |
1807 #ifdef __REACTOS__
1809 #else
1811 #endif
1812 
1813  if (fFlags & wUnsupportedFlags)
1814  FIXME("Unsupported flags: %04x\n", fFlags);
1815 }
1816 
1817 #ifdef __REACTOS__
1818 
1819 static DWORD
1820 validate_operation(LPSHFILEOPSTRUCTW lpFileOp, FILE_LIST *flFrom, FILE_LIST *flTo)
1821 {
1822  DWORD i, k, dwNumDest;
1823  WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1824  CStringW strTitle, strText;
1825  const FILE_ENTRY *feFrom;
1826  const FILE_ENTRY *feTo;
1827  UINT wFunc = lpFileOp->wFunc;
1828  HWND hwnd = lpFileOp->hwnd;
1829 
1830  dwNumDest = flTo->dwNumFiles;
1831 
1832  if (wFunc != FO_COPY && wFunc != FO_MOVE)
1833  return ERROR_SUCCESS;
1834 
1835  for (k = 0; k < dwNumDest; ++k)
1836  {
1837  feTo = &flTo->feFiles[k];
1838  for (i = 0; i < flFrom->dwNumFiles; ++i)
1839  {
1840  feFrom = &flFrom->feFiles[i];
1841  StringCbCopyW(szFrom, sizeof(szFrom), feFrom->szFullPath);
1842  StringCbCopyW(szTo, sizeof(szTo), feTo->szFullPath);
1843  if (IsAttribDir(feTo->attributes))
1844  {
1845  PathAppendW(szTo, feFrom->szFilename);
1846  }
1847 
1848  // same path?
1849  if (lstrcmpiW(szFrom, szTo) == 0 &&
1850  (wFunc == FO_MOVE || !(lpFileOp->fFlags & FOF_RENAMEONCOLLISION)))
1851  {
1852  if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
1853  {
1854  if (wFunc == FO_MOVE)
1855  {
1856  strTitle.LoadStringW(IDS_MOVEERRORTITLE);
1857  if (IsAttribDir(feFrom->attributes))
1858  strText.Format(IDS_MOVEERRORSAMEFOLDER, feFrom->szFilename);
1859  else
1860  strText.Format(IDS_MOVEERRORSAME, feFrom->szFilename);
1861  }
1862  else
1863  {
1864  strTitle.LoadStringW(IDS_COPYERRORTITLE);
1865  strText.Format(IDS_COPYERRORSAME, feFrom->szFilename);
1866  return ERROR_SUCCESS;
1867  }
1868  MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
1869  return DE_SAMEFILE;
1870  }
1871  return DE_OPCANCELLED;
1872  }
1873 
1874  // subfolder?
1875  if (IsAttribDir(feFrom->attributes))
1876  {
1877  size_t cchFrom = PathAddBackslashW(szFrom) - szFrom;
1878  size_t cchTo = PathAddBackslashW(szTo) - szTo;
1879  if (cchFrom <= cchTo)
1880  {
1881  WCHAR ch = szTo[cchFrom];
1882  szTo[cchFrom] = 0;
1883  int compare = lstrcmpiW(szFrom, szTo);
1884  szTo[cchFrom] = ch;
1885 
1886  if (compare == 0)
1887  {
1888  if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
1889  {
1890  if (wFunc == FO_MOVE)
1891  {
1892  strTitle.LoadStringW(IDS_MOVEERRORTITLE);
1893  strText.Format(IDS_MOVEERRORSUBFOLDER, feFrom->szFilename);
1894  }
1895  else
1896  {
1897  strTitle.LoadStringW(IDS_COPYERRORTITLE);
1898  strText.Format(IDS_COPYERRORSUBFOLDER, feFrom->szFilename);
1899  }
1900  MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
1901  return DE_DESTSUBTREE;
1902  }
1903  return DE_OPCANCELLED;
1904  }
1905  }
1906  }
1907  }
1908  }
1909 
1910  return ERROR_SUCCESS;
1911 }
1912 #endif
1913 /*************************************************************************
1914  * SHFileOperationW [SHELL32.@]
1915  *
1916  * See SHFileOperationA
1917  */
1919 {
1921  FILE_LIST flFrom, flTo;
1922  int ret = 0;
1923 
1924  if (!lpFileOp)
1925  return ERROR_INVALID_PARAMETER;
1926 
1927  ret = CoInitialize(NULL);
1928  if (FAILED(ret))
1929  return ret;
1930 
1931  lpFileOp->fAnyOperationsAborted = FALSE;
1932  check_flags(lpFileOp->fFlags);
1933 
1934  ZeroMemory(&flFrom, sizeof(FILE_LIST));
1935  ZeroMemory(&flTo, sizeof(FILE_LIST));
1936 
1937  if ((ret = parse_file_list(&flFrom, lpFileOp->pFrom)))
1938  return ret;
1939 
1940  if (lpFileOp->wFunc != FO_DELETE)
1941  parse_file_list(&flTo, lpFileOp->pTo);
1942 
1943  ZeroMemory(&op, sizeof(op));
1944  op.req = lpFileOp;
1945  op.totalSize.QuadPart = 0ull;
1946  op.completedSize.QuadPart = 0ull;
1947  op.bManyItems = (flFrom.dwNumFiles > 1);
1948 
1949 #ifdef __REACTOS__
1950  ret = validate_operation(lpFileOp, &flFrom, &flTo);
1951  if (ret)
1952  goto cleanup;
1953 #endif
1954  if (lpFileOp->wFunc != FO_RENAME && !(lpFileOp->fFlags & FOF_SILENT)) {
1955  ret = CoCreateInstance(CLSID_ProgressDialog,
1956  NULL,
1957  CLSCTX_INPROC_SERVER,
1958  IID_PPV_ARG(IProgressDialog, &op.progress));
1959  if (FAILED(ret))
1960  goto cleanup;
1961 
1962  op.progress->StartProgressDialog(op.req->hwnd, NULL, PROGDLG_NORMAL & PROGDLG_AUTOTIME, NULL);
1964  _FileOpCountManager(&op, &flFrom);
1965  }
1966 
1967  switch (lpFileOp->wFunc)
1968  {
1969  case FO_COPY:
1970  ret = copy_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
1971  break;
1972  case FO_DELETE:
1973  ret = delete_files(&op, &flFrom);
1974  break;
1975  case FO_MOVE:
1976  ret = move_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
1977  break;
1978  case FO_RENAME:
1979  ret = rename_files(&op, &flFrom, &flTo);
1980  break;
1981  default:
1983  break;
1984  }
1985 
1986  if (op.progress) {
1987  op.progress->StopProgressDialog();
1988  op.progress->Release();
1989  }
1990 
1991 cleanup:
1992  destroy_file_list(&flFrom);
1993 
1994  if (lpFileOp->wFunc != FO_DELETE)
1995  destroy_file_list(&flTo);
1996 
1997  if (ret == ERROR_CANCELLED)
1998  lpFileOp->fAnyOperationsAborted = TRUE;
1999 
2000  CoUninitialize();
2001 
2002  return ret;
2003 }
2004 
2005 // Used by SHFreeNameMappings
2006 static int CALLBACK _DestroyCallback(void *p, void *pData)
2007 {
2009 
2010  SHFree(lp->pszOldPath);
2011  SHFree(lp->pszNewPath);
2012 
2013  return TRUE;
2014 }
2015 
2016 /*************************************************************************
2017  * SHFreeNameMappings [shell32.246]
2018  *
2019  * Free the mapping handle returned by SHFileOperation if FOF_WANTSMAPPINGHANDLE
2020  * was specified.
2021  *
2022  * PARAMS
2023  * hNameMapping [I] handle to the name mappings used during renaming of files
2024  *
2025  * RETURNS
2026  * Nothing
2027  */
2029 {
2030  if (hNameMapping)
2031  {
2032  DSA_DestroyCallback((HDSA) hNameMapping, _DestroyCallback, NULL);
2033  }
2034 }
2035 
2036 /*************************************************************************
2037  * SheGetDirA [SHELL32.@]
2038  *
2039  * drive = 0: returns the current directory path
2040  * drive > 0: returns the current directory path of the specified drive
2041  * drive=1 -> A: drive=2 -> B: ...
2042  * returns 0 if successful
2043 */
2045 {
2046  WCHAR org_path[MAX_PATH];
2047  DWORD ret;
2048  char drv_path[3];
2049 
2050  /* change current directory to the specified drive */
2051  if (drive) {
2052  strcpy(drv_path, "A:");
2053  drv_path[0] += (char)drive-1;
2054 
2055  GetCurrentDirectoryW(MAX_PATH, org_path);
2056 
2057  SetCurrentDirectoryA(drv_path);
2058  }
2059 
2060  /* query current directory path of the specified drive */
2062 
2063  /* back to the original drive */
2064  if (drive)
2065  SetCurrentDirectoryW(org_path);
2066 
2067  if (!ret)
2068  return GetLastError();
2069 
2070  return 0;
2071 }
2072 
2073 /*************************************************************************
2074  * SheGetDirW [SHELL32.@]
2075  *
2076  * drive = 0: returns the current directory path
2077  * drive > 0: returns the current directory path of the specified drive
2078  * drive=1 -> A: drive=2 -> B: ...
2079  * returns 0 if successful
2080  */
2082 {
2083  WCHAR org_path[MAX_PATH];
2084  DWORD ret;
2085  char drv_path[3];
2086 
2087  /* change current directory to the specified drive */
2088  if (drive)
2089  {
2090  strcpy(drv_path, "A:");
2091  drv_path[0] += (char)drive-1;
2092 
2093  GetCurrentDirectoryW(MAX_PATH, org_path);
2094 
2095  SetCurrentDirectoryA(drv_path);
2096  }
2097 
2098  /* query current directory path of the specified drive */
2100 
2101  /* back to the original drive */
2102  if (drive)
2103  SetCurrentDirectoryW(org_path);
2104 
2105  if (!ret)
2106  return GetLastError();
2107 
2108  return 0;
2109 }
2110 
2111 /*************************************************************************
2112  * SheChangeDirA [SHELL32.@]
2113  *
2114  * changes the current directory to the specified path
2115  * and returns 0 if successful
2116  */
2118 {
2120  return 0;
2121  else
2122  return GetLastError();
2123 }
2124 
2125 /*************************************************************************
2126  * SheChangeDirW [SHELL32.@]
2127  *
2128  * changes the current directory to the specified path
2129  * and returns 0 if successful
2130  */
2132 {
2134  return 0;
2135  else
2136  return GetLastError();
2137 }
2138 
2139 /*************************************************************************
2140  * IsNetDrive [SHELL32.66]
2141  */
2143 {
2144  char root[4];
2145  strcpy(root, "A:\\");
2146  root[0] += (char)drive;
2147  return (GetDriveTypeA(root) == DRIVE_REMOTE);
2148 }
2149 
2150 
2151 /*************************************************************************
2152  * RealDriveType [SHELL32.524]
2153  */
2155 {
2156  char root[] = "A:\\";
2157  root[0] += (char)drive;
2158  return GetDriveTypeA(root);
2159 }
2160 
2161 /***********************************************************************
2162  * SHPathPrepareForWriteW (SHELL32.@)
2163  */
2165 {
2166  DWORD res;
2167  DWORD err;
2168  LPCWSTR realpath;
2169  int len;
2170  WCHAR* last_slash;
2171  WCHAR* temppath=NULL;
2172 
2173  TRACE("%p %p %s 0x%08x\n", hwnd, modless, debugstr_w(path), flags);
2174 
2176  FIXME("unimplemented flags 0x%08x\n", flags);
2177 
2178  /* cut off filename if necessary */
2180  {
2181  last_slash = StrRChrW(path, NULL, '\\');
2182  if (last_slash == NULL)
2183  len = 1;
2184  else
2185  len = last_slash - path + 1;
2186  temppath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2187  if (!temppath)
2188  return E_OUTOFMEMORY;
2189  StrCpyNW(temppath, path, len);
2190  realpath = temppath;
2191  }
2192  else
2193  {
2194  realpath = path;
2195  }
2196 
2197  /* try to create the directory if asked to */
2199  {
2200  if (flags & SHPPFW_ASKDIRCREATE)
2201  FIXME("treating SHPPFW_ASKDIRCREATE as SHPPFW_DIRCREATE\n");
2202 
2203  SHCreateDirectoryExW(0, realpath, NULL);
2204  }
2205 
2206  /* check if we can access the directory */
2207  res = GetFileAttributesW(realpath);
2208 
2209  HeapFree(GetProcessHeap(), 0, temppath);
2210 
2212  {
2213  err = GetLastError();
2214  if (err == ERROR_FILE_NOT_FOUND)
2216  return HRESULT_FROM_WIN32(err);
2217  }
2218  else if (res & FILE_ATTRIBUTE_DIRECTORY)
2219  return S_OK;
2220  else
2222 }
2223 
2224 /***********************************************************************
2225  * SHPathPrepareForWriteA (SHELL32.@)
2226  */
2228 {
2229  WCHAR wpath[MAX_PATH];
2230  MultiByteToWideChar( CP_ACP, 0, path, -1, wpath, MAX_PATH);
2231  return SHPathPrepareForWriteW(hwnd, modless, wpath, flags);
2232 }
2233 
2234 
2235 /*
2236  * The two following background operations were modified from filedefext.cpp
2237  * They use an inordinate amount of mutable state across the string functions,
2238  * so are not easy to follow and care is required when modifying.
2239  */
2240 
2241 DWORD WINAPI
2243 {
2244  DWORD ticks = GetTickCount();
2245  FILE_ENTRY *entryToCount;
2246 
2247  for (UINT i = 0; i < from->dwNumFiles; i++)
2248  {
2249  entryToCount = &from->feFiles[i];
2250 
2251  WCHAR theFileName[MAX_PATH];
2252  StringCchCopyW(theFileName, MAX_PATH, entryToCount->szFullPath);
2253  _FileOpCount(op, theFileName, IsAttribDir(entryToCount->attributes), &ticks);
2254  }
2255  return 0;
2256 }
2257 
2258 // All path manipulations, even when this function is nested, occur on the one buffer.
2259 static BOOL
2260 _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks)
2261 {
2262  /* Find filename position */
2263  UINT cchBuf = wcslen(pwszBuf);
2264  WCHAR *pwszFilename = pwszBuf + cchBuf;
2265  size_t cchFilenameMax = MAX_PATH - cchBuf;
2266  if (!cchFilenameMax)
2267  return FALSE;
2268 
2269  if (bFolder) {
2270  *(pwszFilename++) = '\\';
2271  --cchFilenameMax;
2272  /* Find all files, FIXME: shouldn't be "*"? */
2273  StringCchCopyW(pwszFilename, cchFilenameMax, L"*");
2274  }
2275 
2276  WIN32_FIND_DATAW wfd;
2277  HANDLE hFind = FindFirstFileW(pwszBuf, &wfd);
2278  if (hFind == INVALID_HANDLE_VALUE)
2279  {
2280  ERR("FindFirstFileW %ls failed\n", pwszBuf);
2281  return FALSE;
2282  }
2283 
2284  do
2285  {
2286  if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2287  {
2288  /* Don't process "." and ".." items */
2289  if (!wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L".."))
2290  continue;
2291 
2292  StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName);
2293  _FileOpCount(op, pwszBuf, TRUE, ticks);
2294  }
2295  else
2296  {
2298  FileSize.u.LowPart = wfd.nFileSizeLow;
2299  FileSize.u.HighPart = wfd.nFileSizeHigh;
2300  op->totalSize.QuadPart += FileSize.QuadPart;
2301  }
2302  if (GetTickCount() - *ticks > (DWORD) 500)
2303  {
2304  // Check if the dialog has ended. If it has, we'll spin down.
2305  if (op->progress != NULL)
2306  op->bCancelled = op->progress->HasUserCancelled();
2307 
2308  if (op->bCancelled)
2309  break;
2310  *ticks = GetTickCount();
2311  }
2312  } while(FindNextFileW(hFind, &wfd));
2313 
2314  FindClose(hFind);
2315  return TRUE;
2316 }
static HRESULT parse_file_list(FILE_LIST *flList, LPCWSTR szFiles)
Definition: shlfileop.cpp:1150
HINSTANCE hIconInstance
Definition: shlfileop.cpp:222
#define SHCNE_MKDIR
Definition: shlobj.h:1732
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
#define IDS_FILEOOP_MOVING
Definition: shresdef.h:222
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
Definition: bug.cpp:7
static const WCHAR CONFIRM_MSG_PROP[]
Definition: shlfileop.cpp:90
#define ASK_CANT_TRASH_ITEM
Definition: shell32_main.h:121
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define STM_SETICON
Definition: winuser.h:2074
static HRESULT rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
Definition: shlfileop.cpp:1777
#define MAKEINTRESOURCE
Definition: winuser.h:591
static void SHELL32_FreeUnicodeBuf(LPWSTR wPath)
Definition: shlfileop.cpp:357
const uint16_t * PCWSTR
Definition: typedefs.h:57
LPWSTR WINAPI StrPBrkW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
Definition: string.c:1276
GLint GLint GLsizei width
Definition: gl.h:1546
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
#define FOF_NOCOPYSECURITYATTRIBS
Definition: shellapi.h:149
static HICON
Definition: imagelist.c:84
#define FOF_NO_CONNECTED_ELEMENTS
Definition: shellapi.h:151
#define SHCNE_RMDIR
Definition: shlobj.h:1733
BOOL WINAPI PathIsRelativeW(LPCWSTR lpszPath)
Definition: path.c:1558
#define IDS_MOVEERRORSAMEFOLDER
Definition: shresdef.h:236
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
#define IDI_SHELL_CONFIRM_DELETE
Definition: shresdef.h:569
INT_PTR WINAPI DialogBoxParamW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
DWORD WINAPI _FileOpCountManager(FILE_OPERATION *op, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:2242
SHFILEOPSTRUCTW * req
Definition: shlfileop.cpp:43
#define ERROR_SUCCESS
Definition: deptool.c:10
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define DWORD_PTR
Definition: treelist.c:76
#define IDYES
Definition: winuser.h:829
ULARGE_INTEGER totalSize
Definition: shlfileop.cpp:49
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static INT_PTR ConfirmMsgBox_Paint(HWND hDlg)
Definition: shlfileop.cpp:127
#define DE_OPCANCELLED
Definition: shlfileop.c:45
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
PVOID hNameMappings
Definition: shellapi.h:359
HDC WINAPI GetDC(_In_opt_ HWND)
LPWSTR szFullPath
Definition: shlfileop.cpp:60
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
#define IDS_FILEOOP_FROM
Definition: shresdef.h:225
GLsizei const GLchar ** path
Definition: glext.h:7234
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define SW_HIDE
Definition: winuser.h:762
static INT_PTR ConfirmMsgBox_Init(HWND hDlg, LPARAM lParam)
Definition: shlfileop.cpp:149
FILEOP_FLAGS fFlags
Definition: shellapi.h:347
uint16_t * PWSTR
Definition: typedefs.h:56
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define FO_COPY
Definition: shellapi.h:134
static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minChars)
Definition: shlfileop.cpp:341
#define ASK_DELETE_FILE
Definition: shell32_main.h:112
#define FOF_SILENT
Definition: shellapi.h:140
#define IDD_YESTOALL_MSGBOX
Definition: shresdef.h:378
#define CP_ACP
Definition: compat.h:109
const GLint * attribs
Definition: glext.h:10538
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:405
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:402
#define IDS_OVERWRITEFILE_CAPTION
Definition: shresdef.h:118
#define ASK_TRASH_FILE
Definition: shell32_main.h:118
#define DT_WORDBREAK
Definition: winuser.h:544
#define IDS_DELETEITEM_CAPTION
Definition: shresdef.h:114
LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count)
Definition: string.c:536
static const WCHAR szFrom[]
Definition: http.c:101
static void confirm_msg_move_button(HWND hDlg, INT iId, INT *xPos, INT yOffset, BOOL bShow)
Definition: shlfileop.cpp:102
static HDC
Definition: imagelist.c:92
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:615
#define CALLBACK
Definition: compat.h:35
#define ASK_DELETE_SELECTED
Definition: shell32_main.h:117
HWND hWnd
Definition: settings.c:17
#define ERROR_NO_MORE_SEARCH_HANDLES
Definition: winerror.h:187
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
static CStringW try_find_new_name(LPCWSTR szDestPath)
Definition: shlfileop.cpp:1237
#define FO_MASK
Definition: shlfileop.cpp:34
#define FOF_ALLOWUNDO
Definition: shellapi.h:144
static HRESULT delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:1552
#define IDS_OVERWRITEFOLDER_TEXT
Definition: shresdef.h:125
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1499
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
#define ASK_TRASH_FOLDER
Definition: shell32_main.h:119
#define FOF_WANTNUKEWARNING
Definition: shellapi.h:152
#define CALLBACK_STREAM_SWITCH
Definition: winbase.h:151
#define assert(x)
Definition: debug.h:53
#define IDS_COPYERRORSAME
Definition: shresdef.h:238
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
BOOL bAnyFromWildcard
Definition: shlfileop.cpp:71
#define ZeroMemory
Definition: winbase.h:1648
EXTERN_C DWORD WINAPI SheGetDirW(DWORD drive, LPWSTR buffer)
Definition: shlfileop.cpp:2081
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:716
GLuint buffer
Definition: glext.h:5915
BOOL SHELL_ConfirmYesNoW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir)
Definition: shlfileop.cpp:336
DWORD attributes
Definition: shlfileop.cpp:57
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
UINT_PTR WPARAM
Definition: windef.h:207
#define ASK_TRASH_MULTIPLE_ITEM
Definition: shell32_main.h:120
const TCHAR * szFiles[]
Definition: CImage.cpp:17
void WINAPI SHFreeNameMappings(HANDLE hNameMapping)
Definition: shlfileop.cpp:2028
static DWORD SHNotifyMoveFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BOOL isdir)
Definition: shlfileop.cpp:679
EXTERN_C INT WINAPI RealDriveType(INT drive, BOOL bQueryNet)
Definition: shlfileop.cpp:2154
BOOL bFromRelative
Definition: shlfileop.cpp:62
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo)
Definition: shlfileop.cpp:1402
ULARGE_INTEGER completedSize
Definition: shlfileop.cpp:48
int32_t INT_PTR
Definition: typedefs.h:64
char * LPSTR
Definition: xmlstorage.h:182
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
FILEOP_FLAGS fFlags
Definition: shellapi.h:357
#define FO_RENAME
Definition: shellapi.h:136
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_DIRECTORY
Definition: winerror.h:295
#define DT_NOPREFIX
Definition: winuser.h:537
#define lstrlenW
Definition: compat.h:609
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
static void _SetOperationTitle(FILE_OPERATION *op)
Definition: shlfileop.cpp:480
Definition: match.c:390
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:58
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1918
#define IDI_SHELL_FOLDER_MOVE2
Definition: shresdef.h:642
BOOL WINAPI EndDialog(_In_ HWND, _In_ INT_PTR)
WPARAM wParam
Definition: combotst.c:138
EXTERN_C int WINAPI IsNetDrive(int drive)
Definition: shlfileop.cpp:2142
struct _ULARGE_INTEGER::@3873 u
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define lstrcpynW
Definition: compat.h:597
BOOL WINAPI PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend)
Definition: path.c:121
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
BOOL bExists
Definition: shlfileop.cpp:63
#define IDS_MOVEERRORTITLE
Definition: shresdef.h:234
#define FO_MOVE
Definition: shellapi.h:133
EXTERN_C HRESULT WINAPI SHPathPrepareForWriteW(HWND hwnd, IUnknown *modless, LPCWSTR path, DWORD flags)
Definition: shlfileop.cpp:2164
#define MB_ICONEXCLAMATION
Definition: winuser.h:779
#define IDS_DELETEFOLDER_CAPTION
Definition: shresdef.h:115
#define DT_PATH_ELLIPSIS
Definition: winuser.h:530
IProgressDialog * progress
Definition: shlfileop.cpp:47
GLuint * ids
Definition: glext.h:5907
BOOL fAnyOperationsAborted
Definition: shellapi.h:358
static BOOL _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks)
Definition: shlfileop.cpp:2260
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1034
#define SM_CXSCREEN
Definition: winuser.h:949
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static void check_flags(FILEOP_FLAGS fFlags)
Definition: shlfileop.cpp:1803
#define DRIVE_REMOTE
Definition: winbase.h:250
#define IDC_YESTOALL_MESSAGE
Definition: shresdef.h:381
#define IDS_CREATEFOLDER_DENIED
Definition: shresdef.h:112
GLenum GLint GLuint mask
Definition: glext.h:6028
#define IDS_MOVEERRORSAME
Definition: shresdef.h:237
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
Definition: dsa.c:44
static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
Definition: shlfileop.cpp:421
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
static const WCHAR szText[]
Definition: dialog.c:139
#define DT_CALCRECT
Definition: winuser.h:526
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:289
#define SHPPFW_DIRCREATE
Definition: shlobj.h:303
unsigned int BOOL
Definition: ntddk_ex.h:94
static const WCHAR wWildcardChars[]
Definition: shlfileop.cpp:39
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
DWORD num_alloc
Definition: shlfileop.cpp:69
EXTERN_C BOOL WINAPI Win32RemoveDirectoryW(LPCWSTR path)
Definition: shlfileop.cpp:475
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
#define debugstr_w
Definition: kernel32.h:32
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:111
BOOL WINAPI MoveFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
Definition: move.c:1044
BOOL bAnyDirectories
Definition: shlfileop.cpp:72
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
LPCSTR lpszProgressTitle
Definition: shellapi.h:350
DWORD dwNumFiles
Definition: shlfileop.cpp:70
#define TRANSPARENT
Definition: wingdi.h:949
static void destroy_file_list(FILE_LIST *flList)
Definition: shlfileop.cpp:1220
#define FOF_NOERRORUI
Definition: shellapi.h:148
static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
Definition: shlfileop.cpp:1697
#define FOF_NOCONFIRMATION
Definition: shellapi.h:142
#define IDA_SHELL_DELETE
Definition: shresdef.h:750
smooth NULL
Definition: ftsmooth.c:416
#define WM_GETFONT
Definition: winuser.h:1633
char ext[3]
Definition: mkdosfs.c:358
LPCWSTR lpszProgressTitle
Definition: shellapi.h:360
unsigned char
Definition: typeof.h:29
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:389
LONG_PTR LPARAM
Definition: windef.h:208
char * va_list
Definition: acmsvcex.h:78
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1756
#define IDS_FILEOOP_DELETING
Definition: shresdef.h:223
static INT_PTR CALLBACK ConfirmMsgBoxProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: shlfileop.cpp:190
static const WCHAR sizeW[]
Definition: editor.c:79
static void copy_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
Definition: shlfileop.cpp:1366
DWORD dwYesToAllMask
Definition: shlfileop.cpp:44
unsigned int dir
Definition: maze.c:112
const char * LPCSTR
Definition: xmlstorage.h:183
static BOOL SHELL_ConfirmIDs(int nKindOfDialog, SHELL_ConfirmIDstruc *ids)
Definition: shlfileop.cpp:227
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:442
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static void parse_wildcard_files(FILE_LIST *flList, LPCWSTR szFile, LPDWORD pdwListIndex)
Definition: shlfileop.cpp:1116
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
#define ASK_DELETE_FOLDER
Definition: shell32_main.h:113
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define IDS_DELETEITEM_TEXT
Definition: shresdef.h:116
static void __inline grow_list(FILE_LIST *list)
Definition: shlfileop.cpp:1058
#define FOF_WANTMAPPINGHANDLE
Definition: shellapi.h:143
static int CALLBACK _DestroyCallback(void *p, void *pData)
Definition: shlfileop.cpp:2006
#define SM_CYSCREEN
Definition: winuser.h:950
static const WCHAR wWildcardFile[]
Definition: shlfileop.cpp:38
LPWSTR szFilename
Definition: shlfileop.cpp:59
#define TRACE(s)
Definition: solgame.cpp:4
static LPSTR pName
Definition: security.c:75
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:595
LPWSTR pszNewPath
Definition: shellapi.h:389
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
BOOL WINAPI SetPropW(_In_ HWND, _In_ LPCWSTR, _In_opt_ HANDLE)
static void add_file_to_entry(FILE_ENTRY *feFile, LPCWSTR szFile)
Definition: shlfileop.cpp:1068
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
WINE_DEFAULT_DEBUG_CHANNEL(shell)
#define debugstr_a
Definition: kernel32.h:31
LONG HRESULT
Definition: typedefs.h:79
#define _countof(array)
Definition: sndvol32.h:68
#define ASK_DELETE_MULTIPLE_ITEM
Definition: shell32_main.h:114
#define WM_CLOSE
Definition: winuser.h:1603
#define FOF_FILESONLY
Definition: shellapi.h:145
_In_ LPCSTR pszDir
Definition: shellapi.h:582
#define IDI_SHELL_TRASH_FILE
Definition: shresdef.h:554
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
#define SHPPFW_ASKDIRCREATE
Definition: shlobj.h:305
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
unsigned long DWORD
Definition: ntddk_ex.h:95
UINT op
Definition: effect.c:224
int WINAPI SHCreateDirectoryExA(HWND hWnd, LPCSTR path, LPSECURITY_ATTRIBUTES sec)
Definition: shlfileop.cpp:825
#define SetLastError(x)
Definition: compat.h:611
LRESULT WINAPI SendDlgItemMessageW(_In_ HWND, _In_ int, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define PROGDLG_AUTOTIME
Definition: shlobj.h:893
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define PROGDLG_NORMAL
Definition: shlobj.h:891
static BOOL SHELL_ConfirmDialogW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir, FILE_OPERATION *op)
Definition: shlfileop.cpp:298
#define IDS_TRASHFOLDER_TEXT
Definition: shresdef.h:121
TCHAR szTitle[MAX_LOADSTRING]
Definition: magnifier.c:35
static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path)
Definition: shlfileop.cpp:451
GLbitfield flags
Definition: glext.h:7161
static BOOL copy_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCHAR *szTo)
Definition: shlfileop.cpp:1330
#define WM_PAINT
Definition: winuser.h:1602
#define DE_DESTSAMETREE
Definition: shlfileop.c:48
BOOL bFromWildcard
Definition: shlfileop.cpp:61
#define IDS_FILEOOP_COPYING
Definition: shresdef.h:221
#define FOF_SIMPLEPROGRESS
Definition: shellapi.h:146
BOOL fAnyOperationsAborted
Definition: shellapi.h:348
static void create_dest_dirs(LPCWSTR szDestDir)
Definition: shlfileop.cpp:1382
static void move_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
Definition: shlfileop.cpp:1651
PVOID hNameMappings
Definition: shellapi.h:349
LPCWSTR pFrom
Definition: shellapi.h:355
int ret
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
EXTERN_C DWORD WINAPI SheChangeDirA(LPSTR path)
Definition: shlfileop.cpp:2117
static DWORD SHNotifyCopyFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists)
Definition: shlfileop.cpp:730
static const WCHAR L[]
Definition: oid.c:1250
HDC hdc
Definition: main.c:9
#define ASK_OVERWRITE_FILE
Definition: shell32_main.h:116
#define MB_ICONERROR
Definition: winuser.h:781
#define IDA_SHELL_COPY
Definition: shresdef.h:746
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2205
#define IDS_OVERWRITEFILE_TEXT
Definition: resource.h:61
#define IDS_CREATEFOLDER_CAPTION
Definition: shresdef.h:113
GLenum GLsizei len
Definition: glext.h:6722
#define IDS_COPYERRORSUBFOLDER
Definition: shresdef.h:240
#define IDS_DELETEMULTIPLE_TEXT
Definition: shresdef.h:117
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
EXTERN_C DWORD WINAPI SheChangeDirW(LPWSTR path)
Definition: shlfileop.cpp:2131
BOOL WINAPI CopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags)
Definition: copy.c:318
#define FOF_NORECURSEREPARSE
Definition: shellapi.h:154
#define IDS_FILEOOP_PREFLIGHT
Definition: shresdef.h:226
GLenum src
Definition: glext.h:6340
#define err(...)
#define WM_COMMAND
Definition: winuser.h:1722
#define IDC_YESTOALL_ICON
Definition: shresdef.h:380
int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt,...)
Definition: wsprintf.c:564
uint32_t DWORD_PTR
Definition: typedefs.h:65
_In_ HANDLE hFile
Definition: mswsock.h:90
BOOL WINAPI MoveWindow(_In_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ BOOL)
static DWORD SHNotifyDeleteFileW(FILE_OPERATION *op, LPCWSTR path)
Definition: shlfileop.cpp:610
EXTERN_C BOOL WINAPI Win32CreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
Definition: shlfileop.cpp:435
Definition: shlfileop.cpp:55
#define lstrcmp
Definition: winbase.h:3712
EXTERN_C DWORD WINAPI Win32DeleteFileW(LPCWSTR path)
Definition: shlfileop.cpp:661
EXTERN_C HRESULT WINAPI SHPathPrepareForWriteA(HWND hwnd, IUnknown *modless, LPCSTR path, DWORD flags)
Definition: shlfileop.cpp:2227
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
DWORD CALLBACK SHCopyProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
Definition: shlfileop.cpp:563
LPWSTR szDirectory
Definition: shlfileop.cpp:58
#define SHCNF_PATHW
Definition: shlobj.h:1764
#define FOF_RENAMEONCOLLISION
Definition: shellapi.h:141
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
#define ERR(fmt,...)
Definition: debug.h:110
int WINAPI SHCreateDirectory(HWND hWnd, LPCWSTR path)
Definition: shlfileop.cpp:788
void WINAPI DSA_DestroyCallback(HDSA hdsa, PFNDSAENUMCALLBACK enumProc, LPVOID lParam)
Definition: dsa.c:432
static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:1529
bool IsEmpty() const
Definition: atlsimpstr.h:379
#define IsAttribDir(x)
Definition: shlfileop.cpp:31
static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly)
Definition: shlfileop.cpp:909
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define IDS_COPYERRORTITLE
Definition: shresdef.h:235
#define IDS_MOVEERRORSUBFOLDER
Definition: shresdef.h:239
#define S_OK
Definition: intsafe.h:51
BOOL WINAPI PathIsDirectoryEmptyW(LPCWSTR lpszPath)
Definition: path.c:3910
#define shell32_hInstance
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define IDC_YESTOALL
Definition: shresdef.h:379
#define lstrcpyW
Definition: compat.h:608
#define ERROR_CANCELLED
Definition: winerror.h:726
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
HICON hIcon
Definition: msconfig.c:44
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
int WINAPI SHCreateDirectoryExW(HWND hWnd, LPCWSTR path, LPSECURITY_ATTRIBUTES sec)
Definition: shlfileop.cpp:846
#define SHCNE_DELETE
Definition: shlobj.h:1731
BOOL TRASH_TrashFile(LPCWSTR wszPath)
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2248
#define NEW_FILENAME_ON_COPY_TRIES
Definition: shlfileop.cpp:36
#define HeapReAlloc
Definition: compat.h:593
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2145
#define list
Definition: rosglue.h:35
#define ShellMessageBoxW
Definition: precomp.h:58
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:468
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define IDS_DELETESELECTED_TEXT
Definition: shresdef.h:120
#define MB_OK
Definition: winuser.h:784
HANDLE WINAPI GetPropW(_In_ HWND, _In_ LPCWSTR)
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:667
#define IsAttrib(x, y)
Definition: shlfileop.cpp:29
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define ASK_OVERWRITE_FOLDER
Definition: shell32_main.h:122
#define MultiByteToWideChar
Definition: compat.h:110
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp)
Definition: shlfileop.cpp:1000
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:331
static DWORD _ConvertAtoW(PCSTR strSrc, PCWSTR *pStrDest, BOOL isList)
Definition: shlfileop.cpp:938
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
#define DE_DESTSUBTREE
Definition: shlfileop.c:46
#define IsDotDir(x)
Definition: shlfileop.cpp:32
EXTERN_C HRESULT WINAPI SHIsFileAvailableOffline(LPCWSTR path, LPDWORD status)
Definition: shlfileop.cpp:362
BOOL SHELL_DeleteDirectoryW(FILE_OPERATION *op, LPCWSTR pszDir, BOOL bShowUI)
Definition: shlfileop.cpp:374
GLuint res
Definition: glext.h:9613
LPWSTR pszOldPath
Definition: shellapi.h:388
uint32_t * LPDWORD
Definition: typedefs.h:59
#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND
Definition: shlfileop.cpp:53
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
unsigned int ULONG
Definition: retypes.h:1
HICON WINAPI LoadIconW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2044
#define IDS_TRASHMULTIPLE_TEXT
Definition: shresdef.h:123
WORD FILEOP_FLAGS
Definition: shellapi.h:211
char * cleanup(char *str)
Definition: wpickclick.c:99
CAtlStringW CStringW
Definition: atlstr.h:130
#define DE_SAMEFILE
Definition: shlfileop.c:42
#define SHPPFW_IGNOREFILENAME
Definition: shlobj.h:306
BOOL TRASH_CanTrashFile(LPCWSTR wszPath)
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
static char * dest
Definition: rtl.c:135
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
static LPWSTR wildcard_to_file(LPCWSTR szWildCard, LPCWSTR szFileName)
Definition: shlfileop.cpp:1094
#define IDS_TRASHITEM_TEXT
Definition: shresdef.h:122
const char * PCSTR
Definition: typedefs.h:52
int yOffset
Definition: appswitch.c:59
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define SHCNE_CREATE
Definition: shlobj.h:1730
struct _LARGE_INTEGER::@2267 u
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define FOF_MULTIDESTFILES
Definition: shellapi.h:138
#define IDNO
Definition: winuser.h:830
#define ERROR_GEN_FAILURE
Definition: winerror.h:134
static void _SetOperationTexts(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest)
Definition: shlfileop.cpp:513
LPWSTR lpszCaption
Definition: shlfileop.cpp:95
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define IDCANCEL
Definition: winuser.h:825
BOOL WINAPI ScreenToClient(_In_ HWND, _Inout_ LPPOINT)
#define IsAttribFile(x)
Definition: shlfileop.cpp:30
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
CardRegion * from
Definition: spigame.cpp:19
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
Definition: string.c:556
#define EXTERN_C
Definition: basetyps.h:12
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
LPWSTR WINAPI PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile)
Definition: path.c:189
int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll)
Definition: shlfileop.cpp:208
#define FO_DELETE
Definition: shellapi.h:135
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define WM_INITDIALOG
Definition: winuser.h:1721
LPARAM lParam
Definition: combotst.c:139
int k
Definition: mpi.c:3369
#define IDS_CANTTRASH_TEXT
Definition: shresdef.h:124
static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
Definition: shlfileop.cpp:1265
static void move_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
Definition: shlfileop.cpp:1684
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:594
BOOL bAnyDontExist
Definition: shlfileop.cpp:73
#define IDS_FILEOOP_FROM_TO
Definition: shresdef.h:224
EXTERN_C DWORD WINAPI SheGetDirA(DWORD drive, LPSTR buffer)
Definition: shlfileop.cpp:2044
LONGLONG QuadPart
Definition: typedefs.h:114
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:17
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
Definition: fci.c:126
struct _FILE_ENTRY FILE_ENTRY
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
FILE_ENTRY * feFiles
Definition: shlfileop.cpp:68
Definition: ps.c:97