Andrew Nguyen : setupapi: Only extract the first MSZIP cabinet file in SetupDecompressOrExtractFile.

Alexandre Julliard julliard at winehq.org
Wed Jun 16 13:23:22 CDT 2010


Module: wine
Branch: master
Commit: a44506b563af5a1f852c3c26478adb75ffe01b38
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a44506b563af5a1f852c3c26478adb75ffe01b38

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Tue Jun 15 22:05:36 2010 -0500

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 3343cd2..6e83962 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 20f2683..f2d885d 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);
 }
 




More information about the wine-cvs mailing list