Added patch for support of shell32 file operation progress dialog.

This commit is contained in:
Sebastian Lackner 2015-02-27 02:12:30 +01:00
parent cc1368ba9e
commit e01d563654
9 changed files with 2030 additions and 7 deletions

View File

@ -38,7 +38,7 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [7]:**
**Bugfixes and features included in the next upcoming release [8]:**
* Add stub for gdiplus.GdipCreateEffect ([Wine Bug #32163](https://bugs.winehq.org/show_bug.cgi?id=32163))
* Add support for CopyFileEx progress callback ([Wine Bug #22692](https://bugs.winehq.org/show_bug.cgi?id=22692))
@ -47,6 +47,7 @@ Included bug fixes and improvements
* Fix race-condition when threads are killed during shutdown
* Implement SetFileInformationByHandle
* Process Hacker 2.x needs ntoskrnl.ProbeForRead ([Wine Bug #38103](https://bugs.winehq.org/show_bug.cgi?id=38103))
* Support for shell32 file operation progress dialog
**Bugs fixed in Wine Staging 1.7.37 [182]:**

1
debian/changelog vendored
View File

@ -13,6 +13,7 @@ wine-staging (1.7.38) UNRELEASED; urgency=low
* Added first set of patches for job objects (by Andrew Cook).
* Added patch for stub of gdiplus.GdipCreateEffect.
* Added patches for ntoskrnl.ProbeFor{Read,Write}.
* Added patch for support of shell32 file operation progress dialog.
* Removed patch to properly call DriverUnload when unloading device drivers (accepted upstream).
* Removed patch to allow Accept-Encoding for HTTP/1.0 in wininet (accepted upstream).
* Removed patch to declare pDirectInputCreateEx in a MSVC compatible way (accepted upstream).

View File

@ -167,6 +167,7 @@ patch_enable_all ()
enable_shell32_Default_Folder_ACLs="$1"
enable_shell32_Default_Path="$1"
enable_shell32_Icons="$1"
enable_shell32_Progress_Dialog="$1"
enable_shell32_Quoted_ShellExecute="$1"
enable_shell32_RunDLL_CallEntry16="$1"
enable_shell32_SHCreateSessionKey="$1"
@ -534,6 +535,9 @@ patch_enable ()
shell32-Icons)
enable_shell32_Icons="$2"
;;
shell32-Progress_Dialog)
enable_shell32_Progress_Dialog="$2"
;;
shell32-Quoted_ShellExecute)
enable_shell32_Quoted_ShellExecute="$2"
;;
@ -889,6 +893,20 @@ patch_apply ()
}
if test "$enable_shell32_SHFileOperation" -eq 1; then
if test "$enable_shell32_Progress_Dialog" -gt 1; then
abort "Patchset shell32-Progress_Dialog disabled, but shell32-SHFileOperation depends on that."
fi
enable_shell32_Progress_Dialog=1
fi
if test "$enable_shell32_Progress_Dialog" -eq 1; then
if test "$enable_kernel32_CopyFileEx" -gt 1; then
abort "Patchset kernel32-CopyFileEx disabled, but shell32-Progress_Dialog depends on that."
fi
enable_kernel32_CopyFileEx=1
fi
if test "$enable_server_ACL_Compat" -eq 1; then
if test "$enable_server_Inherited_ACLs" -gt 1; then
abort "Patchset server-Inherited_ACLs disabled, but server-ACL_Compat depends on that."
@ -3410,6 +3428,22 @@ if test "$enable_shell32_Icons" -eq 1; then
) >> "$patchlist"
fi
# Patchset shell32-Progress_Dialog
# |
# | Modified files:
# | * dlls/shell32/shell32.rc, dlls/shell32/shlfileop.c, dlls/shell32/shresdef.h
# |
if test "$enable_shell32_Progress_Dialog" -eq 1; then
patch_apply shell32-Progress_Dialog/0001-shell32-Correct-indentation-in-shfileop.c.patch
patch_apply shell32-Progress_Dialog/0002-shell32-Pass-FILE_INFORMATION-into-SHNotify-function.patch
patch_apply shell32-Progress_Dialog/0003-shell32-Implement-file-operation-progress-dialog.patch
(
echo '+ { "Michael Müller", "shell32: Correct indentation in shfileop.c.", 1 },';
echo '+ { "Michael Müller", "shell32: Pass FILE_INFORMATION into SHNotify* functions.", 1 },';
echo '+ { "Michael Müller", "shell32: Implement file operation progress dialog.", 1 },';
) >> "$patchlist"
fi
# Patchset shell32-Quoted_ShellExecute
# |
# | This patchset fixes the following Wine bugs:

View File

@ -0,0 +1,527 @@
From 8442c70f08cd95cf592ec4232489ea93c5d0a038 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 26 Feb 2015 23:21:26 +0100
Subject: shell32: Pass FILE_INFORMATION into SHNotify* functions.
Preparation of the progressbar work. Based on a patch by Huw Campbell.
---
dlls/shell32/shlfileop.c | 222 +++++++++++++++++++++++------------------------
1 file changed, 111 insertions(+), 111 deletions(-)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index ee40e39..ed8ff38 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -59,16 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
static const WCHAR wWildcardFile[] = {'*',0};
static const WCHAR wWildcardChars[] = {'*','?',0};
-static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec);
-static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec);
-static DWORD SHNotifyRemoveDirectoryA(LPCSTR path);
-static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path);
-static DWORD SHNotifyDeleteFileA(LPCSTR path);
-static DWORD SHNotifyDeleteFileW(LPCWSTR path);
-static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest);
-static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists);
-static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly);
-
typedef struct
{
SHFILEOPSTRUCTW *req;
@@ -77,6 +67,42 @@ typedef struct
BOOL bCancelled;
} FILE_OPERATION;
+typedef struct
+{
+ DWORD attributes;
+ LPWSTR szDirectory;
+ LPWSTR szFilename;
+ LPWSTR szFullPath;
+ BOOL bFromWildcard;
+ BOOL bFromRelative;
+ BOOL bExists;
+} FILE_ENTRY;
+
+typedef struct
+{
+ FILE_ENTRY *feFiles;
+ DWORD num_alloc;
+ DWORD dwNumFiles;
+ BOOL bAnyFromWildcard;
+ BOOL bAnyDirectories;
+ BOOL bAnyDontExist;
+} FILE_LIST;
+
+#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026
+
+static DWORD SHNotifyCreateDirectoryA(LPCSTR path, LPSECURITY_ATTRIBUTES sec);
+static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec);
+static DWORD SHNotifyRemoveDirectoryA(LPCSTR path);
+static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path);
+static DWORD SHNotifyDeleteFileA(FILE_OPERATION *op, LPCSTR path);
+static DWORD SHNotifyDeleteFileW(FILE_OPERATION *op, LPCWSTR path);
+static DWORD SHNotifyMoveFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest);
+static DWORD SHNotifyCopyFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists);
+static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly);
+
+static DWORD copy_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, FILE_LIST *flTo);
+static DWORD move_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, const FILE_LIST *flTo);
+
/* Confirm dialogs with an optional "Yes To All" as used in file operations confirmations
*/
static const WCHAR CONFIRM_MSG_PROP[] = {'W','I','N','E','_','C','O','N','F','I','R','M',0};
@@ -347,7 +373,7 @@ HRESULT WINAPI SHIsFileAvailableOffline(LPCWSTR path, LPDWORD status)
* Asks for confirmation when bShowUI is true and deletes the directory and
* all its subdirectories and files if necessary.
*/
-static DWORD SHELL_DeleteDirectoryW(HWND hwnd, LPCWSTR pszDir, BOOL bShowUI)
+static DWORD SHELL_DeleteDirectoryW(FILE_OPERATION *op, LPCWSTR pszDir, BOOL bShowUI)
{
DWORD ret = 0;
HANDLE hFind;
@@ -357,16 +383,18 @@ static DWORD SHELL_DeleteDirectoryW(HWND hwnd, LPCWSTR pszDir, BOOL bShowUI)
PathCombineW(szTemp, pszDir, wWildcardFile);
hFind = FindFirstFileW(szTemp, &wfd);
- if (hFind != INVALID_HANDLE_VALUE) {
- if (!bShowUI || SHELL_ConfirmDialogW(hwnd, ASK_DELETE_FOLDER, pszDir, NULL)) {
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ if (!bShowUI || SHELL_ConfirmDialogW(op->req->hwnd, ASK_DELETE_FOLDER, pszDir, NULL))
+ {
do {
if (IsDotDir(wfd.cFileName))
continue;
PathCombineW(szTemp, pszDir, wfd.cFileName);
if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
- ret = SHELL_DeleteDirectoryW(hwnd, szTemp, FALSE);
+ ret = SHELL_DeleteDirectoryW(op, szTemp, FALSE);
else
- ret = SHNotifyDeleteFileW(szTemp);
+ ret = SHNotifyDeleteFileW(op, szTemp);
} while (!ret && FindNextFileW(hFind, &wfd));
}
FindClose(hFind);
@@ -497,22 +525,9 @@ BOOL WINAPI Win32RemoveDirectoryAW(LPCVOID path)
return (SHNotifyRemoveDirectoryA(path) == ERROR_SUCCESS);
}
-/************************************************************************
- * Win32DeleteFile [SHELL32.164]
- *
- * Deletes a file. Also triggers a change notify if one exists.
- *
- * PARAMS
- * path [I] path to file to delete
- *
- * RETURNS
- * TRUE if successful, FALSE otherwise
- *
- * NOTES
- * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
- * This is Unicode on NT/2000
- */
-static DWORD SHNotifyDeleteFileA(LPCSTR path)
+/***********************************************************************/
+
+static DWORD SHNotifyDeleteFileA(FILE_OPERATION *op, LPCSTR path)
{
LPWSTR wPath;
DWORD retCode;
@@ -522,7 +537,7 @@ static DWORD SHNotifyDeleteFileA(LPCSTR path)
retCode = SHELL32_AnsiToUnicodeBuf(path, &wPath, 0);
if (!retCode)
{
- retCode = SHNotifyDeleteFileW(wPath);
+ retCode = SHNotifyDeleteFileW(op, wPath);
SHELL32_FreeUnicodeBuf(wPath);
}
return retCode;
@@ -530,12 +545,14 @@ static DWORD SHNotifyDeleteFileA(LPCSTR path)
/***********************************************************************/
-static DWORD SHNotifyDeleteFileW(LPCWSTR path)
+static DWORD SHNotifyDeleteFileW(FILE_OPERATION *op, LPCWSTR path)
{
BOOL ret;
TRACE("(%s)\n", debugstr_w(path));
+ /* FIXME: Implement progress dialog - op can also be zero! */
+
ret = DeleteFileW(path);
if (!ret)
{
@@ -558,8 +575,8 @@ static DWORD SHNotifyDeleteFileW(LPCWSTR path)
DWORD WINAPI Win32DeleteFileAW(LPCVOID path)
{
if (SHELL_OsIsUnicode())
- return (SHNotifyDeleteFileW(path) == ERROR_SUCCESS);
- return (SHNotifyDeleteFileA(path) == ERROR_SUCCESS);
+ return (SHNotifyDeleteFileW(NULL, path) == ERROR_SUCCESS);
+ return (SHNotifyDeleteFileA(NULL, path) == ERROR_SUCCESS);
}
/************************************************************************
@@ -568,18 +585,21 @@ DWORD WINAPI Win32DeleteFileAW(LPCVOID path)
* Moves a file. Also triggers a change notify if one exists.
*
* PARAMS
+ * op [I] file operation context
* src [I] path to source file to move
* dest [I] path to target file to move to
*
* RETURNS
* ERORR_SUCCESS if successful
*/
-static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest)
+static DWORD SHNotifyMoveFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest)
{
BOOL ret;
TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest));
+ /* FIXME: Implement progress dialog */
+
ret = MoveFileExW(src, dest, MOVEFILE_REPLACE_EXISTING);
/* MOVEFILE_REPLACE_EXISTING fails with dirs, so try MoveFile */
@@ -614,6 +634,7 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest)
* Copies a file. Also triggers a change notify if one exists.
*
* PARAMS
+ * op [I] file operation context
* src [I] path to source file to move
* dest [I] path to target file to move to
* bFailIfExists [I] if TRUE, the target file will not be overwritten if
@@ -622,13 +643,15 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest)
* RETURNS
* ERROR_SUCCESS if successful
*/
-static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists)
+static DWORD SHNotifyCopyFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists)
{
BOOL ret;
DWORD attribs;
TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : "");
+ /* FIXME: Update progress dialog */
+
/* Destination file may already exist with read only attribute */
attribs = GetFileAttributesW(dest);
if (IsAttrib(attribs, FILE_ATTRIBUTE_READONLY))
@@ -904,30 +927,6 @@ int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp)
return retCode;
}
-#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026
-
-typedef struct
-{
- DWORD attributes;
- LPWSTR szDirectory;
- LPWSTR szFilename;
- LPWSTR szFullPath;
- BOOL bFromWildcard;
- BOOL bFromRelative;
- BOOL bExists;
-} FILE_ENTRY;
-
-typedef struct
-{
- FILE_ENTRY *feFiles;
- DWORD num_alloc;
- DWORD dwNumFiles;
- BOOL bAnyFromWildcard;
- BOOL bAnyDirectories;
- BOOL bAnyDontExist;
-} FILE_LIST;
-
-
static inline void grow_list(FILE_LIST *list)
{
FILE_ENTRY *new = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list->feFiles,
@@ -1091,7 +1090,7 @@ static void destroy_file_list(FILE_LIST *flList)
static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
{
WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
- SHFILEOPSTRUCTW fileOp;
+ FILE_LIST flFromNew, flToNew;
static const WCHAR wildCardFiles[] = {'*','.','*',0};
@@ -1119,17 +1118,16 @@ static void copy_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWST
PathCombineW(szFrom, feFrom->szFullPath, wildCardFiles);
szFrom[lstrlenW(szFrom) + 1] = '\0';
- fileOp = *op->req;
- fileOp.pFrom = szFrom;
- fileOp.pTo = szTo;
- fileOp.fFlags &= ~FOF_MULTIDESTFILES; /* we know we're copying to one dir */
+ ZeroMemory(&flFromNew, sizeof(FILE_LIST));
+ ZeroMemory(&flToNew, sizeof(FILE_LIST));
+ parse_file_list(&flFromNew, szFrom);
+ parse_file_list(&flToNew, szTo);
- /* Don't ask the user about overwriting files when he accepted to overwrite the
- folder. FIXME: this is not exactly what Windows does - e.g. there would be
- an additional confirmation for a nested folder */
- fileOp.fFlags |= FOF_NOCONFIRMATION;
+ /* we know we're copying to one dir */
+ copy_files(op, FALSE, &flFromNew, &flToNew);
- SHFileOperationW(&fileOp);
+ destroy_file_list(&flFromNew);
+ destroy_file_list(&flToNew);
}
static BOOL copy_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCHAR *szTo)
@@ -1140,7 +1138,7 @@ static BOOL copy_file_to_file(FILE_OPERATION *op, const WCHAR *szFrom, const WCH
return FALSE;
}
- return SHNotifyCopyFileW(szFrom, szTo, FALSE) == 0;
+ return SHNotifyCopyFileW(op, szFrom, szTo, FALSE) == 0;
}
/* copy a file or directory to another directory */
@@ -1180,7 +1178,7 @@ static void create_dest_dirs(LPCWSTR szDestDir)
}
/* the FO_COPY operation */
-static DWORD copy_files(FILE_OPERATION *op, const FILE_LIST *flFrom, FILE_LIST *flTo)
+static DWORD copy_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, FILE_LIST *flTo)
{
DWORD i;
const FILE_ENTRY *entryToCopy;
@@ -1203,7 +1201,7 @@ static DWORD copy_files(FILE_OPERATION *op, const FILE_LIST *flFrom, FILE_LIST *
fileDest = &flTo->feFiles[0];
}
- if (op->req->fFlags & FOF_MULTIDESTFILES)
+ if (multidest)
{
if (flFrom->bAnyFromWildcard)
return ERROR_CANCELLED;
@@ -1255,8 +1253,7 @@ static DWORD copy_files(FILE_OPERATION *op, const FILE_LIST *flFrom, FILE_LIST *
{
entryToCopy = &flFrom->feFiles[i];
- if ((op->req->fFlags & FOF_MULTIDESTFILES) &&
- flTo->dwNumFiles > 1)
+ if (multidest && flTo->dwNumFiles > 1)
{
fileDest = &flTo->feFiles[i];
}
@@ -1328,7 +1325,7 @@ static BOOL confirm_delete_list(HWND hWnd, DWORD fFlags, BOOL fTrash, const FILE
}
/* the FO_DELETE operation */
-static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
+static DWORD delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
{
const FILE_ENTRY *fileEntry;
DWORD i, ret;
@@ -1338,13 +1335,13 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
return ERROR_SUCCESS;
/* Windows also checks only the first item */
- bTrash = (lpFileOp->fFlags & FOF_ALLOWUNDO)
+ bTrash = (op->req->fFlags & FOF_ALLOWUNDO)
&& TRASH_CanTrashFile(flFrom->feFiles[0].szFullPath);
- if (!(lpFileOp->fFlags & FOF_NOCONFIRMATION) || (!bTrash && lpFileOp->fFlags & FOF_WANTNUKEWARNING))
- if (!confirm_delete_list(lpFileOp->hwnd, lpFileOp->fFlags, bTrash, flFrom))
+ if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (!bTrash && op->req->fFlags & FOF_WANTNUKEWARNING))
+ if (!confirm_delete_list(op->req->hwnd, op->req->fFlags, bTrash, flFrom))
{
- lpFileOp->fAnyOperationsAborted = TRUE;
+ op->req->fAnyOperationsAborted = TRUE;
return 0;
}
@@ -1353,7 +1350,7 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
fileEntry = &flFrom->feFiles[i];
if (!IsAttribFile(fileEntry->attributes) &&
- (lpFileOp->fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
+ (op->req->fFlags & FOF_FILESONLY && fileEntry->bFromWildcard))
continue;
if (bTrash)
@@ -1363,14 +1360,14 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
continue;
/* Note: Windows silently deletes the file in such a situation, we show a dialog */
- if (!(lpFileOp->fFlags & FOF_NOCONFIRMATION) || (lpFileOp->fFlags & FOF_WANTNUKEWARNING))
- bDelete = SHELL_ConfirmDialogW(lpFileOp->hwnd, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL);
+ if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (op->req->fFlags & FOF_WANTNUKEWARNING))
+ bDelete = SHELL_ConfirmDialogW(op->req->hwnd, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL);
else
bDelete = TRUE;
if (!bDelete)
{
- lpFileOp->fAnyOperationsAborted = TRUE;
+ op->req->fAnyOperationsAborted = TRUE;
break;
}
}
@@ -1380,7 +1377,7 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
ret = DeleteFileW(fileEntry->szFullPath) ?
ERROR_SUCCESS : GetLastError();
else
- ret = SHELL_DeleteDirectoryW(lpFileOp->hwnd, fileEntry->szFullPath, FALSE);
+ ret = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
if (ret)
return ret;
@@ -1389,10 +1386,10 @@ static DWORD delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom)
return ERROR_SUCCESS;
}
-static void move_dir_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
+static void move_dir_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, LPCWSTR szDestPath)
{
WCHAR szFrom[MAX_PATH], szTo[MAX_PATH];
- SHFILEOPSTRUCTW fileOp;
+ FILE_LIST flFromNew, flToNew;
static const WCHAR wildCardFiles[] = {'*','.','*',0};
@@ -1407,28 +1404,33 @@ static void move_dir_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom
lstrcpyW(szTo, szDestPath);
szTo[lstrlenW(szDestPath) + 1] = '\0';
- fileOp = *lpFileOp;
- fileOp.pFrom = szFrom;
- fileOp.pTo = szTo;
+ ZeroMemory(&flFromNew, sizeof(FILE_LIST));
+ ZeroMemory(&flToNew, sizeof(FILE_LIST));
+
+ parse_file_list(&flFromNew, szFrom);
+ parse_file_list(&flToNew, szTo);
- SHFileOperationW(&fileOp);
+ move_files(op, FALSE, &flFromNew, &flToNew);
+
+ destroy_file_list(&flFromNew);
+ destroy_file_list(&flToNew);
}
/* moves a file or directory to another directory */
-static void move_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
+static void move_to_dir(FILE_OPERATION *op, const FILE_ENTRY *feFrom, const FILE_ENTRY *feTo)
{
WCHAR szDestPath[MAX_PATH];
PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename);
if (IsAttribFile(feFrom->attributes))
- SHNotifyMoveFileW(feFrom->szFullPath, szDestPath);
- else if (!(lpFileOp->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
- move_dir_to_dir(lpFileOp, feFrom, szDestPath);
+ SHNotifyMoveFileW(op, feFrom->szFullPath, szDestPath);
+ else if (!(op->req->fFlags & FOF_FILESONLY && feFrom->bFromWildcard))
+ move_dir_to_dir(op, feFrom, szDestPath);
}
/* the FO_MOVE operation */
-static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const FILE_LIST *flTo)
+static DWORD move_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, const FILE_LIST *flTo)
{
DWORD i;
INT mismatched = 0;
@@ -1441,14 +1443,12 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
if (!flTo->dwNumFiles)
return ERROR_FILE_NOT_FOUND;
- if (!(lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
- flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
+ if (!multidest && flTo->dwNumFiles > 1 && flFrom->dwNumFiles > 1)
{
return ERROR_CANCELLED;
}
- if (!(lpFileOp->fFlags & FOF_MULTIDESTFILES) &&
- !flFrom->bAnyDirectories &&
+ if (!multidest && !flFrom->bAnyDirectories &&
flFrom->dwNumFiles > flTo->dwNumFiles)
{
return ERROR_CANCELLED;
@@ -1457,7 +1457,7 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
if (!PathFileExistsW(flTo->feFiles[0].szDirectory))
return ERROR_CANCELLED;
- if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
+ if (multidest)
mismatched = flFrom->dwNumFiles - flTo->dwNumFiles;
fileDest = &flTo->feFiles[0];
@@ -1468,7 +1468,7 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
if (!PathFileExistsW(fileDest->szDirectory))
return ERROR_CANCELLED;
- if (lpFileOp->fFlags & FOF_MULTIDESTFILES)
+ if (multidest)
{
if (i >= flTo->dwNumFiles)
break;
@@ -1482,9 +1482,9 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
}
if (fileDest->bExists && IsAttribDir(fileDest->attributes))
- move_to_dir(lpFileOp, entryToMove, fileDest);
+ move_to_dir(op, entryToMove, fileDest);
else
- SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath);
+ SHNotifyMoveFileW(op, entryToMove->szFullPath, fileDest->szFullPath);
}
if (mismatched > 0)
@@ -1499,7 +1499,7 @@ static DWORD move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, con
}
/* the FO_RENAME files */
-static DWORD rename_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, const FILE_LIST *flTo)
+static DWORD rename_files(FILE_OPERATION *op, const FILE_LIST *flFrom, const FILE_LIST *flTo)
{
const FILE_ENTRY *feFrom;
const FILE_ENTRY *feTo;
@@ -1521,7 +1521,7 @@ static DWORD rename_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, c
if (feTo->bExists)
return ERROR_ALREADY_EXISTS;
- return SHNotifyMoveFileW(feFrom->szFullPath, feTo->szFullPath);
+ return SHNotifyMoveFileW(op, feFrom->szFullPath, feTo->szFullPath);
}
/* alert the user if an unsupported flag is used */
@@ -1568,16 +1568,16 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
switch (lpFileOp->wFunc)
{
case FO_COPY:
- ret = copy_files(&op, &flFrom, &flTo);
+ ret = copy_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
break;
case FO_DELETE:
- ret = delete_files(lpFileOp, &flFrom);
+ ret = delete_files(&op, &flFrom);
break;
case FO_MOVE:
- ret = move_files(lpFileOp, &flFrom, &flTo);
+ ret = move_files(&op, op.req->fFlags & FOF_MULTIDESTFILES, &flFrom, &flTo);
break;
case FO_RENAME:
- ret = rename_files(lpFileOp, &flFrom, &flTo);
+ ret = rename_files(&op, &flFrom, &flTo);
break;
default:
ret = ERROR_INVALID_PARAMETER;
--
2.3.0

View File

@ -0,0 +1,453 @@
From a6f9101ab518d9cf5a9ab34533ba1d684ee61d8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 27 Feb 2015 01:04:33 +0100
Subject: shell32: Implement file operation progress dialog.
Based on a patch by Huw Campbell.
---
dlls/shell32/shell32.rc | 7 ++
dlls/shell32/shlfileop.c | 277 +++++++++++++++++++++++++++++++++++++++++++++--
dlls/shell32/shresdef.h | 8 ++
3 files changed, 285 insertions(+), 7 deletions(-)
diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc
index 37acbe7..dd054fb 100644
--- a/dlls/shell32/shell32.rc
+++ b/dlls/shell32/shell32.rc
@@ -184,6 +184,13 @@ If the files in the destination folder have the same names as files in the\n\
selected folder they will be replaced. Do you still want to move or copy\n\
the folder?"
+ IDS_FILEOP_COPYING "Copying"
+ IDS_FILEOP_MOVING "Moving"
+ IDS_FILEOP_DELETING "Deleting"
+ IDS_FILEOP_FROM_TO "From %1 to %2"
+ IDS_FILEOP_FROM "From %1"
+ IDS_FILEOP_PREFLIGHT "Preflight"
+
/* message box strings */
IDS_RESTART_TITLE "Restart"
IDS_RESTART_PROMPT "Do you want to simulate a Windows reboot?"
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index ed8ff38..cef2246 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -65,6 +65,10 @@ typedef struct
DWORD dwYesToAllMask;
BOOL bManyItems;
BOOL bCancelled;
+ IProgressDialog *progress;
+ ULARGE_INTEGER completedSize;
+ ULARGE_INTEGER totalSize;
+ WCHAR szBuilderString[64];
} FILE_OPERATION;
typedef struct
@@ -103,6 +107,12 @@ static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly);
static DWORD copy_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, FILE_LIST *flTo);
static DWORD move_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flFrom, const FILE_LIST *flTo);
+static void progressbar_calc_totalsize(FILE_OPERATION *op, const FILE_LIST *from);
+static void progressbar_update_title(FILE_OPERATION *op);
+static void progressbar_update_files(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dst);
+static DWORD CALLBACK progressbar_copy_routine(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred, LARGE_INTEGER stream_size,
+ LARGE_INTEGER stream_transferred, DWORD stream_number, DWORD reason, HANDLE src_file, HANDLE dst_file, LPVOID user);
+
/* Confirm dialogs with an optional "Yes To All" as used in file operations confirmations
*/
static const WCHAR CONFIRM_MSG_PROP[] = {'W','I','N','E','_','C','O','N','F','I','R','M',0};
@@ -395,6 +405,13 @@ static DWORD SHELL_DeleteDirectoryW(FILE_OPERATION *op, LPCWSTR pszDir, BOOL bSh
ret = SHELL_DeleteDirectoryW(op, szTemp, FALSE);
else
ret = SHNotifyDeleteFileW(op, szTemp);
+
+ /* Check if dialog was cancelled in the meantime */
+ if (op->progress != NULL)
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
+ if (op->bCancelled)
+ break;
+
} while (!ret && FindNextFileW(hFind, &wfd));
}
FindClose(hFind);
@@ -548,10 +565,22 @@ static DWORD SHNotifyDeleteFileA(FILE_OPERATION *op, LPCSTR path)
static DWORD SHNotifyDeleteFileW(FILE_OPERATION *op, LPCWSTR path)
{
BOOL ret;
+ LARGE_INTEGER filesize;
+ filesize.QuadPart = 0;
TRACE("(%s)\n", debugstr_w(path));
- /* FIXME: Implement progress dialog - op can also be zero! */
+ /* Warning: can also be called with empty op */
+ if (op)
+ {
+ WIN32_FILE_ATTRIBUTE_DATA info;
+ progressbar_update_files(op, path, NULL);
+ if (GetFileAttributesExW(path, GetFileExInfoStandard, &info))
+ {
+ filesize.u.HighPart = info.nFileSizeHigh;
+ filesize.u.LowPart = info.nFileSizeLow;
+ }
+ }
ret = DeleteFileW(path);
if (!ret)
@@ -564,6 +593,14 @@ static DWORD SHNotifyDeleteFileW(FILE_OPERATION *op, LPCWSTR path)
}
if (ret)
{
+ if (op)
+ {
+ /* There is no progress while deleting a file,
+ * simply report full file size when we are done. */
+ progressbar_copy_routine(filesize, filesize, filesize, filesize, 0,
+ CALLBACK_STREAM_SWITCH, NULL, NULL, op);
+ }
+
SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, path, NULL);
return ERROR_SUCCESS;
}
@@ -598,9 +635,10 @@ static DWORD SHNotifyMoveFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest)
TRACE("(%s %s)\n", debugstr_w(src), debugstr_w(dest));
- /* FIXME: Implement progress dialog */
+ progressbar_update_files(op, src, dest);
- ret = MoveFileExW(src, dest, MOVEFILE_REPLACE_EXISTING);
+ ret = MoveFileWithProgressW(src, dest, progressbar_copy_routine,
+ op, MOVEFILE_REPLACE_EXISTING);
/* MOVEFILE_REPLACE_EXISTING fails with dirs, so try MoveFile */
if (!ret)
@@ -650,14 +688,15 @@ static DWORD SHNotifyCopyFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BO
TRACE("(%s %s %s)\n", debugstr_w(src), debugstr_w(dest), bFailIfExists ? "failIfExists" : "");
- /* FIXME: Update progress dialog */
+ progressbar_update_files(op, src, dest);
/* Destination file may already exist with read only attribute */
attribs = GetFileAttributesW(dest);
if (IsAttrib(attribs, FILE_ATTRIBUTE_READONLY))
SetFileAttributesW(dest, attribs & ~FILE_ATTRIBUTE_READONLY);
- ret = CopyFileW(src, dest, bFailIfExists);
+ ret = CopyFileExW(src, dest, progressbar_copy_routine, op,
+ &op->bCancelled, bFailIfExists);
if (ret)
{
SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL);
@@ -1293,6 +1332,8 @@ static DWORD copy_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flF
}
/* Vista return code. XP would return e.g. ERROR_FILE_NOT_FOUND, ERROR_ALREADY_EXISTS */
+ if (op->progress != NULL)
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
if (op->bCancelled)
return ERROR_CANCELLED;
}
@@ -1374,13 +1415,17 @@ static DWORD delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
/* delete the file or directory */
if (IsAttribFile(fileEntry->attributes))
- ret = DeleteFileW(fileEntry->szFullPath) ?
- ERROR_SUCCESS : GetLastError();
+ ret = SHNotifyDeleteFileW(op, fileEntry->szFullPath);
else
ret = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
if (ret)
return ret;
+
+ if (op->progress != NULL)
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
+ if (op->bCancelled)
+ return ERROR_CANCELLED;
}
return ERROR_SUCCESS;
@@ -1485,6 +1530,11 @@ static DWORD move_files(FILE_OPERATION *op, BOOL multidest, const FILE_LIST *flF
move_to_dir(op, entryToMove, fileDest);
else
SHNotifyMoveFileW(op, entryToMove->szFullPath, fileDest->szFullPath);
+
+ if (op->progress != NULL)
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
+ if (op->bCancelled)
+ return ERROR_CANCELLED;
}
if (mismatched > 0)
@@ -1544,6 +1594,7 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
{
FILE_OPERATION op;
FILE_LIST flFrom, flTo;
+ HRESULT co_ret = E_FAIL;
int ret = 0;
if (!lpFileOp)
@@ -1562,9 +1613,31 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
ZeroMemory(&op, sizeof(op));
op.req = lpFileOp;
+ op.totalSize.QuadPart = 0;
+ op.completedSize.QuadPart = 0;
op.bManyItems = (flFrom.dwNumFiles > 1);
lpFileOp->fAnyOperationsAborted = FALSE;
+ if (lpFileOp->wFunc != FO_RENAME && !(lpFileOp->fFlags & FOF_SILENT))
+ {
+ co_ret = CoInitialize(NULL);
+ ret = CoCreateInstance(&CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IProgressDialog, (void**)&op.progress);
+ if (SUCCEEDED(ret))
+ {
+ IProgressDialog_StartProgressDialog(op.progress, op.req->hwnd, NULL,
+ PROGDLG_NORMAL | PROGDLG_AUTOTIME, NULL);
+
+ progressbar_update_title(&op);
+ progressbar_calc_totalsize(&op, &flFrom);
+ }
+ else
+ {
+ FIXME("Failed to create progress dialog\n");
+ op.progress = NULL;
+ }
+ }
+
switch (lpFileOp->wFunc)
{
case FO_COPY:
@@ -1584,6 +1657,12 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
break;
}
+ if (op.progress)
+ {
+ IProgressDialog_StopProgressDialog(op.progress);
+ IProgressDialog_Release(op.progress);
+ }
+
destroy_file_list(&flFrom);
if (lpFileOp->wFunc != FO_DELETE)
@@ -1592,6 +1671,9 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
if (ret == ERROR_CANCELLED)
lpFileOp->fAnyOperationsAborted = TRUE;
+ if (SUCCEEDED(co_ret))
+ CoUninitialize();
+
return ret;
}
@@ -1822,3 +1904,184 @@ HRESULT WINAPI SHPathPrepareForWriteW(HWND hwnd, IUnknown *modless, LPCWSTR path
else
return HRESULT_FROM_WIN32(ERROR_DIRECTORY);
}
+
+static BOOL progressbar_calc_size(FILE_OPERATION *op, LPWSTR buf, BOOL is_folder, DWORD *ticks)
+{
+ WIN32_FIND_DATAW wfd;
+ HANDLE find;
+ UINT i = strlenW(buf);
+ WCHAR *file = buf + i;
+ size_t size = MAX_PATH - i;
+
+ if (size < 3)
+ return FALSE;
+
+ if (is_folder)
+ {
+ *file++ = '\\';
+ size--;
+
+ file[0] = '*';
+ file[1] = 0;
+ }
+ else
+ {
+ file[0] = 0;
+ }
+
+ find = FindFirstFileW(buf, &wfd);
+ if (find == INVALID_HANDLE_VALUE)
+ {
+ WARN("FindFirstFileW %s failed\n", debugstr_w(buf));
+ return FALSE;
+ }
+
+ do
+ {
+ if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (wfd.cFileName[0] == '.')
+ {
+ if (wfd.cFileName[1] == 0) continue;
+ if (wfd.cFileName[1] == '.' && wfd.cFileName[2] == 0) continue;
+ }
+
+ if (!lstrcpynW(file, wfd.cFileName, size)) continue;
+ progressbar_calc_size(op, buf, TRUE, ticks);
+ }
+ else
+ {
+ LARGE_INTEGER filesize;
+ filesize.u.LowPart = wfd.nFileSizeLow;
+ filesize.u.HighPart = wfd.nFileSizeHigh;
+ op->totalSize.QuadPart += filesize.QuadPart;
+ }
+
+ if (GetTickCount() - *ticks > (DWORD) 500)
+ {
+ if (op->progress != NULL)
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
+ if (op->bCancelled)
+ break;
+ *ticks = GetTickCount();
+ }
+
+ }
+ while (FindNextFileW(find, &wfd));
+
+ FindClose(find);
+ return TRUE;
+}
+
+static void progressbar_calc_totalsize(FILE_OPERATION *op, const FILE_LIST *from)
+{
+ WCHAR filename[MAX_PATH];
+ DWORD ticks = GetTickCount();
+ UINT i;
+
+ op->totalSize.QuadPart = 0;
+
+ for (i = 0; i < from->dwNumFiles && !op->bCancelled; i++)
+ {
+ if (!lstrcpynW(filename, from->feFiles[i].szFullPath, sizeof(filename)/sizeof(filename[0])))
+ continue;
+ progressbar_calc_size(op, filename, IsAttribDir(from->feFiles[i].attributes), &ticks);
+ }
+}
+
+static void progressbar_update_title(FILE_OPERATION *op)
+{
+ WCHAR buf[64];
+ UINT title_id, builder_id;
+
+ if (op->progress == NULL)
+ return;
+
+ switch (op->req->wFunc)
+ {
+ case FO_COPY:
+ title_id = IDS_FILEOP_COPYING;
+ builder_id = IDS_FILEOP_FROM_TO;
+ break;
+
+ case FO_DELETE:
+ title_id = IDS_FILEOP_DELETING;
+ builder_id = IDS_FILEOP_FROM;
+ break;
+
+ case FO_MOVE:
+ title_id = IDS_FILEOP_MOVING;
+ builder_id = IDS_FILEOP_FROM_TO;
+ break;
+
+ default:
+ return;
+ }
+
+ LoadStringW(shell32_hInstance, title_id, buf, sizeof(buf)/sizeof(WCHAR));
+ IProgressDialog_SetTitle(op->progress, buf);
+
+ LoadStringW(shell32_hInstance, builder_id, op->szBuilderString,
+ sizeof(op->szBuilderString)/sizeof(WCHAR));
+
+ LoadStringW(shell32_hInstance, IDS_FILEOP_PREFLIGHT, buf, sizeof(buf)/sizeof(WCHAR));
+ IProgressDialog_SetLine(op->progress, 1, buf, FALSE, NULL);
+}
+
+static void progressbar_update_files(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dst)
+{
+ LPWSTR src_file, dst_file;
+ WCHAR src_dir[64], dst_dir[64], final[260];
+ DWORD_PTR args[2] = {0, 0};
+
+ if (!op->progress || !src || (op->req->wFunc == FO_MOVE && !dst))
+ return;
+
+ if (op->req->wFunc != FO_COPY &&
+ op->req->wFunc != FO_MOVE &&
+ op->req->wFunc != FO_DELETE)
+ {
+ return;
+ }
+
+ src_file = PathFindFileNameW(src);
+ lstrcpynW(src_dir, src, min(sizeof(src_dir) / sizeof(WCHAR) - 1, src_file - src));
+ args[0] = (DWORD_PTR)&src_dir;
+
+ if (op->req->wFunc == FO_MOVE ||
+ op->req->wFunc == FO_COPY)
+ {
+ if (PathIsDirectoryW(dst))
+ args[1] = (DWORD_PTR)&dst;
+ else
+ {
+ dst_file = PathFindFileNameW(dst);
+ lstrcpynW(dst_dir, dst, min(sizeof(dst_dir) / sizeof(WCHAR) - 1, dst_file - dst));
+ args[1] = (DWORD_PTR)&dst_dir;
+ }
+ }
+
+ FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, op->szBuilderString,
+ 0, 0, final, sizeof(final)/sizeof(final[0]), (__ms_va_list *)&args);
+
+ IProgressDialog_SetLine(op->progress, 1, src_file, FALSE, NULL);
+ IProgressDialog_SetLine(op->progress, 2, final, FALSE, NULL);
+}
+
+static DWORD CALLBACK progressbar_copy_routine(LARGE_INTEGER total_size, LARGE_INTEGER total_transferred, LARGE_INTEGER stream_size,
+ LARGE_INTEGER stream_transferred, DWORD stream_number, DWORD reason, HANDLE src_file, HANDLE dst_file, LPVOID user)
+{
+ FILE_OPERATION *op = (FILE_OPERATION *)user;
+
+ if (!op->progress)
+ return PROGRESS_CONTINUE;
+
+ if (reason == CALLBACK_STREAM_SWITCH)
+ op->completedSize.QuadPart += total_size.QuadPart;
+
+ IProgressDialog_SetProgress64(op->progress, op->completedSize.QuadPart - total_size.QuadPart +
+ total_transferred.QuadPart, op->totalSize.QuadPart);
+
+ op->bCancelled |= IProgressDialog_HasUserCancelled(op->progress);
+ return op->bCancelled ? PROGRESS_CANCEL : PROGRESS_CONTINUE;
+}
diff --git a/dlls/shell32/shresdef.h b/dlls/shell32/shresdef.h
index 183a75e..8ee525a 100644
--- a/dlls/shell32/shresdef.h
+++ b/dlls/shell32/shresdef.h
@@ -149,6 +149,14 @@
#define IDM_RECYCLEBIN_RESTORE 301
#define IDM_RECYCLEBIN_ERASE 302
+/* Strings for file operations */
+#define IDS_FILEOP_COPYING 333
+#define IDS_FILEOP_MOVING 334
+#define IDS_FILEOP_DELETING 335
+#define IDS_FILEOP_FROM_TO 336
+#define IDS_FILEOP_FROM 337
+#define IDS_FILEOP_PREFLIGHT 338
+
/* Note: this string is referenced from the registry*/
#define IDS_RECYCLEBIN_FOLDER_NAME 8964
--
2.3.0

View File

@ -0,0 +1,2 @@
Fixes: Support for shell32 file operation progress dialog
Depends: kernel32-CopyFileEx

View File

@ -1,4 +1,4 @@
From 3bd2667c70cd1b9ef472d353ffe16220823cdc35 Mon Sep 17 00:00:00 2001
From 838dbfc163ed83706e88e309201d84197e6ebee1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 31 Jul 2014 04:52:01 +0200
Subject: shell32: Choose return value for SHFileOperationW depending on
@ -9,19 +9,19 @@ Subject: shell32: Choose return value for SHFileOperationW depending on
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index 62d7880..249970a 100644
index cef2246..290102a 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -1022,7 +1022,7 @@ static HRESULT parse_file_list(FILE_LIST *flList, LPCWSTR szFiles)
@@ -1060,7 +1060,7 @@ static HRESULT parse_file_list(FILE_LIST *flList, LPCWSTR szFiles)
/* empty list */
if (!szFiles[0])
- return ERROR_ACCESS_DENIED;
+ return ERROR_ACCESS_DENIED; /* S_OK for Windows 95/98 */
flList->feFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
flList->num_alloc * sizeof(FILE_ENTRY));
@@ -1555,7 +1555,19 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
@@ -1606,7 +1606,19 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
ZeroMemory(&flTo, sizeof(FILE_LIST));
if ((ret = parse_file_list(&flFrom, lpFileOp->pFrom)))
@ -42,5 +42,5 @@ index 62d7880..249970a 100644
if (lpFileOp->wFunc != FO_DELETE)
parse_file_list(&flTo, lpFileOp->pTo);
--
1.9.1
2.3.0

View File

@ -1 +1,2 @@
Fixes: [37916] Anno 1602 installer depends on Windows 98 behavior of SHFileOperationW
Depends: shell32-Progress_Dialog