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