[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.
This commit is contained in:
Hermès Bélusca-Maïto 2017-12-31 02:47:03 +01:00
parent 7c447a15a0
commit e0baa58f1b
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0

View file

@ -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
}