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