From e0baa58f1b54b9d49e1724ed559f7b9a5cff6a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 31 Dec 2017 02:47:03 +0100 Subject: [PATCH] [SETUPAPI] Fix extraction of files from a cabinet file using the SetupQueueCopy and SetupCommitFileQueue method. CORE-14164 - Contrary to what Wine thought, this works even if the cabinet file does not have a ".cab" extension. - Instead of polluting the directory where the cabinet file exists with all the files extracted from it, we only extract the needed file to a temporary folder (thus being sure it does not overwrite any other existing file with the same name), and then we move the extracted file to its final destination with rename. --- dll/win32/setupapi/queue.c | 75 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/dll/win32/setupapi/queue.c b/dll/win32/setupapi/queue.c index b556418389f..060984be8f0 100644 --- a/dll/win32/setupapi/queue.c +++ b/dll/win32/setupapi/queue.c @@ -362,7 +362,11 @@ static WCHAR *get_destination_dir( HINF hinf, const WCHAR *section ) } +#ifndef __REACTOS__ static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); +#else +static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, LPSTR, LPVOID, DWORD ); +#endif /*********************************************************************** * extract_cabinet_file @@ -372,14 +376,21 @@ static void (WINAPI *pExtractFiles)( LPSTR, LPSTR, DWORD, DWORD, DWORD, DWORD ); static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, const WCHAR *src, const WCHAR *dst ) { +#ifndef __REACTOS__ static const WCHAR extW[] = {'.','c','a','b',0}; +#endif static HMODULE advpack; char *cab_path, *cab_file; int len = strlenW( cabinet ); +#ifdef __REACTOS__ + TRACE("extract_cabinet_file(cab = '%s' ; root = '%s' ; src = '%s' ; dst = '%s')\n", + debugstr_w(cabinet), debugstr_w(root), debugstr_w(src), debugstr_w(dst)); +#else /* make sure the cabinet file has a .cab extension */ if (len <= 4 || strcmpiW( cabinet + len - 4, extW )) return FALSE; +#endif if (!pExtractFiles) { if (!advpack && !(advpack = LoadLibraryA( "advpack.dll" ))) @@ -405,10 +416,74 @@ static BOOL extract_cabinet_file( const WCHAR *cabinet, const WCHAR *root, if (cab_file[0] && cab_file[strlen(cab_file)-1] != '\\') strcat( cab_file, "\\" ); WideCharToMultiByte( CP_ACP, 0, cabinet, -1, cab_file + strlen(cab_file), len, NULL, NULL ); FIXME( "awful hack: extracting cabinet %s\n", debugstr_a(cab_file) ); + +#ifdef __REACTOS__ + { + BOOL Success; + char *src_file; + const WCHAR *src_fileW; + WCHAR TempPath[MAX_PATH]; + + /* Retrieve the temporary path */ + if (!GetTempPathW(ARRAYSIZE(TempPath), TempPath)) + { + ERR("GetTempPathW error\n"); + HeapFree( GetProcessHeap(), 0, cab_file ); + return FALSE; + } + + /* Build the real path to where the file will be extracted */ + HeapFree( GetProcessHeap(), 0, cab_path ); + if (!(cab_path = strdupWtoA( TempPath ))) + { + HeapFree( GetProcessHeap(), 0, cab_file ); + return FALSE; + } + + /* Build the file list */ + src_fileW = strrchrW(src, '\\'); // Find where the filename starts. + if (src_fileW) ++src_fileW; + else src_fileW = src; + /* Convert to ANSI */ + if (!(src_file = strdupWtoA( src_fileW ))) + { + HeapFree( GetProcessHeap(), 0, cab_file ); + HeapFree( GetProcessHeap(), 0, cab_path ); + return FALSE; + } + + /* Prepare for the move operation */ + /* Build the full path to the extracted file, that will be renamed */ + if (!(src = HeapAlloc( GetProcessHeap(), 0, (strlenW(TempPath) + 1 + strlenW(src_fileW) + 1) * sizeof(WCHAR) ))) + { + HeapFree( GetProcessHeap(), 0, src_file ); + HeapFree( GetProcessHeap(), 0, cab_file ); + HeapFree( GetProcessHeap(), 0, cab_path ); + return FALSE; + } + concat_W( (WCHAR*)src, NULL, TempPath, src_fileW ); + + TRACE("pExtractFiles(cab_file = '%s' ; cab_path = '%s', src_file = '%s')\n", + debugstr_a(cab_file), debugstr_a(cab_path), debugstr_a(src_file)); + + /* Extract to temporary folder */ + pExtractFiles( cab_file, cab_path, 0, src_file, NULL, 0 ); + HeapFree( GetProcessHeap(), 0, src_file ); + HeapFree( GetProcessHeap(), 0, cab_file ); + HeapFree( GetProcessHeap(), 0, cab_path ); + + /* Move to destination, overwriting the original file if needed */ + TRACE("Renaming src = '%s' to dst = '%s')\n", debugstr_w(src), debugstr_w(dst)); + Success = MoveFileExW( src, dst , MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED ); + HeapFree( GetProcessHeap(), 0, (WCHAR*)src ); + return Success; + } +#else pExtractFiles( cab_file, cab_path, 0, 0, 0, 0 ); HeapFree( GetProcessHeap(), 0, cab_file ); HeapFree( GetProcessHeap(), 0, cab_path ); return CopyFileW( src, dst, FALSE /*FIXME*/ ); +#endif }