ReactOS 0.4.15-dev-5863-g1fe3ab7
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
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#ifdef __REACTOS__
662/************************************************************************
663 * CheckForError [internal]
664 *
665 * Show message box if operation failed
666 *
667 * PARAMS
668 * op [I] File Operation context
669 * error [I] Error code
670 * src [I] Source file full name
671 *
672 */
673static DWORD CheckForError(FILE_OPERATION *op, DWORD error, LPCWSTR src)
674{
675 CStringW strTitle, strMask, strText;
676 LPWSTR lpMsgBuffer;
677
678 if (error == ERROR_SUCCESS || (op->req->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
679 goto exit;
680
681 strTitle.LoadStringW(op->req->wFunc == FO_COPY ? IDS_COPYERRORTITLE : IDS_MOVEERRORTITLE);
682
684 NULL,
685 error,
687 (LPWSTR)&lpMsgBuffer,
688 0,
689 NULL);
690
691 strText.Format(op->req->wFunc == FO_COPY ? IDS_COPYERROR : IDS_MOVEERROR,
693 lpMsgBuffer);
694
695 MessageBoxW(op->req->hwnd, strText, strTitle, MB_ICONERROR);
696 LocalFree(lpMsgBuffer);
697
698exit:
699 return error;
700}
701#endif
702
703/************************************************************************
704 * SHNotifyMoveFile [internal]
705 *
706 * Moves a file. Also triggers a change notify if one exists.
707 *
708 * PARAMS
709 * op [I] File Operation context
710 * src [I] path to source file to move
711 * dest [I] path to target file to move to
712 *
713 * RETURNS
714 * ERROR_SUCCESS if successful
715 */
717{
718 BOOL ret;
719
720 TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest));
721
723
725
726 /* MOVEFILE_REPLACE_EXISTING fails with dirs, so try MoveFile */
727 if (!ret)
728 ret = MoveFileW(src, dest);
729
730 if (!ret)
731 {
732 DWORD dwAttr;
733
734 dwAttr = SHFindAttrW(dest, FALSE);
735 if (INVALID_FILE_ATTRIBUTES == dwAttr)
736 {
737 /* Source file may be write protected or a system file */
738 dwAttr = GetFileAttributesW(src);
741 ret = MoveFileW(src, dest);
742 }
743 }
744 if (ret)
745 {
748 return ERROR_SUCCESS;
749 }
750
751#ifdef __REACTOS__
752 return CheckForError(op, GetLastError(), src);
753#else
754 return GetLastError();
755#endif
756}
757
759{
760 WCHAR tmp[] = { L"A:\\" };
761
762 if (!path || !path[0])
763 return FALSE;
764
765 if (path[1] != UNICODE_NULL && path[1] != ':')
766 return FALSE;
767
768 tmp[0] = path[0];
769
770 return GetDriveTypeW(tmp) == DRIVE_CDROM;
771}
772
773/************************************************************************
774 * SHNotifyCopyFile [internal]
775 *
776 * Copies a file. Also triggers a change notify if one exists.
777 *
778 * PARAMS
779 * src [I] path to source file to move
780 * dest [I] path to target file to move to
781 * bFailIfExists [I] if TRUE, the target file will not be overwritten if
782 * a file with this name already exists
783 *
784 * RETURNS
785 * ERROR_SUCCESS if successful
786 */
788{
789 BOOL ret;
791
792 TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : "");
793
795
796 /* Destination file may already exist with read only attribute */
800
802 {
805 {
806 TRACE("[shell32, SHNotifyCopyFileW] STILL SHIT\n");
807 }
808 }
809
810 ret = CopyFileExW(src, dest, SHCopyProgressRoutine, op, &op->bCancelled, bFailIfExists);
811 if (ret)
812 {
813 // We are copying from a CD-ROM volume, which is readonly
814 if (SHIsCdRom(src))
815 {
817 attribs &= ~FILE_ATTRIBUTE_READONLY;
819 }
820
822 return ERROR_SUCCESS;
823 }
824
825#ifdef __REACTOS__
826 return CheckForError(op, GetLastError(), src);
827#else
828 return GetLastError();
829#endif
830}
831
832/*************************************************************************
833 * SHCreateDirectory [SHELL32.165]
834 *
835 * This function creates a file system folder whose fully qualified path is
836 * given by path. If one or more of the intermediate folders do not exist,
837 * they will be created as well.
838 *
839 * PARAMS
840 * hWnd [I]
841 * path [I] path of directory to create
842 *
843 * RETURNS
844 * ERROR_SUCCESS or one of the following values:
845 * ERROR_BAD_PATHNAME if the path is relative
846 * ERROR_FILE_EXISTS when a file with that name exists
847 * ERROR_PATH_NOT_FOUND can't find the path, probably invalid
848 * ERROR_INVALID_NAME if the path contains invalid chars
849 * ERROR_ALREADY_EXISTS when the directory already exists
850 * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
851 *
852 * NOTES
853 * exported by ordinal
854 * Win9x exports ANSI
855 * WinNT/2000 exports Unicode
856 */
858{
860}
861
862/*************************************************************************
863 * SHCreateDirectoryExA [SHELL32.@]
864 *
865 * This function creates a file system folder whose fully qualified path is
866 * given by path. If one or more of the intermediate folders do not exist,
867 * they will be created as well.
868 *
869 * PARAMS
870 * hWnd [I]
871 * path [I] path of directory to create
872 * sec [I] security attributes to use or NULL
873 *
874 * RETURNS
875 * ERROR_SUCCESS or one of the following values:
876 * ERROR_BAD_PATHNAME or ERROR_PATH_NOT_FOUND if the path is relative
877 * ERROR_INVALID_NAME if the path contains invalid chars
878 * ERROR_FILE_EXISTS when a file with that name exists
879 * ERROR_ALREADY_EXISTS when the directory already exists
880 * ERROR_FILENAME_EXCED_RANGE if the filename was too long to process
881 *
882 * FIXME: Not implemented yet;
883 * SHCreateDirectoryEx also verifies that the files in the directory will be visible
884 * if the path is a network path to deal with network drivers which might have a limited
885 * but unknown maximum path length. If not:
886 *
887 * If hWnd is set to a valid window handle, a message box is displayed warning
888 * the user that the files may not be accessible. If the user chooses not to
889 * proceed, the function returns ERROR_CANCELLED.
890 *
891 * If hWnd is set to NULL, no user interface is displayed and the function
892 * returns ERROR_CANCELLED.
893 */
895{
896 LPWSTR wPath;
897 DWORD retCode;
898
899 TRACE("(%s, %p)\n", debugstr_a(path), sec);
900
901 retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
902 if (!retCode)
903 {
904 retCode = SHCreateDirectoryExW(hWnd, wPath, sec);
906 }
907 return retCode;
908}
909
910/*************************************************************************
911 * SHCreateDirectoryExW [SHELL32.@]
912 *
913 * See SHCreateDirectoryExA.
914 */
916{
918 TRACE("(%p, %s, %p)\n", hWnd, debugstr_w(path), sec);
919
921 {
923 }
924 else
925 {
927 /* Refuse to work on certain error codes before trying to create directories recursively */
928 if (ret != ERROR_SUCCESS &&
932 {
933 WCHAR *pEnd, *pSlash, szTemp[MAX_PATH + 1]; /* extra for PathAddBackslash() */
934
935 lstrcpynW(szTemp, path, MAX_PATH);
936 pEnd = PathAddBackslashW(szTemp);
937 pSlash = szTemp + 3;
938
939 while (*pSlash)
940 {
941 while (*pSlash && *pSlash != '\\') pSlash++;
942 if (*pSlash)
943 {
944 *pSlash = 0; /* terminate path at separator */
945
946 ret = SHNotifyCreateDirectoryW(szTemp, pSlash + 1 == pEnd ? sec : NULL);
947 }
948 *pSlash++ = '\\'; /* put the separator back */
949 }
950 }
951
952 if (ret && hWnd && (ERROR_CANCELLED != ret && ERROR_ALREADY_EXISTS != ret))
953 {
957 }
958 }
959
960 return ret;
961}
962
963/*************************************************************************
964 * SHFindAttrW [internal]
965 *
966 * Get the Attributes for a file or directory. The difference to GetAttributes()
967 * is that this function will also work for paths containing wildcard characters
968 * in its filename.
969
970 * PARAMS
971 * path [I] path of directory or file to check
972 * fileOnly [I] TRUE if only files should be found
973 *
974 * RETURNS
975 * INVALID_FILE_ATTRIBUTES if the path does not exist, the actual attributes of
976 * the first file or directory found otherwise
977 */
979{
981 BOOL b_FileMask = fileOnly && (NULL != StrPBrkW(pName, L"*?"));
983 HANDLE hFind = FindFirstFileW(pName, &wfd);
984
985 TRACE("%s %d\n", debugstr_w(pName), fileOnly);
986 if (INVALID_HANDLE_VALUE != hFind)
987 {
988 do
989 {
990 if (b_FileMask && IsAttribDir(wfd.dwFileAttributes))
991 continue;
992 dwAttr = wfd.dwFileAttributes;
993 break;
994 } while (FindNextFileW(hFind, &wfd));
995
996 FindClose(hFind);
997 }
998 return dwAttr;
999}
1000
1001/*************************************************************************
1002 *
1003 * _ConvertAtoW helper function for SHFileOperationA
1004 *
1005 * Converts a string or string-list to unicode.
1006 */
1007static DWORD _ConvertAtoW(PCSTR strSrc, PCWSTR* pStrDest, BOOL isList)
1008{
1009 *pStrDest = NULL;
1010
1011 // If the input is null, nothing to convert.
1012 if (!strSrc)
1013 return 0;
1014
1015 // Measure the total size, depending on if it's a zero-terminated list.
1016 int sizeA = 0;
1017 if (isList)
1018 {
1019 PCSTR tmpSrc = strSrc;
1020 int size;
1021 do
1022 {
1023 size = lstrlenA(tmpSrc) + 1;
1024 sizeA += size;
1025 tmpSrc += size;
1026 } while (size != 1);
1027 }
1028 else
1029 {
1030 sizeA = lstrlenA(strSrc) + 1;
1031 }
1032
1033 // Measure the needed allocation size.
1034 int sizeW = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, NULL, 0);
1035 if (!sizeW)
1036 return GetLastError();
1037
1038 PWSTR strDest = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeW * sizeof(WCHAR));
1039 if (!strDest)
1040 return ERROR_OUTOFMEMORY;
1041
1042 int err = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, strDest, sizeW);
1043 if (!err)
1044 {
1045 HeapFree(GetProcessHeap(), 0, strDest);
1046 return GetLastError();
1047 }
1048
1049 *pStrDest = strDest;
1050 return 0;
1051}
1052
1053/*************************************************************************
1054 * SHFileOperationA [SHELL32.@]
1055 *
1056 * Function to copy, move, delete and create one or more files with optional
1057 * user prompts.
1058 *
1059 * PARAMS
1060 * lpFileOp [I/O] pointer to a structure containing all the necessary information
1061 *
1062 * RETURNS
1063 * Success: ERROR_SUCCESS.
1064 * Failure: ERROR_CANCELLED.
1065 *
1066 * NOTES
1067 * exported by name
1068 */
1070{
1071 int errCode, retCode;
1072 SHFILEOPSTRUCTW nFileOp = { 0 };
1073
1074 // Convert A information to W
1075 nFileOp.hwnd = lpFileOp->hwnd;
1076 nFileOp.wFunc = lpFileOp->wFunc;
1077 nFileOp.fFlags = lpFileOp->fFlags;
1078
1079 errCode = _ConvertAtoW(lpFileOp->pFrom, &nFileOp.pFrom, TRUE);
1080 if (errCode != 0)
1081 goto cleanup;
1082
1083 if (FO_DELETE != (nFileOp.wFunc & FO_MASK))
1084 {
1085 errCode = _ConvertAtoW(lpFileOp->pTo, &nFileOp.pTo, TRUE);
1086 if (errCode != 0)
1087 goto cleanup;
1088 }
1089
1090 if (nFileOp.fFlags & FOF_SIMPLEPROGRESS)
1091 {
1092 errCode = _ConvertAtoW(lpFileOp->lpszProgressTitle, &nFileOp.lpszProgressTitle, FALSE);
1093 if (errCode != 0)
1094 goto cleanup;
1095 }
1096
1097 // Call the actual function
1098 retCode = SHFileOperationW(&nFileOp);
1099 if (retCode)
1100 {
1101 ERR("SHFileOperationW failed with 0x%x\n", retCode);
1102 }
1103
1104 // Cleanup
1105cleanup:
1106 if (nFileOp.pFrom)
1107 HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pFrom);
1108 if (nFileOp.pTo)
1109 HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pTo);
1110 if (nFileOp.lpszProgressTitle)
1112
1113 if (errCode != 0)
1114 {
1115 lpFileOp->fAnyOperationsAborted = TRUE;
1116 SetLastError(errCode);
1117
1118 return errCode;
1119 }
1120
1121 // Thankfully, starting with NT4 the name mappings are always unicode, so no need to convert.
1122 lpFileOp->hNameMappings = nFileOp.hNameMappings;
1123 lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted;
1124 return retCode;
1125}
1126
1127static void __inline grow_list(FILE_LIST *list)
1128{
1130 list->num_alloc * 2 * sizeof(*newx) );
1131 list->feFiles = newx;
1132 list->num_alloc *= 2;
1133}
1134
1135/* adds a file to the FILE_ENTRY struct
1136 */
1137static void add_file_to_entry(FILE_ENTRY *feFile, LPCWSTR szFile)
1138{
1139 DWORD dwLen = lstrlenW(szFile) + 1;
1140 LPCWSTR ptr;
1141 LPCWSTR ptr2;
1142
1143 feFile->szFullPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1144 lstrcpyW(feFile->szFullPath, szFile);
1145
1146 ptr = StrRChrW(szFile, NULL, '\\');
1147 ptr2 = StrRChrW(szFile, NULL, '/');
1148 if (!ptr || ptr < ptr2)
1149 ptr = ptr2;
1150 if (ptr)
1151 {
1152 dwLen = ptr - szFile + 1;
1153 feFile->szDirectory = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1154 lstrcpynW(feFile->szDirectory, szFile, dwLen);
1155
1156 dwLen = lstrlenW(feFile->szFullPath) - dwLen + 1;
1157 feFile->szFilename = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(WCHAR));
1158 lstrcpyW(feFile->szFilename, ptr + 1); /* skip over backslash */
1159 }
1160 feFile->bFromWildcard = FALSE;
1161}
1162
1163static LPWSTR wildcard_to_file(LPCWSTR szWildCard, LPCWSTR szFileName)
1164{
1165 LPCWSTR ptr;
1166 LPCWSTR ptr2;
1167 LPWSTR szFullPath;
1168 DWORD dwDirLen, dwFullLen;
1169
1170 ptr = StrRChrW(szWildCard, NULL, '\\');
1171 ptr2 = StrRChrW(szWildCard, NULL, '/');
1172 if (!ptr || ptr < ptr2)
1173 ptr = ptr2;
1174 dwDirLen = ptr - szWildCard + 1;
1175
1176 dwFullLen = dwDirLen + lstrlenW(szFileName) + 1;
1177 szFullPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwFullLen * sizeof(WCHAR));
1178
1179 lstrcpynW(szFullPath, szWildCard, dwDirLen + 1);
1180 lstrcatW(szFullPath, szFileName);
1181
1182 return szFullPath;
1183}
1184
1185static void parse_wildcard_files(FILE_LIST *flList, LPCWSTR szFile, LPDWORD pdwListIndex)
1186{
1187 WIN32_FIND_DATAW wfd;
1188 HANDLE hFile = FindFirstFileW(szFile, &wfd);
1190 LPWSTR szFullPath;
1191 BOOL res;
1192
1193 if (hFile == INVALID_HANDLE_VALUE) return;
1194
1195 for (res = TRUE; res; res = FindNextFileW(hFile, &wfd))
1196 {
1197 if (IsDotDir(wfd.cFileName))
1198 continue;
1199
1200 if (*pdwListIndex >= flList->num_alloc)
1201 grow_list( flList );
1202
1203 szFullPath = wildcard_to_file(szFile, wfd.cFileName);
1204 file = &flList->feFiles[(*pdwListIndex)++];
1205 add_file_to_entry(file, szFullPath);
1206 file->bFromWildcard = TRUE;
1207 file->attributes = wfd.dwFileAttributes;
1208
1209 if (IsAttribDir(file->attributes))
1210 flList->bAnyDirectories = TRUE;
1211
1212 HeapFree(GetProcessHeap(), 0, szFullPath);
1213 }
1214
1216}
1217
1218/* takes the null-separated file list and fills out the FILE_LIST */
1220{
1222 WCHAR szCurFile[MAX_PATH];
1223 DWORD i = 0;
1224
1225 if (!szFiles)
1227
1228 flList->bAnyFromWildcard = FALSE;
1229 flList->bAnyDirectories = FALSE;
1230 flList->bAnyDontExist = FALSE;
1231 flList->num_alloc = 32;
1232 flList->dwNumFiles = 0;
1233
1234 /* empty list */
1235 if (!szFiles[0])
1236 return ERROR_ACCESS_DENIED;
1237
1239 flList->num_alloc * sizeof(FILE_ENTRY));
1240
1241 while (*ptr)
1242 {
1243 if (i >= flList->num_alloc) grow_list( flList );
1244
1245 /* change relative to absolute path */
1246 if (PathIsRelativeW(ptr))
1247 {
1248 GetCurrentDirectoryW(MAX_PATH, szCurFile);
1249 PathCombineW(szCurFile, szCurFile, ptr);
1250 flList->feFiles[i].bFromRelative = TRUE;
1251 }
1252 else
1253 {
1254 lstrcpyW(szCurFile, ptr);
1255 flList->feFiles[i].bFromRelative = FALSE;
1256 }
1257
1258 /* parse wildcard files if they are in the filename */
1259 if (StrPBrkW(szCurFile, L"*?"))
1260 {
1261 parse_wildcard_files(flList, szCurFile, &i);
1262 flList->bAnyFromWildcard = TRUE;
1263 i--;
1264 }
1265 else
1266 {
1267 FILE_ENTRY *file = &flList->feFiles[i];
1268 add_file_to_entry(file, szCurFile);
1269 file->attributes = GetFileAttributesW( file->szFullPath );
1270 file->bExists = (file->attributes != INVALID_FILE_ATTRIBUTES);
1271
1272 if (!file->bExists)
1273 flList->bAnyDontExist = TRUE;
1274
1275 if (IsAttribDir(file->attributes))
1276 flList->bAnyDirectories = TRUE;
1277 }
1278
1279 /* advance to the next string */
1280 ptr += lstrlenW(ptr) + 1;
1281 i++;
1282 }
1283 flList->dwNumFiles = i;
1284
1285 return S_OK;
1286}
1287
1288/* free the FILE_LIST */
1289static void destroy_file_list(FILE_LIST *flList)
1290{
1291 DWORD i;
1292
1293 if (!flList || !flList->feFiles)
1294 return;
1295
1296 for (i = 0; i < flList->dwNumFiles; i++)
1297 {
1299 HeapFree(GetProcessHeap(), 0, flList->feFiles[i].szFilename);
1300 HeapFree(GetProcessHeap(), 0, flList->feFiles[i].szFullPath);
1301 }
1302
1303 HeapFree(GetProcessHeap(), 0, flList->feFiles);
1304}
1305
1307{
1308 CStringW mask(szDestPath);
1309 CStringW ext(PathFindExtensionW(szDestPath));
1310
1311 // cut off extension before inserting a "new file" mask
1312 if (!ext.IsEmpty())
1313 {
1314 mask = mask.Left(mask.GetLength() - ext.GetLength());
1315 }
1316 mask += L" (%d)" + ext;
1317
1318 CStringW newName;
1319
1320 // trying to find new file name
1321 for (int i = 1; i < NEW_FILENAME_ON_COPY_TRIES; i++)
1322 {
1323 newName.Format(mask, i);
1324
1325 if (!PathFileExistsW(newName))
1326 {
1327 return newName;
1328 }
1329 }
1330
1331 return CStringW();
1332}
1333
1334static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
1335{
1336 WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1337 FILE_LIST flFromNew, flToNew;
1338
1339 if (IsDotDir(feFrom->szFilename))
1340 return;
1341
1342 if (PathFileExistsW(szDestPath))
1343 PathCombineW(szTo, szDestPath, feFrom->szFilename);
1344 else
1345 lstrcpyW(szTo, szDestPath);
1346
1347#ifdef __REACTOS__
1348 if (PathFileExistsW(szTo))
1349 {
1350 if (op->req->fFlags & FOF_RENAMEONCOLLISION)
1351 {
1352 CStringW newPath = try_find_new_name(szTo);
1353 if (!newPath.IsEmpty())
1354 {
1355 StringCchCopyW(szTo, _countof(szTo), newPath);
1356 }
1357 }
1358 else if (!(op->req->fFlags & FOF_NOCONFIRMATION))
1359#else
1360 if (!(op->req->fFlags & FOF_NOCONFIRMATION) && PathFileExistsW(szTo))
1361 {
1362 CStringW newPath;
1363 if (lstrcmp(feFrom->szDirectory, szDestPath) == 0 && !(newPath = try_find_new_name(szTo)).IsEmpty())
1364 {
1365 StringCchCopyW(szTo, _countof(szTo), newPath);
1366 }
1367 else
1368#endif
1369 {
1370 if (!SHELL_ConfirmDialogW(op->req->hwnd, ASK_OVERWRITE_FOLDER, feFrom->szFilename, op))
1371 {
1372 /* Vista returns an ERROR_CANCELLED even if user pressed "No" */
1373 if (!op->bManyItems)
1374 op->bCancelled = TRUE;
1375 return;
1376 }
1377 }
1378 }
1379
1380 szTo[lstrlenW(szTo) + 1] = '\0';
1382
1383 PathCombineW(szFrom, feFrom->szFullPath, L"*.*");
1384 szFrom[lstrlenW(szFrom) + 1] = '\0';
1385
1386 ZeroMemory(&flFromNew, sizeof(FILE_LIST));
1387 ZeroMemory(&flToNew, sizeof(FILE_LIST));
1388 parse_file_list(&flFromNew, szFrom);
1389 parse_file_list(&flToNew, szTo);
1390
1391 copy_files(op, FALSE, &flFromNew, &flToNew);
1392
1393 destroy_file_list(&flFromNew);
1394 destroy_file_list(&flToNew);
1395}
1396
1397static BOOL copy_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCHAR *szTo)
1398{
1399#ifdef __REACTOS__
1400 if (PathFileExistsW(szTo))
1401 {
1402 if (op->req->fFlags & FOF_RENAMEONCOLLISION)
1403 {
1404 CStringW newPath = try_find_new_name(szTo);
1405 if (!newPath.IsEmpty())
1406 {
1407 return SHNotifyCopyFileW(op, szFrom, newPath, FALSE) == 0;
1408 }
1409 }
1410 else if (!(op->req->fFlags & FOF_NOCONFIRMATION))
1411 {
1413 return FALSE;
1414 }
1415#else
1416 if (!(op->req->fFlags & FOF_NOCONFIRMATION) && PathFileExistsW(szTo))
1417 {
1418 CStringW newPath;
1419 if (lstrcmp(szFrom, szTo) == 0 && !(newPath = try_find_new_name(szTo)).IsEmpty())
1420 {
1421 return SHNotifyCopyFileW(op, szFrom, newPath, FALSE) == 0;
1422 }
1423
1425 return FALSE;
1426#endif
1427 }
1428
1429 return SHNotifyCopyFileW(op, szFrom, szTo, FALSE) == 0;
1430}
1431
1432/* copy a file or directory to another directory */
1433static void copy_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
1434{
1435 if (!PathFileExistsW(feTo->szFullPath))
1437
1438 if (IsAttribFile(feFrom->attributes))
1439 {
1440 WCHAR szDestPath[MAX_PATH];
1441
1442 PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
1443 copy_file_to_file(op, feFrom->szFullPath, szDestPath);
1444 }
1445 else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
1446 copy_dir_to_dir(op, feFrom, feTo->szFullPath);
1447}
1448
1449static void create_dest_dirs(LPCWSTR szDestDir)
1450{
1452 LPCWSTR ptr = StrChrW(szDestDir, '\\');
1453
1454 /* make sure all directories up to last one are created */
1455 while (ptr && (ptr = StrChrW(ptr + 1, '\\')))
1456 {
1457 lstrcpynW(dir, szDestDir, ptr - szDestDir + 1);
1458
1459 if (!PathFileExistsW(dir))
1461 }
1462
1463 /* create last directory */
1464 if (!PathFileExistsW(szDestDir))
1465 SHNotifyCreateDirectoryW(szDestDir, NULL);
1466}
1467
1468/* the FO_COPY operation */
1469static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo)
1470{
1471 DWORD i;
1472 const FILE_ENTRY *entryToCopy;
1473 const FILE_ENTRY *fileDest = &flTo->feFiles[0];
1474
1475 if (flFrom->bAnyDontExist)
1477
1478 if (flTo->dwNumFiles == 0)
1479 {
1480 /* If the destination is empty, SHFileOperation should use the current directory */
1481 WCHAR curdir[MAX_PATH+1];
1482
1484 curdir[lstrlenW(curdir)+1] = 0;
1485
1486 destroy_file_list(flTo);
1487 ZeroMemory(flTo, sizeof(FILE_LIST));
1488 parse_file_list(flTo, curdir);
1489 fileDest = &flTo->feFiles[0];
1490 }
1491
1492 if (multiDest)
1493 {
1494 if (flFrom->bAnyFromWildcard)
1495 return ERROR_CANCELLED;
1496
1497 if (flFrom->dwNumFiles != flTo->dwNumFiles)
1498 {
1499 if (flFrom->dwNumFiles != 1 && !IsAttribDir(fileDest->attributes))
1500 return ERROR_CANCELLED;
1501
1502 /* Free all but the first entry. */
1503 for (i = 1; i < flTo->dwNumFiles; i++)
1504 {
1508 }
1509
1510 flTo->dwNumFiles = 1;
1511 }
1512 else if (IsAttribDir(fileDest->attributes))
1513 {
1514 for (i = 1; i < flTo->dwNumFiles; i++)
1515 if (!IsAttribDir(flTo->feFiles[i].attributes) ||
1516 !IsAttribDir(flFrom->feFiles[i].attributes))
1517 {
1518 return ERROR_CANCELLED;
1519 }
1520 }
1521 }
1522 else if (flFrom->dwNumFiles != 1)
1523 {
1524 if (flTo->dwNumFiles != 1 && !IsAttribDir(fileDest->attributes))
1525 return ERROR_CANCELLED;
1526
1527 if (PathFileExistsW(fileDest->szFullPath) &&
1528 IsAttribFile(fileDest->attributes))
1529 {
1530 return ERROR_CANCELLED;
1531 }
1532
1533 if (flTo->dwNumFiles == 1 && fileDest->bFromRelative &&
1534 !PathFileExistsW(fileDest->szFullPath))
1535 {
1536 return ERROR_CANCELLED;
1537 }
1538 }
1539
1540 for (i = 0; i < flFrom->dwNumFiles; i++)
1541 {
1542 entryToCopy = &flFrom->feFiles[i];
1543
1544 if ((multiDest) &&
1545 flTo->dwNumFiles > 1)
1546 {
1547 fileDest = &flTo->feFiles[i];
1548 }
1549
1550 if (IsAttribDir(entryToCopy->attributes) &&
1551 !lstrcmpiW(entryToCopy->szFullPath, fileDest->szDirectory))
1552 {
1553 return ERROR_SUCCESS;
1554 }
1555
1556 create_dest_dirs(fileDest->szDirectory);
1557
1558 if (!lstrcmpiW(entryToCopy->szFullPath, fileDest->szFullPath))
1559 {
1560 if (IsAttribFile(entryToCopy->attributes))
1562 else
1563 return ERROR_SUCCESS;
1564 }
1565
1566 if ((flFrom->dwNumFiles > 1 && flTo->dwNumFiles == 1) ||
1567 IsAttribDir(fileDest->attributes))
1568 {
1569 copy_to_dir(op, entryToCopy, fileDest);
1570 }
1571 else if (IsAttribDir(entryToCopy->attributes))
1572 {
1573 copy_dir_to_dir(op, entryToCopy, fileDest->szFullPath);
1574 }
1575 else
1576 {
1577 if (!copy_file_to_file(op, entryToCopy->szFullPath, fileDest->szFullPath))
1578 {
1579 op->req->fAnyOperationsAborted = TRUE;
1580 return ERROR_CANCELLED;
1581 }
1582 }
1583
1584 if (op->progress != NULL)
1585 op->bCancelled |= op->progress->HasUserCancelled();
1586 /* Vista return code. XP would return e.g. ERROR_FILE_NOT_FOUND, ERROR_ALREADY_EXISTS */
1587 if (op->bCancelled)
1588 return ERROR_CANCELLED;
1589 }
1590
1591 /* Vista return code. On XP if the used pressed "No" for the last item,
1592 * ERROR_ARENA_TRASHED would be returned */
1593 return ERROR_SUCCESS;
1594}
1595
1596static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE_LIST *flFrom)
1597{
1598 if (flFrom->dwNumFiles > 1)
1599 {
1600 WCHAR tmp[8];
1601
1602 wnsprintfW(tmp, sizeof(tmp)/sizeof(tmp[0]), L"%d", flFrom->dwNumFiles);
1604 }
1605 else
1606 {
1607 const FILE_ENTRY *fileEntry = &flFrom->feFiles[0];
1608
1609 if (IsAttribFile(fileEntry->attributes))
1611 else if (!(fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
1613 }
1614 return TRUE;
1615}
1616
1617/* the FO_DELETE operation */
1619{
1620 const FILE_ENTRY *fileEntry;
1621 DWORD i;
1622 BOOL bPathExists;
1623 BOOL bTrash;
1624
1625 if (!flFrom->dwNumFiles)
1626 return ERROR_SUCCESS;
1627
1628 /* Windows also checks only the first item */
1629 bTrash = (op->req->fFlags & FOF_ALLOWUNDO)
1630 && TRASH_CanTrashFile(flFrom->feFiles[0].szFullPath);
1631
1632 if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (!bTrash && op->req->fFlags & FOF_WANTNUKEWARNING))
1633 if (!confirm_delete_list(op->req->hwnd, op->req->fFlags, bTrash, flFrom))
1634 {
1635 op->req->fAnyOperationsAborted = TRUE;
1636 return 0;
1637 }
1638
1639 /* Check files. Do not delete one if one file does not exists */
1640 for (i = 0; i < flFrom->dwNumFiles; i++)
1641 {
1642 fileEntry = &flFrom->feFiles[i];
1643
1644 if (fileEntry->attributes == (ULONG)-1)
1645 {
1646 // This is a windows 2003 server specific value which has been removed.
1647 // Later versions of windows return ERROR_FILE_NOT_FOUND.
1649 }
1650 }
1651
1652 for (i = 0; i < flFrom->dwNumFiles; i++)
1653 {
1654 bPathExists = TRUE;
1655 fileEntry = &flFrom->feFiles[i];
1656
1657 if (!IsAttribFile(fileEntry->attributes) &&
1658 (op->req->fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
1659 continue;
1660
1661 if (bTrash)
1662 {
1663 BOOL bDelete;
1664 if (TRASH_TrashFile(fileEntry->szFullPath))
1665 {
1667 continue;
1668 }
1669
1670 /* Note: Windows silently deletes the file in such a situation, we show a dialog */
1671 if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (op->req->fFlags & FOF_WANTNUKEWARNING))
1672 bDelete = SHELL_ConfirmDialogW(op->req->hwnd, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL);
1673 else
1674 bDelete = TRUE;
1675
1676 if (!bDelete)
1677 {
1678 op->req->fAnyOperationsAborted = TRUE;
1679 break;
1680 }
1681 }
1682
1683 /* delete the file or directory */
1684 if (IsAttribFile(fileEntry->attributes))
1685 {
1686 bPathExists = (ERROR_SUCCESS == SHNotifyDeleteFileW(op, fileEntry->szFullPath));
1687 }
1688 else
1689 bPathExists = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
1690
1691 if (!bPathExists)
1692 {
1694
1696 {
1697 // This is a windows 2003 server specific value which ahs been removed.
1698 // Later versions of windows return ERROR_FILE_NOT_FOUND.
1700 }
1701 else
1702 {
1703 return err;
1704 }
1705 }
1706
1707 if (op->progress != NULL)
1708 op->bCancelled |= op->progress->HasUserCancelled();
1709 /* Should fire on progress dialog only */
1710 if (op->bCancelled)
1711 return ERROR_CANCELLED;
1712 }
1713
1714 return ERROR_SUCCESS;
1715}
1716
1717static void move_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
1718{
1719 WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1720 FILE_LIST flFromNew, flToNew;
1721
1722 if (IsDotDir(feFrom->szFilename))
1723 return;
1724
1725 SHNotifyCreateDirectoryW(szDestPath, NULL);
1726
1727 PathCombineW(szFrom, feFrom->szFullPath, L"*.*");
1728 szFrom[lstrlenW(szFrom) + 1] = '\0';
1729
1730 lstrcpyW(szTo, szDestPath);
1731 szTo[lstrlenW(szDestPath) + 1] = '\0';
1732
1733 ZeroMemory(&flFromNew, sizeof(FILE_LIST));
1734 ZeroMemory(&flToNew, sizeof(FILE_LIST));
1735 parse_file_list(&flFromNew, szFrom);
1736 parse_file_list(&flToNew, szTo);
1737
1738 move_files(op, FALSE, &flFromNew, &flToNew);
1739
1740 destroy_file_list(&flFromNew);
1741 destroy_file_list(&flToNew);
1742
1743 if (PathIsDirectoryEmptyW(feFrom->szFullPath))
1745}
1746
1747/* moves a file or directory to another directory */
1748static void move_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
1749{
1750 WCHAR szDestPath[MAX_PATH];
1751
1752 PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
1753
1754 if (IsAttribFile(feFrom->attributes))
1755 SHNotifyMoveFileW(op, feFrom->szFullPath, szDestPath, FALSE);
1756 else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
1757 move_dir_to_dir(op, feFrom, szDestPath);
1758}
1759
1760/* the FO_MOVE operation */
1761static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1762{
1763 DWORD i;
1764 INT mismatched = 0;
1765
1766 const FILE_ENTRY *entryToMove;
1767 const FILE_ENTRY *fileDest;
1768
1769 if (!flFrom->dwNumFiles)
1770 return ERROR_SUCCESS;
1771
1772 if (!flTo->dwNumFiles)
1773 return ERROR_FILE_NOT_FOUND;
1774
1775 if (!(multiDest) &&
1776 flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
1777 {
1778 return ERROR_CANCELLED;
1779 }
1780
1781 if (!(multiDest) &&
1782 !flFrom->bAnyDirectories &&
1783 flFrom->dwNumFiles > flTo->dwNumFiles &&
1784 !(flTo->bAnyDirectories && flTo->dwNumFiles == 1))
1785 {
1786 return ERROR_CANCELLED;
1787 }
1788
1789 if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
1790 return ERROR_CANCELLED;
1791
1792 if (multiDest)
1793 mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
1794
1795 fileDest = &flTo->feFiles[0];
1796 for (i = 0; i < flFrom->dwNumFiles; i++)
1797 {
1798 entryToMove = &flFrom->feFiles[i];
1799
1800 if (!PathFileExistsW(fileDest->szDirectory))
1801 return ERROR_CANCELLED;
1802
1803 if (multiDest)
1804 {
1805 if (i >= flTo->dwNumFiles)
1806 break;
1807 fileDest = &flTo->feFiles[i];
1808 if (mismatched && !fileDest->bExists)
1809 {
1811 flTo->feFiles[i].bExists = TRUE;
1813 }
1814 }
1815
1816 if (fileDest->bExists && IsAttribDir(fileDest->attributes))
1817 move_to_dir(op, entryToMove, fileDest);
1818 else
1819 SHNotifyMoveFileW(op, entryToMove->szFullPath, fileDest->szFullPath, IsAttribDir(entryToMove->attributes));
1820
1821 if (op->progress != NULL)
1822 op->bCancelled |= op->progress->HasUserCancelled();
1823 /* Should fire on progress dialog only */
1824 if (op->bCancelled)
1825 return ERROR_CANCELLED;
1826
1827 }
1828
1829 if (mismatched > 0)
1830 {
1831 if (flFrom->bAnyDirectories)
1832 return DE_DESTSAMETREE;
1833 else
1834 return DE_SAMEFILE;
1835 }
1836
1837 return ERROR_SUCCESS;
1838}
1839
1840/* the FO_RENAME files */
1841static HRESULT rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1842{
1843 const FILE_ENTRY *feFrom;
1844 const FILE_ENTRY *feTo;
1845
1846 if (flFrom->dwNumFiles != 1)
1847 return ERROR_GEN_FAILURE;
1848
1849 if (flTo->dwNumFiles != 1)
1850 return ERROR_CANCELLED;
1851
1852 feFrom = &flFrom->feFiles[0];
1853 feTo= &flTo->feFiles[0];
1854
1855 /* fail if destination doesn't exist */
1856 if (!feFrom->bExists)
1858
1859 /* fail if destination already exists */
1860 if (feTo->bExists)
1861 return ERROR_ALREADY_EXISTS;
1862
1863 return SHNotifyMoveFileW(op, feFrom->szFullPath, feTo->szFullPath, IsAttribDir(feFrom->attributes));
1864}
1865
1866/* alert the user if an unsupported flag is used */
1867static void check_flags(FILEOP_FLAGS fFlags)
1868{
1869 WORD wUnsupportedFlags = FOF_NO_CONNECTED_ELEMENTS |
1871#ifdef __REACTOS__
1873#else
1875#endif
1876
1877 if (fFlags & wUnsupportedFlags)
1878 FIXME("Unsupported flags: %04x\n", fFlags);
1879}
1880
1881#ifdef __REACTOS__
1882
1883static DWORD
1884validate_operation(LPSHFILEOPSTRUCTW lpFileOp, FILE_LIST *flFrom, FILE_LIST *flTo)
1885{
1886 DWORD i, k, dwNumDest;
1887 WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1888 CStringW strTitle, strText;
1889 const FILE_ENTRY *feFrom;
1890 const FILE_ENTRY *feTo;
1891 UINT wFunc = lpFileOp->wFunc;
1892 HWND hwnd = lpFileOp->hwnd;
1893
1894 dwNumDest = flTo->dwNumFiles;
1895
1896 if (wFunc != FO_COPY && wFunc != FO_MOVE)
1897 return ERROR_SUCCESS;
1898
1899 for (k = 0; k < dwNumDest; ++k)
1900 {
1901 feTo = &flTo->feFiles[k];
1902 for (i = 0; i < flFrom->dwNumFiles; ++i)
1903 {
1904 feFrom = &flFrom->feFiles[i];
1905 StringCbCopyW(szFrom, sizeof(szFrom), feFrom->szFullPath);
1906 StringCbCopyW(szTo, sizeof(szTo), feTo->szFullPath);
1907 if (IsAttribDir(feTo->attributes))
1908 {
1909 PathAppendW(szTo, feFrom->szFilename);
1910 }
1911
1912 // same path?
1913 if (lstrcmpiW(szFrom, szTo) == 0 &&
1914 (wFunc == FO_MOVE || !(lpFileOp->fFlags & FOF_RENAMEONCOLLISION)))
1915 {
1916 if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
1917 {
1918 if (wFunc == FO_MOVE)
1919 {
1920 strTitle.LoadStringW(IDS_MOVEERRORTITLE);
1921 if (IsAttribDir(feFrom->attributes))
1922 strText.Format(IDS_MOVEERRORSAMEFOLDER, feFrom->szFilename);
1923 else
1924 strText.Format(IDS_MOVEERRORSAME, feFrom->szFilename);
1925 }
1926 else
1927 {
1928 strTitle.LoadStringW(IDS_COPYERRORTITLE);
1929 strText.Format(IDS_COPYERRORSAME, feFrom->szFilename);
1930 return ERROR_SUCCESS;
1931 }
1932 MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
1933 return DE_SAMEFILE;
1934 }
1935 return DE_OPCANCELLED;
1936 }
1937
1938 // subfolder?
1939 if (IsAttribDir(feFrom->attributes))
1940 {
1941 size_t cchFrom = PathAddBackslashW(szFrom) - szFrom;
1942 size_t cchTo = PathAddBackslashW(szTo) - szTo;
1943 if (cchFrom <= cchTo)
1944 {
1945 WCHAR ch = szTo[cchFrom];
1946 szTo[cchFrom] = 0;
1947 int compare = lstrcmpiW(szFrom, szTo);
1948 szTo[cchFrom] = ch;
1949
1950 if (compare == 0)
1951 {
1952 if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
1953 {
1954 if (wFunc == FO_MOVE)
1955 {
1956 strTitle.LoadStringW(IDS_MOVEERRORTITLE);
1957 strText.Format(IDS_MOVEERRORSUBFOLDER, feFrom->szFilename);
1958 }
1959 else
1960 {
1961 strTitle.LoadStringW(IDS_COPYERRORTITLE);
1962 strText.Format(IDS_COPYERRORSUBFOLDER, feFrom->szFilename);
1963 }
1964 MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
1965 return DE_DESTSUBTREE;
1966 }
1967 return DE_OPCANCELLED;
1968 }
1969 }
1970 }
1971 }
1972 }
1973
1974 return ERROR_SUCCESS;
1975}
1976#endif
1977/*************************************************************************
1978 * SHFileOperationW [SHELL32.@]
1979 *
1980 * See SHFileOperationA
1981 */
1983{
1985 FILE_LIST flFrom, flTo;
1986 int ret = 0;
1987
1988 if (!lpFileOp)
1990
1992 if (FAILED(ret))
1993 return ret;
1994
1995 lpFileOp->fAnyOperationsAborted = FALSE;
1996 check_flags(lpFileOp->fFlags);
1997
1998 ZeroMemory(&flFrom, sizeof(FILE_LIST));
1999 ZeroMemory(&flTo, sizeof(FILE_LIST));
2000
2001 if ((ret = parse_file_list(&flFrom, lpFileOp->pFrom)))
2002 return ret;
2003
2004 if (lpFileOp->wFunc != FO_DELETE)
2005 parse_file_list(&flTo, lpFileOp->pTo);
2006
2007 ZeroMemory(&op, sizeof(op));
2008 op.req = lpFileOp;
2009 op.totalSize.QuadPart = 0ull;
2010 op.completedSize.QuadPart = 0ull;
2011 op.bManyItems = (flFrom.dwNumFiles > 1);
2012
2013#ifdef __REACTOS__
2014 ret = validate_operation(lpFileOp, &flFrom, &flTo);
2015 if (ret)
2016 goto cleanup;
2017#endif
2018 if (lpFileOp->wFunc != FO_RENAME && !(lpFileOp->fFlags & FOF_SILENT)) {
2019 ret = CoCreateInstance(CLSID_ProgressDialog,
2020 NULL,
2021 CLSCTX_INPROC_SERVER,
2022 IID_PPV_ARG(IProgressDialog, &op.progress));
2023 if (FAILED(ret))
2024 goto cleanup;
2025
2026 op.progress->StartProgressDialog(op.req->hwnd, NULL, PROGDLG_NORMAL & PROGDLG_AUTOTIME, NULL);
2028 _FileOpCountManager(&op, &flFrom);
2029 }
2030
2031 switch (lpFileOp->wFunc)
2032 {
2033 case FO_COPY:
2034 ret = copy_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
2035 break;
2036 case FO_DELETE:
2037 ret = delete_files(&op, &flFrom);
2038 break;
2039 case FO_MOVE:
2040 ret = move_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
2041 break;
2042 case FO_RENAME:
2043 ret = rename_files(&op, &flFrom, &flTo);
2044 break;
2045 default:
2047 break;
2048 }
2049
2050 if (op.progress) {
2051 op.progress->StopProgressDialog();
2052 op.progress->Release();
2053 }
2054
2055cleanup:
2056 destroy_file_list(&flFrom);
2057
2058 if (lpFileOp->wFunc != FO_DELETE)
2059 destroy_file_list(&flTo);
2060
2061 if (ret == ERROR_CANCELLED)
2062 lpFileOp->fAnyOperationsAborted = TRUE;
2063
2065
2066 return ret;
2067}
2068
2069// Used by SHFreeNameMappings
2070static int CALLBACK _DestroyCallback(void *p, void *pData)
2071{
2073
2074 SHFree(lp->pszOldPath);
2075 SHFree(lp->pszNewPath);
2076
2077 return TRUE;
2078}
2079
2080/*************************************************************************
2081 * SHFreeNameMappings [shell32.246]
2082 *
2083 * Free the mapping handle returned by SHFileOperation if FOF_WANTSMAPPINGHANDLE
2084 * was specified.
2085 *
2086 * PARAMS
2087 * hNameMapping [I] handle to the name mappings used during renaming of files
2088 *
2089 * RETURNS
2090 * Nothing
2091 */
2093{
2094 if (hNameMapping)
2095 {
2097 }
2098}
2099
2100/*************************************************************************
2101 * SheGetDirA [SHELL32.@]
2102 *
2103 * drive = 0: returns the current directory path
2104 * drive > 0: returns the current directory path of the specified drive
2105 * drive=1 -> A: drive=2 -> B: ...
2106 * returns 0 if successful
2107*/
2109{
2110 WCHAR org_path[MAX_PATH];
2111 DWORD ret;
2112 char drv_path[3];
2113
2114 /* change current directory to the specified drive */
2115 if (drive) {
2116 strcpy(drv_path, "A:");
2117 drv_path[0] += (char)drive-1;
2118
2119 GetCurrentDirectoryW(MAX_PATH, org_path);
2120
2121 SetCurrentDirectoryA(drv_path);
2122 }
2123
2124 /* query current directory path of the specified drive */
2126
2127 /* back to the original drive */
2128 if (drive)
2129 SetCurrentDirectoryW(org_path);
2130
2131 if (!ret)
2132 return GetLastError();
2133
2134 return 0;
2135}
2136
2137/*************************************************************************
2138 * SheGetDirW [SHELL32.@]
2139 *
2140 * drive = 0: returns the current directory path
2141 * drive > 0: returns the current directory path of the specified drive
2142 * drive=1 -> A: drive=2 -> B: ...
2143 * returns 0 if successful
2144 */
2146{
2147 WCHAR org_path[MAX_PATH];
2148 DWORD ret;
2149 char drv_path[3];
2150
2151 /* change current directory to the specified drive */
2152 if (drive)
2153 {
2154 strcpy(drv_path, "A:");
2155 drv_path[0] += (char)drive-1;
2156
2157 GetCurrentDirectoryW(MAX_PATH, org_path);
2158
2159 SetCurrentDirectoryA(drv_path);
2160 }
2161
2162 /* query current directory path of the specified drive */
2164
2165 /* back to the original drive */
2166 if (drive)
2167 SetCurrentDirectoryW(org_path);
2168
2169 if (!ret)
2170 return GetLastError();
2171
2172 return 0;
2173}
2174
2175/*************************************************************************
2176 * SheChangeDirA [SHELL32.@]
2177 *
2178 * changes the current directory to the specified path
2179 * and returns 0 if successful
2180 */
2182{
2184 return 0;
2185 else
2186 return GetLastError();
2187}
2188
2189/*************************************************************************
2190 * SheChangeDirW [SHELL32.@]
2191 *
2192 * changes the current directory to the specified path
2193 * and returns 0 if successful
2194 */
2196{
2198 return 0;
2199 else
2200 return GetLastError();
2201}
2202
2203/*************************************************************************
2204 * IsNetDrive [SHELL32.66]
2205 */
2207{
2208 char root[4];
2209 strcpy(root, "A:\\");
2210 root[0] += (char)drive;
2211 return (GetDriveTypeA(root) == DRIVE_REMOTE);
2212}
2213
2214
2215/*************************************************************************
2216 * RealDriveType [SHELL32.524]
2217 */
2219{
2220 char root[] = "A:\\";
2221 root[0] += (char)drive;
2222 return GetDriveTypeA(root);
2223}
2224
2225/***********************************************************************
2226 * SHPathPrepareForWriteW (SHELL32.@)
2227 */
2229{
2230 DWORD res;
2231 DWORD err;
2232 LPCWSTR realpath;
2233 int len;
2234 WCHAR* last_slash;
2235 WCHAR* temppath=NULL;
2236
2237 TRACE("%p %p %s 0x%08x\n", hwnd, modless, debugstr_w(path), flags);
2238
2240 FIXME("unimplemented flags 0x%08x\n", flags);
2241
2242 /* cut off filename if necessary */
2244 {
2245 last_slash = StrRChrW(path, NULL, '\\');
2246 if (last_slash == NULL)
2247 len = 1;
2248 else
2249 len = last_slash - path + 1;
2250 temppath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2251 if (!temppath)
2252 return E_OUTOFMEMORY;
2253 StrCpyNW(temppath, path, len);
2254 realpath = temppath;
2255 }
2256 else
2257 {
2258 realpath = path;
2259 }
2260
2261 /* try to create the directory if asked to */
2263 {
2265 FIXME("treating SHPPFW_ASKDIRCREATE as SHPPFW_DIRCREATE\n");
2266
2267 SHCreateDirectoryExW(0, realpath, NULL);
2268 }
2269
2270 /* check if we can access the directory */
2271 res = GetFileAttributesW(realpath);
2272
2273 HeapFree(GetProcessHeap(), 0, temppath);
2274
2276 {
2277 err = GetLastError();
2280 return HRESULT_FROM_WIN32(err);
2281 }
2282 else if (res & FILE_ATTRIBUTE_DIRECTORY)
2283 return S_OK;
2284 else
2286}
2287
2288/***********************************************************************
2289 * SHPathPrepareForWriteA (SHELL32.@)
2290 */
2292{
2293 WCHAR wpath[MAX_PATH];
2294 MultiByteToWideChar( CP_ACP, 0, path, -1, wpath, MAX_PATH);
2295 return SHPathPrepareForWriteW(hwnd, modless, wpath, flags);
2296}
2297
2298
2299/*
2300 * The two following background operations were modified from filedefext.cpp
2301 * They use an inordinate amount of mutable state across the string functions,
2302 * so are not easy to follow and care is required when modifying.
2303 */
2304
2307{
2308 DWORD ticks = GetTickCount();
2309 FILE_ENTRY *entryToCount;
2310
2311 for (UINT i = 0; i < from->dwNumFiles; i++)
2312 {
2313 entryToCount = &from->feFiles[i];
2314
2315 WCHAR theFileName[MAX_PATH];
2316 StringCchCopyW(theFileName, MAX_PATH, entryToCount->szFullPath);
2317 _FileOpCount(op, theFileName, IsAttribDir(entryToCount->attributes), &ticks);
2318 }
2319 return 0;
2320}
2321
2322// All path manipulations, even when this function is nested, occur on the one buffer.
2323static BOOL
2324_FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks)
2325{
2326 /* Find filename position */
2327 UINT cchBuf = wcslen(pwszBuf);
2328 WCHAR *pwszFilename = pwszBuf + cchBuf;
2329 size_t cchFilenameMax = MAX_PATH - cchBuf;
2330 if (!cchFilenameMax)
2331 return FALSE;
2332
2333 if (bFolder) {
2334 *(pwszFilename++) = '\\';
2335 --cchFilenameMax;
2336 /* Find all files, FIXME: shouldn't be "*"? */
2337 StringCchCopyW(pwszFilename, cchFilenameMax, L"*");
2338 }
2339
2340 WIN32_FIND_DATAW wfd;
2341 HANDLE hFind = FindFirstFileW(pwszBuf, &wfd);
2342 if (hFind == INVALID_HANDLE_VALUE)
2343 {
2344 ERR("FindFirstFileW %ls failed\n", pwszBuf);
2345 return FALSE;
2346 }
2347
2348 do
2349 {
2350 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2351 {
2352 /* Don't process "." and ".." items */
2353 if (!wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L".."))
2354 continue;
2355
2356 StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName);
2357 _FileOpCount(op, pwszBuf, TRUE, ticks);
2358 }
2359 else
2360 {
2362 FileSize.u.LowPart = wfd.nFileSizeLow;
2363 FileSize.u.HighPart = wfd.nFileSizeHigh;
2364 op->totalSize.QuadPart += FileSize.QuadPart;
2365 }
2366 if (GetTickCount() - *ticks > (DWORD) 500)
2367 {
2368 // Check if the dialog has ended. If it has, we'll spin down.
2369 if (op->progress != NULL)
2370 op->bCancelled = op->progress->HasUserCancelled();
2371
2372 if (op->bCancelled)
2373 break;
2374 *ticks = GetTickCount();
2375 }
2376 } while(FindNextFileW(hFind, &wfd));
2377
2378 FindClose(hFind);
2379 return TRUE;
2380}
const TCHAR * szFiles[]
Definition: CImage.cpp:17
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
Definition: atlsimpstr.h:379
void __cdecl Format(UINT nFormatID,...)
Definition: cstringt.h:753
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
@ IsEmpty
Definition: atl_ax.c:995
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 PathAddBackslashW(LPWSTR lpszPath)
Definition: path.c:294
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 PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend)
Definition: path.c:126
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
LPWSTR WINAPI PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile)
Definition: path.c:194
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:1577
_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:115
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:17
#define L(x)
Definition: ntvdm.h:50
#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:119
#define ASK_OVERWRITE_FILE
Definition: shell32_main.h:116
#define ASK_DELETE_MULTIPLE_ITEM
Definition: shell32_main.h:114
#define ASK_OVERWRITE_FOLDER
Definition: shell32_main.h:122
#define ASK_DELETE_FILE
Definition: shell32_main.h:112
#define ASK_TRASH_FILE
Definition: shell32_main.h:118
#define ASK_DELETE_SELECTED
Definition: shell32_main.h:117
#define ASK_DELETE_FOLDER
Definition: shell32_main.h:113
#define ASK_CANT_TRASH_ITEM
Definition: shell32_main.h:121
#define ASK_TRASH_MULTIPLE_ITEM
Definition: shell32_main.h:120
#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:1163
static HRESULT rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
Definition: shlfileop.cpp:1841
#define IsAttrib(x, y)
Definition: shlfileop.cpp:29
EXTERN_C DWORD WINAPI SheGetDirA(DWORD drive, LPSTR buffer)
Definition: shlfileop.cpp:2108
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:1748
static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:1596
static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly)
Definition: shlfileop.cpp:978
static void parse_wildcard_files(FILE_LIST *flList, LPCWSTR szFile, LPDWORD pdwListIndex)
Definition: shlfileop.cpp:1185
EXTERN_C DWORD WINAPI SheChangeDirW(LPWSTR path)
Definition: shlfileop.cpp:2195
static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo)
Definition: shlfileop.cpp:1469
EXTERN_C int WINAPI IsNetDrive(int drive)
Definition: shlfileop.cpp:2206
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:894
static HRESULT parse_file_list(FILE_LIST *flList, LPCWSTR szFiles)
Definition: shlfileop.cpp:1219
static DWORD _ConvertAtoW(PCSTR strSrc, PCWSTR *pStrDest, BOOL isList)
Definition: shlfileop.cpp:1007
#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 int CALLBACK _DestroyCallback(void *p, void *pData)
Definition: shlfileop.cpp:2070
static void destroy_file_list(FILE_LIST *flList)
Definition: shlfileop.cpp:1289
EXTERN_C HRESULT WINAPI SHIsFileAvailableOffline(LPCWSTR path, LPDWORD status)
Definition: shlfileop.cpp:357
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
Definition: shlfileop.cpp:1982
void WINAPI SHFreeNameMappings(HANDLE hNameMapping)
Definition: shlfileop.cpp:2092
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:1069
static void copy_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
Definition: shlfileop.cpp:1433
static CStringW try_find_new_name(LPCWSTR szDestPath)
Definition: shlfileop.cpp:1306
static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path)
Definition: shlfileop.cpp:446
EXTERN_C DWORD WINAPI SheChangeDirA(LPSTR path)
Definition: shlfileop.cpp:2181
EXTERN_C INT WINAPI RealDriveType(INT drive, BOOL bQueryNet)
Definition: shlfileop.cpp:2218
static void __inline grow_list(FILE_LIST *list)
Definition: shlfileop.cpp:1127
EXTERN_C DWORD WINAPI SheGetDirW(DWORD drive, LPWSTR buffer)
Definition: shlfileop.cpp:2145
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:1137
#define IsAttribDir(x)
Definition: shlfileop.cpp:31
EXTERN_C HRESULT WINAPI SHPathPrepareForWriteA(HWND hwnd, IUnknown *modless, LPCSTR path, DWORD flags)
Definition: shlfileop.cpp:2291
static void create_dest_dirs(LPCWSTR szDestDir)
Definition: shlfileop.cpp:1449
static BOOL copy_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCHAR *szTo)
Definition: shlfileop.cpp:1397
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:2228
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
int WINAPI SHCreateDirectory(HWND hWnd, LPCWSTR path)
Definition: shlfileop.cpp:857
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:716
static HRESULT delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:1618
DWORD WINAPI _FileOpCountManager(FILE_OPERATION *op, const FILE_LIST *flFrom)
Definition: shlfileop.cpp:2306
static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
Definition: shlfileop.cpp:1761
static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
Definition: shlfileop.cpp:1334
static BOOL _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks)
Definition: shlfileop.cpp:2324
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:1717
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:915
static void check_flags(FILEOP_FLAGS fFlags)
Definition: shlfileop.cpp:1867
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:787
static BOOL SHIsCdRom(LPCWSTR path)
Definition: shlfileop.cpp:758
#define SHCNE_RMDIR
Definition: shlobj.h:1746
#define SHCNE_DELETE
Definition: shlobj.h:1744
#define SHCNE_MKDIR
Definition: shlobj.h:1745
#define SHCNE_CREATE
Definition: shlobj.h:1743
#define SHPPFW_IGNOREFILENAME
Definition: shlobj.h:306
#define SHPPFW_ASKDIRCREATE
Definition: shlobj.h:305
#define PROGDLG_AUTOTIME
Definition: shlobj.h:893
#define SHPPFW_DIRCREATE
Definition: shlobj.h:303
#define PROGDLG_NORMAL
Definition: shlobj.h:891
#define SHCNF_PATHW
Definition: shlobj.h:1777
#define IDD_YESTOALL_MSGBOX
Definition: shresdef.h:406
#define IDS_DELETESELECTED_TEXT
Definition: shresdef.h:130
#define IDA_SHELL_DELETE
Definition: shresdef.h:786
#define IDI_SHELL_FOLDER_MOVE2
Definition: shresdef.h:678
#define IDS_MOVEERROR
Definition: shresdef.h:255
#define IDI_SHELL_CONFIRM_DELETE
Definition: shresdef.h:605
#define IDS_MOVEERRORSUBFOLDER
Definition: shresdef.h:253
#define IDS_OVERWRITEFOLDER_TEXT
Definition: shresdef.h:135
#define IDS_FILEOOP_FROM
Definition: shresdef.h:239
#define IDS_FILEOOP_FROM_TO
Definition: shresdef.h:238
#define IDS_CREATEFOLDER_DENIED
Definition: shresdef.h:122
#define IDS_OVERWRITEFILE_CAPTION
Definition: shresdef.h:128
#define IDS_FILEOOP_MOVING
Definition: shresdef.h:236
#define IDS_COPYERRORSUBFOLDER
Definition: shresdef.h:254
#define IDC_YESTOALL_MESSAGE
Definition: shresdef.h:409
#define IDS_CREATEFOLDER_CAPTION
Definition: shresdef.h:123
#define IDS_CANTTRASH_TEXT
Definition: shresdef.h:134
#define IDS_MOVEERRORSAME
Definition: shresdef.h:251
#define IDS_TRASHITEM_TEXT
Definition: shresdef.h:132
#define IDS_DELETEITEM_CAPTION
Definition: shresdef.h:124
#define IDS_FILEOOP_DELETING
Definition: shresdef.h:237
#define IDS_TRASHMULTIPLE_TEXT
Definition: shresdef.h:133
#define IDC_YESTOALL_ICON
Definition: shresdef.h:408
#define IDS_TRASHFOLDER_TEXT
Definition: shresdef.h:131
#define IDS_FILEOOP_COPYING
Definition: shresdef.h:235
#define IDS_DELETEFOLDER_CAPTION
Definition: shresdef.h:125
#define IDS_DELETEITEM_TEXT
Definition: shresdef.h:126
#define IDS_COPYERROR
Definition: shresdef.h:256
#define IDC_YESTOALL
Definition: shresdef.h:407
#define IDI_SHELL_TRASH_FILE
Definition: shresdef.h:590
#define IDS_COPYERRORTITLE
Definition: shresdef.h:249
#define IDS_COPYERRORSAME
Definition: shresdef.h:252
#define IDS_FILEOOP_PREFLIGHT
Definition: shresdef.h:240
#define IDS_MOVEERRORTITLE
Definition: shresdef.h:248
#define IDS_DELETEMULTIPLE_TEXT
Definition: shresdef.h:127
#define IDA_SHELL_COPY
Definition: shresdef.h:782
#define IDS_MOVEERRORSAMEFOLDER
Definition: shresdef.h:250
#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::@3930 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::@2268 u
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
#define ZeroMemory
Definition: winbase.h:1670
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:421
#define DRIVE_REMOTE
Definition: winbase.h:253
#define lstrcmp
Definition: winbase.h:3743
#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:1610
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define SW_HIDE
Definition: winuser.h:762
#define WM_CLOSE
Definition: winuser.h:1611
#define DT_NOPREFIX
Definition: winuser.h:537
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
#define SM_CYSCREEN
Definition: winuser.h:954
#define STM_SETICON
Definition: winuser.h:2082
#define IDCANCEL
Definition: winuser.h:825
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:1730
#define WM_INITDIALOG
Definition: winuser.h:1729
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:1641
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:781
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:830
BOOL WINAPI SetPropW(_In_ HWND, _In_ LPCWSTR, _In_opt_ HANDLE)
HDC WINAPI GetDC(_In_opt_ HWND)
#define MB_ICONEXCLAMATION
Definition: winuser.h:779
#define MB_OK
Definition: winuser.h:784
HANDLE WINAPI GetPropW(_In_ HWND, _In_ LPCWSTR)
HICON WINAPI LoadIconW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2044
#define SM_CXSCREEN
Definition: winuser.h:953
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define IDYES
Definition: winuser.h:829
#define DT_CALCRECT
Definition: winuser.h:526
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
#define MAKEINTRESOURCE
Definition: winuser.h:591
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