From a44506b563af5a1f852c3c26478adb75ffe01b38 Mon Sep 17 00:00:00 2001 From: Andrew Nguyen Date: Tue, 15 Jun 2010 22:05:36 -0500 Subject: [PATCH] setupapi: Only extract the first MSZIP cabinet file in SetupDecompressOrExtractFile. --- dlls/setupapi/misc.c | 26 +++++++++++----------- dlls/setupapi/tests/misc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c index 3343cd2db13..6e83962f9c4 100644 --- a/dlls/setupapi/misc.c +++ b/dlls/setupapi/misc.c @@ -1456,26 +1456,27 @@ static DWORD decompress_file_lz( LPCWSTR source, LPCWSTR target ) return ret; } +struct callback_context +{ + int has_extracted; + LPCWSTR target; +}; + static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 ) { + struct callback_context *context_info = context; FILE_IN_CABINET_INFO_W *info = (FILE_IN_CABINET_INFO_W *)param1; switch (notification) { case SPFILENOTIFY_FILEINCABINET: { - LPCWSTR filename, targetname = context; - WCHAR *p; - - if ((p = strrchrW( targetname, '\\' ))) filename = p + 1; - else filename = targetname; + if (context_info->has_extracted) + return FILEOP_ABORT; - if (!lstrcmpiW( filename, info->NameInCabinet )) - { - strcpyW( info->FullTargetName, targetname ); - return FILEOP_DOIT; - } - return FILEOP_SKIP; + strcpyW( info->FullTargetName, context_info->target ); + context_info->has_extracted = 1; + return FILEOP_DOIT; } default: return NO_ERROR; } @@ -1483,9 +1484,10 @@ static UINT CALLBACK decompress_or_copy_callback( PVOID context, UINT notificati static DWORD decompress_file_cab( LPCWSTR source, LPCWSTR target ) { + struct callback_context context = {0, target}; BOOL ret; - ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, (PVOID)target ); + ret = SetupIterateCabinetW( source, 0, decompress_or_copy_callback, &context ); if (ret) return ERROR_SUCCESS; else return GetLastError(); diff --git a/dlls/setupapi/tests/misc.c b/dlls/setupapi/tests/misc.c index 20f26830e19..f2d885d9904 100644 --- a/dlls/setupapi/tests/misc.c +++ b/dlls/setupapi/tests/misc.c @@ -361,6 +361,9 @@ static BOOL compare_file_data(LPSTR file, const BYTE *data, DWORD size) static const BYTE uncompressed[] = { 'u','n','c','o','m','p','r','e','s','s','e','d','\r','\n' }; +static const BYTE laurence[] = { + 'l','a','u','r','e','n','c','e','\r','\n' +}; static const BYTE comp_lzx[] = { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33, 0x41, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x75, 0x6e, 0x63, 0x6f, 0x6d, 0x70, 0x3f, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64 @@ -394,6 +397,18 @@ static const BYTE comp_cab_zip[] = { 0x00, 0x7c, 0x80, 0x26, 0x2b, 0x12, 0x00, 0x0e, 0x00, 0x43, 0x4b, 0x2b, 0xcd, 0x4b, 0xce, 0xcf, 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0xe1, 0xe5, 0x02, 0x00 }; +static const BYTE comp_cab_zip_multi[] = { + 0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x74, 0x72, 0x69, 0x73, + 0x74, 0x72, 0x61, 0x6d, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, + 0x38, 0xf0, 0x48, 0x20, 0x00, 0x77, 0x69, 0x6e, 0x65, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd1, 0x38, 0xf0, 0x48, 0x20, 0x00, 0x73, 0x68, 0x61, 0x6e, 0x64, 0x79, + 0x00, 0x67, 0x2c, 0x03, 0x85, 0x23, 0x00, 0x20, 0x00, 0x43, 0x4b, 0xcb, 0x49, 0x2c, 0x2d, 0x4a, + 0xcd, 0x4b, 0x4e, 0xe5, 0xe5, 0x2a, 0xcd, 0x4b, 0xce, 0xcf, 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, + 0x4d, 0xe1, 0xe5, 0x2a, 0x2e, 0x49, 0x2d, 0xca, 0x03, 0x8a, 0x02, 0x00 +}; static void test_SetupGetFileCompressionInfo(void) { @@ -523,6 +538,23 @@ static void test_SetupDecompressOrCopyFile(void) {source, NULL, &type}, }; + const struct + { + const char *filename; + const BYTE *expected_buffer; + const size_t buffer_size; + } zip_multi_tests[] = + { + {"tristram", laurence, sizeof(laurence)}, + {"tristram.txt", laurence, sizeof(laurence)}, + {"wine", laurence, sizeof(laurence)}, + {"wine.txt", laurence, sizeof(laurence)}, + {"shandy", laurence, sizeof(laurence)}, + {"shandy.txt", laurence, sizeof(laurence)}, + {"deadbeef", laurence, sizeof(laurence)}, + {"deadbeef.txt", laurence, sizeof(laurence)}, + }; + GetTempPathA(sizeof(temp), temp); GetTempFileNameA(temp, "doc", 0, source); GetTempFileNameA(temp, "doc", 0, target); @@ -624,7 +656,27 @@ static void test_SetupDecompressOrCopyFile(void) ok(!ret, "SetupDecompressOrCopyFile failed unexpectedly: %d\n", ret); ok(compare_file_data(target, comp_cab_zip, sizeof(comp_cab_zip)), "incorrect target file\n"); - DeleteFileA(target); + /* Show that SetupDecompressOrCopyFileA simply extracts the first file it + * finds within the compressed cabinet. Contents are: + * tristram -> "laurence\r\n" + * wine -> "uncompressed\r\n" + * shandy -> "sterne\r\n" */ + + create_source_file(source, comp_cab_zip_multi, sizeof(comp_cab_zip_multi)); + + p = strrchr(target, '\\'); + + for (i = 0; i < sizeof(zip_multi_tests)/sizeof(zip_multi_tests[0]); i++) + { + lstrcpyA(p + 1, zip_multi_tests[i].filename); + + ret = SetupDecompressOrCopyFileA(source, target, NULL); + ok(!ret, "[%d] SetupDecompressOrCopyFile failed unexpectedly: %d\n", i, ret); + ok(compare_file_data(target, zip_multi_tests[i].expected_buffer, zip_multi_tests[i].buffer_size), + "[%d] incorrect target file\n", i); + DeleteFileA(target); + } + DeleteFileA(source); } -- 2.11.4.GIT