ReactOS 0.4.15-dev-6694-g4ba8af9
shlfileop.cpp
Go to the documentation of this file.
1/*
2 * SHFileOperation
3 *
4 * Copyright 2000 Juergen Schmied
5 * Copyright 2002 Andriy Palamarchuk
6 * Copyright 2004 Dietrich Teickner (from Odin)
7 * Copyright 2004 Rolf Kalbermatter
8 * Copyright 2019-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include "precomp.h"
26
28
29#define IsAttrib(x, y) ((INVALID_FILE_ATTRIBUTES != (x)) && ((x) & (y)))
30#define IsAttribFile(x) (!((x) & FILE_ATTRIBUTE_DIRECTORY))
31#define IsAttribDir(x) IsAttrib(x, FILE_ATTRIBUTE_DIRECTORY)
32#define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
33
34#define FO_MASK 0xF
35
36#define NEW_FILENAME_ON_COPY_TRIES 100
37
38typedef struct
39{
44 IProgressDialog *progress;
47 WCHAR szBuilderString[50];
49
50#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026
51
52typedef struct
53{
62
63typedef struct
64{
71} FILE_LIST;
72
78static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly);
79static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, FILE_LIST *flTo);
80static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo);
81
83static BOOL _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks);
84
85/* Confirm dialogs with an optional "Yes To All" as used in file operations confirmations
86 */
88{
93};
94
95/* as some buttons may be hidden and the dialog height may change we may need
96 * to move the controls */
97static void confirm_msg_move_button(HWND hDlg, INT iId, INT *xPos, INT yOffset, BOOL bShow)
98{
99 HWND hButton = GetDlgItem(hDlg, iId);
100 RECT r;
101
102 if (bShow)
103 {
104 POINT pt;
105 int width;
106
107 GetWindowRect(hButton, &r);
108 width = r.right - r.left;
109 pt.x = r.left;
110 pt.y = r.top;
111 ScreenToClient(hDlg, &pt);
112 MoveWindow(hButton, *xPos - width, pt.y - yOffset, width, r.bottom - r.top, FALSE);
113 *xPos -= width + 5;
114 }
115 else
116 ShowWindow(hButton, SW_HIDE);
117}
118
119/* Note: we paint the text manually and don't use the static control to make
120 * sure the text has the same height as the one computed in WM_INITDIALOG
121 */
123{
124 PAINTSTRUCT ps;
125 HFONT hOldFont;
126 RECT r;
127 HDC hdc;
128
129 BeginPaint(hDlg, &ps);
130 hdc = ps.hdc;
132
134 /* this will remap the rect to dialog coords */
137 DrawTextW(hdc, (LPWSTR)GetPropW(hDlg, L"WINE_CONFIRM"), -1, &r, DT_NOPREFIX | DT_PATH_ELLIPSIS | DT_WORDBREAK);
138 SelectObject(hdc, hOldFont);
139 EndPaint(hDlg, &ps);
140
141 return TRUE;
142}
143
145{
146 struct confirm_msg_info *info = (struct confirm_msg_info *)lParam;
147 INT xPos, yOffset;
148 int width, height;
149 HFONT hOldFont;
150 HDC hdc;
151 RECT r;
152
153 SetWindowTextW(hDlg, info->lpszCaption);
155 SetPropW(hDlg, L"WINE_CONFIRM", info->lpszText);
157
158 /* compute the text height and resize the dialog */
160 hdc = GetDC(hDlg);
161 yOffset = r.bottom;
164 SelectObject(hdc, hOldFont);
165 yOffset -= r.bottom;
166 yOffset = min(yOffset, 35); /* don't make the dialog too small */
167 ReleaseDC(hDlg, hdc);
168
169 GetClientRect(hDlg, &r);
170 xPos = r.right - 7;
171 GetWindowRect(hDlg, &r);
172 width = r.right - r.left;
173 height = r.bottom - r.top - yOffset;
176
177 confirm_msg_move_button(hDlg, IDCANCEL, &xPos, yOffset, info->bYesToAll);
179 confirm_msg_move_button(hDlg, IDC_YESTOALL, &xPos, yOffset, info->bYesToAll);
181
182 return TRUE;
183}
184
186{
187 switch (uMsg)
188 {
189 case WM_INITDIALOG:
190 return ConfirmMsgBox_Init(hDlg, lParam);
191 case WM_PAINT:
192 return ConfirmMsgBox_Paint(hDlg);
193 case WM_COMMAND:
194 EndDialog(hDlg, wParam);
195 break;
196 case WM_CLOSE:
197 EndDialog(hDlg, IDCANCEL);
198 break;
199 }
200 return FALSE;
201}
202
204{
205 struct confirm_msg_info info;
206
207 info.lpszText = lpszText;
208 info.lpszCaption = lpszCaption;
209 info.hIcon = hIcon;
210 info.bYesToAll = bYesToAll;
212}
213
214/* confirmation dialogs content */
215typedef struct
216{
219 UINT caption_resource_id, text_resource_id;
221
223{
224 ids->hIconInstance = shell32_hInstance;
225 switch (nKindOfDialog)
226 {
227 case ASK_DELETE_FILE:
228 ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
229 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
230 ids->text_resource_id = IDS_DELETEITEM_TEXT;
231 return TRUE;
232
234 ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
235 ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION;
236 ids->text_resource_id = IDS_DELETEITEM_TEXT;
237 return TRUE;
238
240 ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
241 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
242 ids->text_resource_id = IDS_DELETEMULTIPLE_TEXT;
243 return TRUE;
244
245 case ASK_TRASH_FILE:
246 ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
247 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
248 ids->text_resource_id = IDS_TRASHITEM_TEXT;
249 return TRUE;
250
251 case ASK_TRASH_FOLDER:
252 ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
253 ids->caption_resource_id = IDS_DELETEFOLDER_CAPTION;
254 ids->text_resource_id = IDS_TRASHFOLDER_TEXT;
255 return TRUE;
256
258 ids->icon_resource_id = IDI_SHELL_TRASH_FILE;
259 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
260 ids->text_resource_id = IDS_TRASHMULTIPLE_TEXT;
261 return TRUE;
262
264 ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
265 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
266 ids->text_resource_id = IDS_CANTTRASH_TEXT;
267 return TRUE;
268
270 ids->icon_resource_id = IDI_SHELL_CONFIRM_DELETE;
271 ids->caption_resource_id = IDS_DELETEITEM_CAPTION;
272 ids->text_resource_id = IDS_DELETESELECTED_TEXT;
273 return TRUE;
274
276 ids->icon_resource_id = IDI_SHELL_FOLDER_MOVE2;
277 ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
278 ids->text_resource_id = IDS_OVERWRITEFILE_TEXT;
279 return TRUE;
280
282 ids->icon_resource_id = IDI_SHELL_FOLDER_MOVE2;
283 ids->caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
284 ids->text_resource_id = IDS_OVERWRITEFOLDER_TEXT;
285 return TRUE;
286
287 default:
288 FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
289 }
290 return FALSE;
291}
292
293static BOOL SHELL_ConfirmDialogW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir, FILE_OPERATION *op)
294{
295 WCHAR szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
297 DWORD_PTR args[1];
298 HICON hIcon;
299 int ret;
300
301 assert(nKindOfDialog >= 0 && nKindOfDialog < 32);
302 if (op && (op->dwYesToAllMask & (1 << nKindOfDialog)))
303 return TRUE;
304
305 if (!SHELL_ConfirmIDs(nKindOfDialog, &ids)) return FALSE;
306
307 LoadStringW(shell32_hInstance, ids.caption_resource_id, szCaption, sizeof(szCaption)/sizeof(WCHAR));
308 LoadStringW(shell32_hInstance, ids.text_resource_id, szText, sizeof(szText)/sizeof(WCHAR));
309
310 args[0] = (DWORD_PTR)szDir;
312 szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)args);
313 hIcon = LoadIconW(ids.hIconInstance, (LPWSTR)MAKEINTRESOURCE(ids.icon_resource_id));
314
315 ret = SHELL_ConfirmMsgBox(hWnd, szBuffer, szCaption, hIcon, op && op->bManyItems);
316 if (op)
317 {
318 if (ret == IDC_YESTOALL)
319 {
320 op->dwYesToAllMask |= (1 << nKindOfDialog);
321 ret = IDYES;
322 }
323 if (ret == IDCANCEL)
324 op->bCancelled = TRUE;
325 if (ret != IDYES)
326 op->req->fAnyOperationsAborted = TRUE;
327 }
328 return ret == IDYES;
329}
330
331BOOL SHELL_ConfirmYesNoW(HWND hWnd, int nKindOfDialog, LPCWSTR szDir)
332{
333 return SHELL_ConfirmDialogW(hWnd, nKindOfDialog, szDir, NULL);
334}
335
336static DWORD SHELL32_AnsiToUnicodeBuf(LPCSTR aPath, LPWSTR *wPath, DWORD minChars)
337{
338 DWORD len = MultiByteToWideChar(CP_ACP, 0, aPath, -1, NULL, 0);
339
340 if (len < minChars)
341 len = minChars;
342
343 *wPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
344 if (*wPath)
345 {
346 MultiByteToWideChar(CP_ACP, 0, aPath, -1, *wPath, len);
347 return NO_ERROR;
348 }
349 return E_OUTOFMEMORY;
350}
351
353{
354 HeapFree(GetProcessHeap(), 0, wPath);
355}
356
358{
359 FIXME("(%s, %p) stub\n", debugstr_w(path), status);
360 return E_FAIL;
361}
362
363/**************************************************************************
364 * SHELL_DeleteDirectory() [internal]
365 *
366 * Asks for confirmation when bShowUI is true and deletes the directory and
367 * all its subdirectories and files if necessary.
368 */
370{
371 BOOL ret = TRUE;
372 HANDLE hFind;
374 WCHAR szTemp[MAX_PATH];
375
376 /* Make sure the directory exists before eventually prompting the user */
377 PathCombineW(szTemp, pszDir, L"*");
378 hFind = FindFirstFileW(szTemp, &wfd);
379 if (hFind == INVALID_HANDLE_VALUE)
380 return FALSE;
381
382 if (!bShowUI || (ret = SHELL_ConfirmDialogW(op->req->hwnd, ASK_DELETE_FOLDER, pszDir, NULL)))
383 {
384 do
385 {
386 if (IsDotDir(wfd.cFileName))
387 continue;
388 PathCombineW(szTemp, pszDir, wfd.cFileName);
389 if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
391 else
392 ret = (SHNotifyDeleteFileW(op, szTemp) == ERROR_SUCCESS);
393
394 if (op->progress != NULL)
395 op->bCancelled |= op->progress->HasUserCancelled();
396 } while (ret && FindNextFileW(hFind, &wfd) && !op->bCancelled);
397 }
398 FindClose(hFind);
399 if (ret)
401 return ret;
402}
403
404/**************************************************************************
405 * Win32CreateDirectory [SHELL32.93]
406 *
407 * Creates a directory. Also triggers a change notify if one exists.
408 *
409 * PARAMS
410 * path [I] path to directory to create
411 *
412 * RETURNS
413 * TRUE if successful, FALSE otherwise
414 */
415
417{
418 TRACE("(%s, %p)\n", debugstr_w(path), sec);
419
420 if (CreateDirectoryW(path, sec))
421 {
423 return ERROR_SUCCESS;
424 }
425 return GetLastError();
426}
427
428/**********************************************************************/
429
431{
433}
434
435/************************************************************************
436 * Win32RemoveDirectory [SHELL32.94]
437 *
438 * Deletes a directory. Also triggers a change notify if one exists.
439 *
440 * PARAMS
441 * path [I] path to directory to delete
442 *
443 * RETURNS
444 * TRUE if successful, FALSE otherwise
445 */
447{
448 BOOL ret;
449 TRACE("(%s)\n", debugstr_w(path));
450
452 if (!ret)
453 {
454 /* Directory may be write protected */
455 DWORD dwAttr = GetFileAttributesW(path);
459 }
460 if (ret)
461 {
463 return ERROR_SUCCESS;
464 }
465 return GetLastError();
466}
467
468/***********************************************************************/
469
471{
473}
474
476 if (op->progress == NULL)
477 return;
478 WCHAR szTitle[50], szPreflight[50];
479 UINT animation_id = NULL;
480
481 switch (op->req->wFunc)
482 {
483 case FO_COPY:
485 LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM_TO, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
486 animation_id = IDA_SHELL_COPY;
487 break;
488 case FO_DELETE:
490 LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
491 animation_id = IDA_SHELL_DELETE;
492 break;
493 case FO_MOVE:
495 LoadStringW(shell32_hInstance, IDS_FILEOOP_FROM_TO, op->szBuilderString, sizeof( op->szBuilderString)/sizeof(WCHAR));
496 animation_id = IDA_SHELL_COPY;
497 break;
498 default:
499 return;
500 }
501 LoadStringW(shell32_hInstance, IDS_FILEOOP_PREFLIGHT, szPreflight, sizeof(szPreflight)/sizeof(WCHAR));
502
503 op->progress->SetTitle(szTitle);
504 op->progress->SetLine(1, szPreflight, false, NULL);
505 op->progress->SetAnimation(shell32_hInstance, animation_id);
506}
507
509 if (op->progress == NULL || src == NULL)
510 return;
511 LPWSTR fileSpecS, pathSpecS, fileSpecD, pathSpecD;
512 WCHAR szFolderS[50], szFolderD[50], szFinalString[260];
513
514 DWORD_PTR args[2];
515
516 fileSpecS = (pathSpecS = (LPWSTR) src);
517 fileSpecD = (pathSpecD = (LPWSTR) dest);
518
519 // March across the string to get the file path and it's parent dir.
520 for (LPWSTR ptr = (LPWSTR) src; *ptr; ptr++) {
521 if (*ptr == '\\') {
522 pathSpecS = fileSpecS;
523 fileSpecS = ptr+1;
524 }
525 }
526 lstrcpynW(szFolderS, pathSpecS, min(50, fileSpecS - pathSpecS));
527 args[0] = (DWORD_PTR) szFolderS;
528
529 switch (op->req->wFunc)
530 {
531 case FO_COPY:
532 case FO_MOVE:
533 if (dest == NULL)
534 return;
535 for (LPWSTR ptr = (LPWSTR) dest; *ptr; ptr++) {
536 if (*ptr == '\\') {
537 pathSpecD = fileSpecD;
538 fileSpecD = ptr + 1;
539 }
540 }
541 lstrcpynW(szFolderD, pathSpecD, min(50, fileSpecD - pathSpecD));
542 args[1] = (DWORD_PTR) szFolderD;
543 break;
544 case FO_DELETE:
545 break;
546 default:
547 return;
548 }
549
551 op->szBuilderString, 0, 0, szFinalString, sizeof(szFinalString), (va_list*)args);
552
553 op->progress->SetLine(1, fileSpecS, false, NULL);
554 op->progress->SetLine(2, szFinalString, false, NULL);
555}
556
557
559 LARGE_INTEGER TotalFileSize,
560 LARGE_INTEGER TotalBytesTransferred,
561 LARGE_INTEGER StreamSize,
562 LARGE_INTEGER StreamBytesTransferred,
563 DWORD dwStreamNumber,
564 DWORD dwCallbackReason,
565 HANDLE hSourceFile,
566 HANDLE hDestinationFile,
567 LPVOID lpData
568) {
569 FILE_OPERATION *op = (FILE_OPERATION *) lpData;
570
571 if (op->progress) {
572 /*
573 * This is called at the start of each file. To keop less state,
574 * I'm adding the file to the completed size here, and the re-subtracting
575 * it when drawing the progress bar.
576 */
577 if (dwCallbackReason & CALLBACK_STREAM_SWITCH)
578 op->completedSize.QuadPart += TotalFileSize.QuadPart;
579
580 op->progress->SetProgress64(op->completedSize.QuadPart -
581 TotalFileSize.QuadPart +
582 TotalBytesTransferred.QuadPart
583 , op->totalSize.QuadPart);
584
585
586 op->bCancelled = op->progress->HasUserCancelled();
587 }
588
589 return 0;
590}
591
592
593/************************************************************************
594 * SHNotifyDeleteFileW [internal]
595 *
596 * Deletes a file. Also triggers a change notify if one exists.
597 *
598 * PARAMS
599 * op [I] File Operation context
600 * path [I] path to source file to move
601 *
602 * RETURNS
603 * ERORR_SUCCESS if successful
604 */
606{
607 BOOL ret;
608
609 TRACE("(%s)\n", debugstr_w(path));
610
612
614 FileSize.QuadPart = 0;
615
618 if (hFile != INVALID_HANDLE_VALUE && IsAttribFile(wfd.dwFileAttributes)) {
619 ULARGE_INTEGER tmp;
620 tmp.u.LowPart = wfd.nFileSizeLow;
621 tmp.u.HighPart = wfd.nFileSizeHigh;
623 }
625
627 if (!ret)
628 {
629 /* File may be write protected or a system file */
630 DWORD dwAttr = GetFileAttributesW(path);
634 }
635 if (ret)
636 {
637 // Bit of a hack to make the progress bar move. We don't have progress inside the file, so inform when done.
640 return ERROR_SUCCESS;
641 }
642 return GetLastError();
643}
644
645/************************************************************************
646 * Win32DeleteFile [SHELL32.164]
647 *
648 * Deletes a file. Also triggers a change notify if one exists.
649 *
650 * PARAMS
651 * path [I] path to file to delete
652 *
653 * RETURNS
654 * TRUE if successful, FALSE otherwise
655 */
657{
659}
660
661#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{
1221 LPCWSTR ptr = szFiles;
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#ifdef __REACTOS__
1748static BOOL move_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCHAR *szTo)
1749{
1750 if (PathFileExistsW(szTo))
1751 {
1752 if (op->req->fFlags & FOF_RENAMEONCOLLISION)
1753 {
1754 CStringW newPath = try_find_new_name(szTo);
1755 if (!newPath.IsEmpty())
1756 {
1757 return SHNotifyMoveFileW(op, szFrom, newPath, FALSE) == 0;
1758 }
1759 }
1760 else if (!(op->req->fFlags & FOF_NOCONFIRMATION))
1761 {
1763 return FALSE;
1764 }
1765 }
1766
1767 return SHNotifyMoveFileW(op, szFrom, szTo, FALSE) == 0;
1768}
1769#endif
1770
1771/* moves a file or directory to another directory */
1772static void move_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
1773{
1774 WCHAR szDestPath[MAX_PATH];
1775
1776#ifdef __REACTOS__
1777 if (!PathFileExistsW(feTo->szFullPath))
1779#endif
1780
1781 PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
1782
1783 if (IsAttribFile(feFrom->attributes))
1784#ifdef __REACTOS__
1785 move_file_to_file(op, feFrom->szFullPath, szDestPath);
1786#else
1787 SHNotifyMoveFileW(op, feFrom->szFullPath, szDestPath, FALSE);
1788#endif
1789 else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
1790 move_dir_to_dir(op, feFrom, szDestPath);
1791}
1792
1793/* the FO_MOVE operation */
1794static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1795{
1796 DWORD i;
1797 INT mismatched = 0;
1798
1799 const FILE_ENTRY *entryToMove;
1800 const FILE_ENTRY *fileDest;
1801
1802 if (!flFrom->dwNumFiles)
1803 return ERROR_SUCCESS;
1804
1805 if (!flTo->dwNumFiles)
1806 return ERROR_FILE_NOT_FOUND;
1807
1808 if (!(multiDest) &&
1809 flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
1810 {
1811 return ERROR_CANCELLED;
1812 }
1813
1814 if (!(multiDest) &&
1815 !flFrom->bAnyDirectories &&
1816 flFrom->dwNumFiles > flTo->dwNumFiles &&
1817 !(flTo->bAnyDirectories && flTo->dwNumFiles == 1))
1818 {
1819 return ERROR_CANCELLED;
1820 }
1821
1822 if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
1823 return ERROR_CANCELLED;
1824
1825 if (multiDest)
1826 mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
1827
1828 fileDest = &flTo->feFiles[0];
1829 for (i = 0; i < flFrom->dwNumFiles; i++)
1830 {
1831 entryToMove = &flFrom->feFiles[i];
1832
1833 if (!PathFileExistsW(fileDest->szDirectory))
1834 return ERROR_CANCELLED;
1835
1836 if (multiDest)
1837 {
1838 if (i >= flTo->dwNumFiles)
1839 break;
1840 fileDest = &flTo->feFiles[i];
1841 if (mismatched && !fileDest->bExists)
1842 {
1844 flTo->feFiles[i].bExists = TRUE;
1846 }
1847 }
1848
1849#ifdef __REACTOS__
1850 if ((flFrom->dwNumFiles > 1 && flTo->dwNumFiles == 1) ||
1851 IsAttribDir(fileDest->attributes))
1852 {
1853 move_to_dir(op, entryToMove, fileDest);
1854 }
1855 else if (IsAttribDir(entryToMove->attributes))
1856 {
1857 move_dir_to_dir(op, entryToMove, fileDest->szFullPath);
1858 }
1859 else
1860 {
1861 if (!move_file_to_file(op, entryToMove->szFullPath, fileDest->szFullPath))
1862 {
1863 op->req->fAnyOperationsAborted = TRUE;
1864 return ERROR_CANCELLED;
1865 }
1866 }
1867#else
1868 if (fileDest->bExists && IsAttribDir(fileDest->attributes))
1869 move_to_dir(op, entryToMove, fileDest);
1870 else
1871 SHNotifyMoveFileW(op, entryToMove->szFullPath, fileDest->szFullPath, IsAttribDir(entryToMove->attributes));
1872#endif
1873
1874 if (op->progress != NULL)
1875 op->bCancelled |= op->progress->HasUserCancelled();
1876 /* Should fire on progress dialog only */
1877 if (op->bCancelled)
1878 return ERROR_CANCELLED;
1879
1880 }
1881
1882 if (mismatched > 0)
1883 {
1884 if (flFrom->bAnyDirectories)
1885 return DE_DESTSAMETREE;
1886 else
1887 return DE_SAMEFILE;
1888 }
1889
1890 return ERROR_SUCCESS;
1891}
1892
1893/* the FO_RENAME files */
1894static HRESULT rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
1895{
1896 const FILE_ENTRY *feFrom;
1897 const FILE_ENTRY *feTo;
1898
1899 if (flFrom->dwNumFiles != 1)
1900 return ERROR_GEN_FAILURE;
1901
1902 if (flTo->dwNumFiles != 1)
1903 return ERROR_CANCELLED;
1904
1905 feFrom = &flFrom->feFiles[0];
1906 feTo= &flTo->feFiles[0];
1907
1908 /* fail if destination doesn't exist */
1909 if (!feFrom->bExists)
1911
1912 /* fail if destination already exists */
1913 if (feTo->bExists)
1914 return ERROR_ALREADY_EXISTS;
1915
1916 return SHNotifyMoveFileW(op, feFrom->szFullPath, feTo->szFullPath, IsAttribDir(feFrom->attributes));
1917}
1918
1919/* alert the user if an unsupported flag is used */
1920static void check_flags(FILEOP_FLAGS fFlags)
1921{
1922 WORD wUnsupportedFlags = FOF_NO_CONNECTED_ELEMENTS |
1924#ifdef __REACTOS__
1926#else
1928#endif
1929
1930 if (fFlags & wUnsupportedFlags)
1931 FIXME("Unsupported flags: %04x\n", fFlags);
1932}
1933
1934#ifdef __REACTOS__
1935
1936static DWORD
1937validate_operation(LPSHFILEOPSTRUCTW lpFileOp, FILE_LIST *flFrom, FILE_LIST *flTo)
1938{
1939 DWORD i, k, dwNumDest;
1940 WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
1941 CStringW strTitle, strText;
1942 const FILE_ENTRY *feFrom;
1943 const FILE_ENTRY *feTo;
1944 UINT wFunc = lpFileOp->wFunc;
1945 HWND hwnd = lpFileOp->hwnd;
1946
1947 dwNumDest = flTo->dwNumFiles;
1948
1949 if (wFunc != FO_COPY && wFunc != FO_MOVE)
1950 return ERROR_SUCCESS;
1951
1952 for (k = 0; k < dwNumDest; ++k)
1953 {
1954 feTo = &flTo->feFiles[k];
1955 for (i = 0; i < flFrom->dwNumFiles; ++i)
1956 {
1957 feFrom = &flFrom->feFiles[i];
1958 StringCbCopyW(szFrom, sizeof(szFrom), feFrom->szFullPath);
1959 StringCbCopyW(szTo, sizeof(szTo), feTo->szFullPath);
1960 if (IsAttribDir(feTo->attributes))
1961 {
1962 PathAppendW(szTo, feFrom->szFilename);
1963 }
1964
1965 // same path?
1966 if (lstrcmpiW(szFrom, szTo) == 0 &&
1967 (wFunc == FO_MOVE || !(lpFileOp->fFlags & FOF_RENAMEONCOLLISION)))
1968 {
1969 if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
1970 {
1971 if (wFunc == FO_MOVE)
1972 {
1973 strTitle.LoadStringW(IDS_MOVEERRORTITLE);
1974 if (IsAttribDir(feFrom->attributes))
1975 strText.Format(IDS_MOVEERRORSAMEFOLDER, feFrom->szFilename);
1976 else
1977 strText.Format(IDS_MOVEERRORSAME, feFrom->szFilename);
1978 }
1979 else
1980 {
1981 strTitle.LoadStringW(IDS_COPYERRORTITLE);
1982 strText.Format(IDS_COPYERRORSAME, feFrom->szFilename);
1983 return ERROR_SUCCESS;
1984 }
1985 MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
1986 return DE_SAMEFILE;
1987 }
1988 return DE_OPCANCELLED;
1989 }
1990
1991 // subfolder?
1992 if (IsAttribDir(feFrom->attributes))
1993 {
1994 size_t cchFrom = PathAddBackslashW(szFrom) - szFrom;
1995 size_t cchTo = PathAddBackslashW(szTo) - szTo;
1996 if (cchFrom < cchTo)
1997 {
1998 WCHAR ch = szTo[cchFrom];
1999 szTo[cchFrom] = 0;
2000 int compare = lstrcmpiW(szFrom, szTo);
2001 szTo[cchFrom] = ch;
2002
2003 if (compare == 0)
2004 {
2005 if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT)))
2006 {
2007 if (wFunc == FO_MOVE)
2008 {
2009 strTitle.LoadStringW(IDS_MOVEERRORTITLE);
2010 strText.Format(IDS_MOVEERRORSUBFOLDER, feFrom->szFilename);
2011 }
2012 else
2013 {
2014 strTitle.LoadStringW(IDS_COPYERRORTITLE);
2015 strText.Format(IDS_COPYERRORSUBFOLDER, feFrom->szFilename);
2016 }
2017 MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR);
2018 return DE_DESTSUBTREE;
2019 }
2020 return DE_OPCANCELLED;
2021 }
2022 }
2023 }
2024 }
2025 }
2026
2027 return ERROR_SUCCESS;
2028}
2029#endif
2030/*************************************************************************
2031 * SHFileOperationW [SHELL32.@]
2032 *
2033 * See SHFileOperationA
2034 */
2036{
2038 FILE_LIST flFrom, flTo;
2039 int ret = 0;
2040
2041 if (!lpFileOp)
2043
2045 if (FAILED(ret))
2046 return ret;
2047
2048 lpFileOp->fAnyOperationsAborted = FALSE;
2049 check_flags(lpFileOp->fFlags);
2050
2051 ZeroMemory(&flFrom, sizeof(FILE_LIST));
2052 ZeroMemory(&flTo, sizeof(FILE_LIST));
2053
2054 if ((ret = parse_file_list(&flFrom, lpFileOp->pFrom)))
2055 return ret;
2056
2057 if (lpFileOp->wFunc != FO_DELETE)
2058 parse_file_list(&flTo, lpFileOp->pTo);
2059
2060 ZeroMemory(&op, sizeof(op));
2061 op.req = lpFileOp;
2062 op.totalSize.QuadPart = 0ull;
2063 op.completedSize.QuadPart = 0ull;
2064 op.bManyItems = (flFrom.dwNumFiles > 1);
2065
2066#ifdef __REACTOS__
2067 ret = validate_operation(lpFileOp, &flFrom, &flTo);
2068 if (ret)
2069 goto cleanup;
2070#endif
2071 if (lpFileOp->wFunc != FO_RENAME && !(lpFileOp->fFlags & FOF_SILENT)) {
2072 ret = CoCreateInstance(CLSID_ProgressDialog,
2073 NULL,
2074 CLSCTX_INPROC_SERVER,
2075 IID_PPV_ARG(IProgressDialog, &op.progress));
2076 if (FAILED(ret))
2077 goto cleanup;
2078
2079 op.progress->StartProgressDialog(op.req->hwnd, NULL, PROGDLG_NORMAL & PROGDLG_AUTOTIME, NULL);
2081 _FileOpCountManager(&op, &flFrom);
2082 }
2083
2084 switch (lpFileOp->wFunc)
2085 {
2086 case FO_COPY:
2087 ret = copy_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
2088 break;
2089 case FO_DELETE:
2090 ret = delete_files(&op, &flFrom);
2091 break;
2092 case FO_MOVE:
2093 ret = move_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
2094 break;
2095 case FO_RENAME:
2096 ret = rename_files(&op, &flFrom, &flTo);
2097 break;
2098 default:
2100 break;
2101 }
2102
2103 if (op.progress) {
2104 op.progress->StopProgressDialog();
2105 op.progress->Release();
2106 }
2107
2108cleanup:
2109 destroy_file_list(&flFrom);
2110
2111 if (lpFileOp->wFunc != FO_DELETE)
2112 destroy_file_list(&flTo);
2113
2114 if (ret == ERROR_CANCELLED)
2115 lpFileOp->fAnyOperationsAborted = TRUE;
2116
2118
2119 return ret;
2120}
2121
2122// Used by SHFreeNameMappings
2123static int CALLBACK _DestroyCallback(void *p, void *pData)
2124{
2126
2127 SHFree(lp->pszOldPath);
2128 SHFree(lp->pszNewPath);
2129
2130 return TRUE;
2131}
2132
2133/*************************************************************************
2134 * SHFreeNameMappings [shell32.246]
2135 *
2136 * Free the mapping handle returned by SHFileOperation if FOF_WANTSMAPPINGHANDLE
2137 * was specified.
2138 *
2139 * PARAMS
2140 * hNameMapping [I] handle to the name mappings used during renaming of files
2141 *
2142 * RETURNS
2143 * Nothing
2144 */
2146{
2147 if (hNameMapping)
2148 {
2150 }
2151}
2152
2153/*************************************************************************
2154 * SheGetDirA [SHELL32.@]
2155 *
2156 * drive = 0: returns the current directory path
2157 * drive > 0: returns the current directory path of the specified drive
2158 * drive=1 -> A: drive=2 -> B: ...
2159 * returns 0 if successful
2160*/
2162{
2163 WCHAR org_path[MAX_PATH];
2164 DWORD ret;
2165 char drv_path[3];
2166
2167 /* change current directory to the specified drive */
2168 if (drive) {
2169 strcpy(drv_path, "A:");
2170 drv_path[0] += (char)drive-1;
2171
2172 GetCurrentDirectoryW(MAX_PATH, org_path);
2173
2174 SetCurrentDirectoryA(drv_path);
2175 }
2176
2177 /* query current directory path of the specified drive */
2179
2180 /* back to the original drive */
2181 if (drive)
2182 SetCurrentDirectoryW(org_path);
2183
2184 if (!ret)
2185 return GetLastError();
2186
2187 return 0;
2188}
2189
2190/*************************************************************************
2191 * SheGetDirW [SHELL32.@]
2192 *
2193 * drive = 0: returns the current directory path
2194 * drive > 0: returns the current directory path of the specified drive
2195 * drive=1 -> A: drive=2 -> B: ...
2196 * returns 0 if successful
2197 */
2199{
2200 WCHAR org_path[MAX_PATH];
2201 DWORD ret;
2202 char drv_path[3];
2203
2204 /* change current directory to the specified drive */
2205 if (drive)
2206 {
2207 strcpy(drv_path, "A:");
2208 drv_path[0] += (char)drive-1;
2209
2210 GetCurrentDirectoryW(MAX_PATH, org_path);
2211
2212 SetCurrentDirectoryA(drv_path);
2213 }
2214
2215 /* query current directory path of the specified drive */
2217
2218 /* back to the original drive */
2219 if (drive)
2220 SetCurrentDirectoryW(org_path);
2221
2222 if (!ret)
2223 return GetLastError();
2224
2225 return 0;
2226}
2227
2228/*************************************************************************
2229 * SheChangeDirA [SHELL32.@]
2230 *
2231 * changes the current directory to the specified path
2232 * and returns 0 if successful
2233 */
2235{
2237 return 0;
2238 else
2239 return GetLastError();
2240}
2241
2242/*************************************************************************
2243 * SheChangeDirW [SHELL32.@]
2244 *
2245 * changes the current directory to the specified path
2246 * and returns 0 if successful
2247 */
2249{
2251 return 0;
2252 else
2253 return GetLastError();
2254}
2255
2256/*************************************************************************
2257 * IsNetDrive [SHELL32.66]
2258 */
2260{
2261 char root[4];
2262 strcpy(root, "A:\\");
2263 root[0] += (char)drive;
2264 return (GetDriveTypeA(root) == DRIVE_REMOTE);
2265}
2266
2267
2268/*************************************************************************
2269 * RealDriveType [SHELL32.524]
2270 */
2272{
2273 char root[] = "A:\\";
2274 root[0] += (char)drive;
2275 return GetDriveTypeA(root);
2276}
2277
2278/***********************************************************************
2279 * SHPathPrepareForWriteW (SHELL32.@)
2280 */
2282{
2283 DWORD res;
2284 DWORD err;
2285 LPCWSTR realpath;
2286 int len;
2287 WCHAR* last_slash;
2288 WCHAR* temppath=NULL;
2289
2290 TRACE("%p %p %s 0x%08x\n", hwnd, modless, debugstr_w(path), flags);
2291
2293 FIXME("unimplemented flags 0x%08x\n", flags);
2294
2295 /* cut off filename if necessary */
2297 {
2298 last_slash = StrRChrW(path, NULL, '\\');
2299 if (last_slash == NULL)
2300 len = 1;
2301 else
2302 len = last_slash - path + 1;
2303 temppath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2304 if (!temppath)
2305 return E_OUTOFMEMORY;
2306 StrCpyNW(temppath, path, len);
2307 realpath = temppath;
2308 }
2309 else
2310 {
2311 realpath = path;
2312 }
2313
2314 /* try to create the directory if asked to */
2316 {
2318 FIXME("treating SHPPFW_ASKDIRCREATE as SHPPFW_DIRCREATE\n");
2319
2320 SHCreateDirectoryExW(0, realpath, NULL);
2321 }
2322
2323 /* check if we can access the directory */
2324 res = GetFileAttributesW(realpath);
2325
2326 HeapFree(GetProcessHeap(), 0, temppath);
2327
2329 {
2330 err = GetLastError();
2333 return HRESULT_FROM_WIN32(err);
2334 }
2335 else if (res & FILE_ATTRIBUTE_DIRECTORY)
2336 return S_OK;
2337 else
2339}
2340
2341/***********************************************************************
2342 * SHPathPrepareForWriteA (SHELL32.@)
2343 */
2345{
2346 WCHAR wpath[MAX_PATH];
2347 MultiByteToWideChar( CP_ACP, 0, path, -1, wpath, MAX_PATH);
2348 return SHPathPrepareForWriteW(hwnd, modless, wpath, flags);
2349}
2350
2351
2352/*
2353 * The two following background operations were modified from filedefext.cpp
2354 * They use an inordinate amount of mutable state across the string functions,
2355 * so are not easy to follow and care is required when modifying.
2356 */
2357
2360{
2361 DWORD ticks = GetTickCount();
2362 FILE_ENTRY *entryToCount;
2363
2364 for (UINT i = 0; i < from->dwNumFiles; i++)
2365 {
2366 entryToCount = &from->feFiles[i];
2367
2368 WCHAR theFileName[MAX_PATH];
2369 StringCchCopyW(theFileName, MAX_PATH, entryToCount->szFullPath);
2370 _FileOpCount(op, theFileName, IsAttribDir(entryToCount->attributes), &ticks);
2371 }
2372 return 0;
2373}
2374
2375// All path manipulations, even when this function is nested, occur on the one buffer.
2376static BOOL
2377_FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks)
2378{
2379 /* Find filename position */
2380 UINT cchBuf = wcslen(pwszBuf);
2381 WCHAR *pwszFilename = pwszBuf + cchBuf;
2382 size_t cchFilenameMax = MAX_PATH - cchBuf;
2383 if (!cchFilenameMax)
2384 return FALSE;
2385
2386 if (bFolder) {
2387 *(pwszFilename++) = '\\';
2388 --cchFilenameMax;
2389 /* Find all files, FIXME: shouldn't be "*"? */
2390 StringCchCopyW(pwszFilename, cchFilenameMax, L"*");
2391 }
2392
2393 WIN32_FIND_DATAW wfd;
2394 HANDLE hFind = FindFirstFileW(pwszBuf, &wfd);
2395 if (hFind == INVALID_HANDLE_VALUE)
2396 {
2397 ERR("FindFirstFileW %ls failed\n", pwszBuf);
2398 return FALSE;
2399 }
2400
2401 do
2402 {
2403 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2404 {
2405 /* Don't process "." and ".." items */
2406 if (!wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L".."))
2407 continue;
2408
2409 StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName);
2410 _FileOpCount(op, pwszBuf, TRUE, ticks);
2411 }
2412 else
2413 {
2415 FileSize.u.LowPart = wfd.nFileSizeLow;
2416 FileSize.u.HighPart = wfd.nFileSizeHigh;
2417 op->totalSize.QuadPart += FileSize.QuadPart;
2418 }
2419 if (GetTickCount() - *ticks > (DWORD) 500)
2420 {
2421 // Check if the dialog has ended. If it has, we'll spin down.
2422 if (op->progress != NULL)
2423 op->bCancelled = op->progress->HasUserCancelled();
2424
2425 if (op->bCancelled)
2426 break;
2427 *ticks = GetTickCount();
2428 }
2429 } while(FindNextFileW(hFind, &wfd));
2430
2431 FindClose(hFind);
2432 return TRUE;
2433}
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:389
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
@ 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:1594
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define DRIVE_CDROM
Definition: machpc98.h: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:16
#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:1894
#define IsAttrib(x, y)
Definition: shlfileop.cpp:29
EXTERN_C DWORD WINAPI SheGetDirA(DWORD drive, LPSTR buffer)
Definition: shlfileop.cpp:2161
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:1772
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:2248
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:2259
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:2123
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:2035
void WINAPI SHFreeNameMappings(HANDLE hNameMapping)
Definition: shlfileop.cpp:2145
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:2234
EXTERN_C INT WINAPI RealDriveType(INT drive, BOOL bQueryNet)
Definition: shlfileop.cpp:2271
static void __inline grow_list(FILE_LIST *list)
Definition: shlfileop.cpp:1127
EXTERN_C DWORD WINAPI SheGetDirW(DWORD drive, LPWSTR buffer)
Definition: shlfileop.cpp:2198
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:2344
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:2281
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:2359
static DWORD move_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
Definition: shlfileop.cpp:1794
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:2377
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:1920
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:1750
#define SHCNE_DELETE
Definition: shlobj.h:1748
#define SHCNE_MKDIR
Definition: shlobj.h:1749
#define SHCNE_CREATE
Definition: shlobj.h:1747
#define SHPPFW_IGNOREFILENAME
Definition: shlobj.h:306
#define SHPPFW_ASKDIRCREATE
Definition: shlobj.h:305
#define PROGDLG_AUTOTIME
Definition: shlobj.h:897
#define SHPPFW_DIRCREATE
Definition: shlobj.h:303
#define PROGDLG_NORMAL
Definition: shlobj.h:895
#define SHCNF_PATHW
Definition: shlobj.h:1781
#define IDD_YESTOALL_MSGBOX
Definition: shresdef.h:412
#define IDS_DELETESELECTED_TEXT
Definition: shresdef.h:130
#define IDA_SHELL_DELETE
Definition: shresdef.h:792
#define IDI_SHELL_FOLDER_MOVE2
Definition: shresdef.h:684
#define IDS_MOVEERROR
Definition: shresdef.h:256
#define IDI_SHELL_CONFIRM_DELETE
Definition: shresdef.h:611
#define IDS_MOVEERRORSUBFOLDER
Definition: shresdef.h:254
#define IDS_OVERWRITEFOLDER_TEXT
Definition: shresdef.h:135
#define IDS_FILEOOP_FROM
Definition: shresdef.h:240
#define IDS_FILEOOP_FROM_TO
Definition: shresdef.h:239
#define IDS_CREATEFOLDER_DENIED
Definition: shresdef.h:122
#define IDS_OVERWRITEFILE_CAPTION
Definition: shresdef.h:128
#define IDS_FILEOOP_MOVING
Definition: shresdef.h:237
#define IDS_COPYERRORSUBFOLDER
Definition: shresdef.h:255
#define IDC_YESTOALL_MESSAGE
Definition: shresdef.h:415
#define IDS_CREATEFOLDER_CAPTION
Definition: shresdef.h:123
#define IDS_CANTTRASH_TEXT
Definition: shresdef.h:134
#define IDS_MOVEERRORSAME
Definition: shresdef.h:252
#define IDS_TRASHITEM_TEXT
Definition: shresdef.h:132
#define IDS_DELETEITEM_CAPTION
Definition: shresdef.h:124
#define IDS_FILEOOP_DELETING
Definition: shresdef.h:238
#define IDS_TRASHMULTIPLE_TEXT
Definition: shresdef.h:133
#define IDC_YESTOALL_ICON
Definition: shresdef.h:414
#define IDS_TRASHFOLDER_TEXT
Definition: shresdef.h:131
#define IDS_FILEOOP_COPYING
Definition: shresdef.h:236
#define IDS_DELETEFOLDER_CAPTION
Definition: shresdef.h:125
#define IDS_DELETEITEM_TEXT
Definition: shresdef.h:126
#define IDS_COPYERROR
Definition: shresdef.h:257
#define IDC_YESTOALL
Definition: shresdef.h:413
#define IDI_SHELL_TRASH_FILE
Definition: shresdef.h:596
#define IDS_COPYERRORTITLE
Definition: shresdef.h:250
#define IDS_COPYERRORSAME
Definition: shresdef.h:253
#define IDS_FILEOOP_PREFLIGHT
Definition: shresdef.h:241
#define IDS_MOVEERRORTITLE
Definition: shresdef.h:249
#define IDS_DELETEMULTIPLE_TEXT
Definition: shresdef.h:127
#define IDA_SHELL_COPY
Definition: shresdef.h:788
#define IDS_MOVEERRORSAMEFOLDER
Definition: shresdef.h:251
#define _countof(array)
Definition: sndvol32.h:68
#define TRACE(s)
Definition: solgame.cpp:4
CardRegion * from
Definition: spigame.cpp:19
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
Definition: shlfileop.cpp:53
BOOL bFromWildcard
Definition: shlfileop.cpp:58
DWORD attributes
Definition: shlfileop.cpp:54
LPWSTR szFilename
Definition: shlfileop.cpp:56
BOOL bExists
Definition: shlfileop.cpp:60
LPWSTR szFullPath
Definition: shlfileop.cpp:57
BOOL bFromRelative
Definition: shlfileop.cpp:59
LPWSTR szDirectory
Definition: shlfileop.cpp:55
DWORD dwNumFiles
Definition: shlfileop.cpp:67
FILE_ENTRY * feFiles
Definition: shlfileop.cpp:65
BOOL bAnyFromWildcard
Definition: shlfileop.cpp:68
DWORD num_alloc
Definition: shlfileop.cpp:66
BOOL bAnyDirectories
Definition: shlfileop.cpp:69
BOOL bAnyDontExist
Definition: shlfileop.cpp:70
SHFILEOPSTRUCTW * req
Definition: shlfileop.cpp:40
DWORD dwYesToAllMask
Definition: shlfileop.cpp:41
IProgressDialog * progress
Definition: shlfileop.cpp:44
ULARGE_INTEGER totalSize
Definition: shlfileop.cpp:46
ULARGE_INTEGER completedSize
Definition: shlfileop.cpp:45
HINSTANCE hIconInstance
Definition: shlfileop.cpp:217
Definition: dsa.c:45
PVOID hNameMappings
Definition: shellapi.h:348
LPCSTR lpszProgressTitle
Definition: shellapi.h:349
FILEOP_FLAGS fFlags
Definition: shellapi.h:346
BOOL fAnyOperationsAborted
Definition: shellapi.h:347
PVOID hNameMappings
Definition: shellapi.h:358
LPCWSTR pFrom
Definition: shellapi.h:354
BOOL fAnyOperationsAborted
Definition: shellapi.h:357
FILEOP_FLAGS fFlags
Definition: shellapi.h:356
LPCWSTR lpszProgressTitle
Definition: shellapi.h:359
LPWSTR pszOldPath
Definition: shellapi.h:387
LPWSTR pszNewPath
Definition: shellapi.h:388
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
struct _ULARGE_INTEGER::@3944 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::@2274 u
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
#define ZeroMemory
Definition: winbase.h:1700
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:421
#define DRIVE_REMOTE
Definition: winbase.h:253
#define lstrcmp
Definition: winbase.h:3797
#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)
#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
HICON WINAPI LoadIconW(_In_opt_ HINSTANCE hInstance, _In_ LPCWSTR lpIconName)
Definition: cursoricon.c:2044
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