From 37c0bd4cacf5aceb287532447be13c94f1287b59 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Thu, 22 Sep 2022 16:13:59 +0200 Subject: [PATCH] [0.4.13][SHELL32] Copy without FILE_ATTRIBUTE_READONLY from a CDROM CORE-18089 (#4386) That problem in the shell was unhidden when we switched from our own to the MS-PL CDFS-driver in 0.4.8-dev-164-g ec6b3ecbe48ad51c366563196cc93a6ae74e8b69 because our own old CDFS driver erroneously never reported any CD file being read-only. Fix picked from 0.4.15-dev-4348-g 513d0a6d2d4652671c9b7c92c495edce6d9491a4 While backporting the fix, I decided to port back also some EOL-whitespace-stripping in that file. --- dll/win32/shell32/shlfileop.cpp | 49 ++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/dll/win32/shell32/shlfileop.cpp b/dll/win32/shell32/shlfileop.cpp index 499f4d3079e..40c58e57063 100644 --- a/dll/win32/shell32/shlfileop.cpp +++ b/dll/win32/shell32/shlfileop.cpp @@ -551,7 +551,7 @@ static void _SetOperationTexts(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest) { default: return; } - + FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY, op->szBuilderString, 0, 0, szFinalString, sizeof(szFinalString), (va_list*)args); @@ -574,11 +574,11 @@ DWORD CALLBACK SHCopyProgressRoutine( FILE_OPERATION *op = (FILE_OPERATION *) lpData; if (op->progress) { - /* - * This is called at the start of each file. To keop less state, + /* + * This is called at the start of each file. To keop less state, * I'm adding the file to the completed size here, and the re-subtracting * it when drawing the progress bar. - */ + */ if (dwCallbackReason & CALLBACK_STREAM_SWITCH) op->completedSize.QuadPart += TotalFileSize.QuadPart; @@ -586,7 +586,7 @@ DWORD CALLBACK SHCopyProgressRoutine( TotalFileSize.QuadPart + TotalBytesTransferred.QuadPart , op->totalSize.QuadPart); - + op->bCancelled = op->progress->HasUserCancelled(); } @@ -713,6 +713,21 @@ static DWORD SHNotifyMoveFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BO return GetLastError(); } +static BOOL SHIsCdRom(LPCWSTR path) +{ + WCHAR tmp[] = { L"A:\\" }; + + if (!path || !path[0]) + return FALSE; + + if (path[1] != UNICODE_NULL && path[1] != ':') + return FALSE; + + tmp[0] = path[0]; + + return GetDriveTypeW(tmp) == DRIVE_CDROM; +} + /************************************************************************ * SHNotifyCopyFile [internal] * @@ -753,6 +768,14 @@ static DWORD SHNotifyCopyFileW(FILE_OPERATION *op, LPCWSTR src, LPCWSTR dest, BO ret = CopyFileExW(src, dest, SHCopyProgressRoutine, op, &op->bCancelled, bFailIfExists); if (ret) { + // We are copying from a CD-ROM volume, which is readonly + if (SHIsCdRom(src)) + { + attribs = GetFileAttributesW(dest); + attribs &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributesW(dest, attribs); + } + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); return ERROR_SUCCESS; } @@ -1477,7 +1500,7 @@ static HRESULT copy_files(FILE_OPERATION *op, BOOL multiDest, const FILE_LIST *f return ERROR_CANCELLED; } } - + if (op->progress != NULL) op->bCancelled |= op->progress->HasUserCancelled(); /* Vista return code. XP would return e.g. ERROR_FILE_NOT_FOUND, ERROR_ALREADY_EXISTS */ @@ -1717,7 +1740,7 @@ 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, IsAttribDir(entryToMove->attributes)); - + if (op->progress != NULL) op->bCancelled |= op->progress->HasUserCancelled(); /* Should fire on progress dialog only */ @@ -1811,9 +1834,9 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp) op.bManyItems = (flFrom.dwNumFiles > 1); if (lpFileOp->wFunc != FO_RENAME && !(lpFileOp->fFlags & FOF_SILENT)) { - ret = CoCreateInstance(CLSID_ProgressDialog, - NULL, - CLSCTX_INPROC_SERVER, + ret = CoCreateInstance(CLSID_ProgressDialog, + NULL, + CLSCTX_INPROC_SERVER, IID_PPV_ARG(IProgressDialog, &op.progress)); if (FAILED(ret)) goto cleanup; @@ -2091,7 +2114,7 @@ EXTERN_C HRESULT WINAPI SHPathPrepareForWriteA(HWND hwnd, IUnknown *modless, LPC } -/* +/* * The two following background operations were modified from filedefext.cpp * They use an inordinate amount of mutable state across the string functions, * so are not easy to follow and care is required when modifying. @@ -2102,11 +2125,11 @@ _FileOpCountManager(FILE_OPERATION *op, const FILE_LIST *from) { DWORD ticks = GetTickCount(); FILE_ENTRY *entryToCount; - + for (UINT i = 0; i < from->dwNumFiles; i++) { entryToCount = &from->feFiles[i]; - + WCHAR theFileName[MAX_PATH]; StringCchCopyW(theFileName, MAX_PATH, entryToCount->szFullPath); _FileOpCount(op, theFileName, IsAttribDir(entryToCount->attributes), &ticks);