cabinet: Fix and test the undocumented Extract function.
The paths are MAX_PATH length.
The last field is list of files which is checked when flags = 0.
Add tests for the flag in the file list.
diff --git a/dlls/cabinet/cabinet.h b/dlls/cabinet/cabinet.h
index d658cdf..53744af 100644
--- a/dlls/cabinet/cabinet.h
+++ b/dlls/cabinet/cabinet.h
@@ -621,7 +621,7 @@
struct ExtractFileList {
LPSTR filename;
struct ExtractFileList *next;
- BOOL unknown; /* always 1L */
+ BOOL flag;
} ;
/* the first parameter of the function extract */
@@ -631,8 +631,10 @@
struct ExtractFileList *filelist; /* 0x010 */
long filecount; /* 0x014 */
DWORD flags; /* 0x018 */
- char directory[0x104]; /* 0x01c */
- char lastfile[0x20c]; /* 0x120 */
+ char directory[MAX_PATH]; /* 0x01c */
+ char lastfile[MAX_PATH]; /* 0x120 */
+ char unknown2[MAX_PATH]; /* 0x224 */
+ struct ExtractFileList *filterlist; /* 0x328 */
} EXTRACTdest;
diff --git a/dlls/cabinet/cabinet_main.c b/dlls/cabinet/cabinet_main.c
index 3c69bf9..ccba932 100644
--- a/dlls/cabinet/cabinet_main.c
+++ b/dlls/cabinet/cabinet_main.c
@@ -157,7 +157,7 @@
static void fill_file_node(struct ExtractFileList *pNode, LPSTR szFilename)
{
pNode->next = NULL;
- pNode->unknown = TRUE;
+ pNode->flag = FALSE;
pNode->filename = HeapAlloc(GetProcessHeap(), 0, strlen(szFilename) + 1);
lstrcpyA(pNode->filename, szFilename);
@@ -216,7 +216,8 @@
pDestination->filecount++;
}
- if (pDestination->flags & EXTRACT_EXTRACTFILES)
+ if ((pDestination->flags & EXTRACT_EXTRACTFILES) ||
+ file_in_list(pDestination->filterlist, pfdin->psz1))
{
/* skip this file it it's not in the file list */
if (!file_in_list(pDestination->filelist, pfdin->psz1))
diff --git a/dlls/cabinet/tests/extract.c b/dlls/cabinet/tests/extract.c
index a108c92..e31318b 100644
--- a/dlls/cabinet/tests/extract.c
+++ b/dlls/cabinet/tests/extract.c
@@ -20,9 +20,17 @@
#include <stdio.h>
#include <windows.h>
-#include <fci.h>
+#include "fci.h"
#include "wine/test.h"
+#ifndef INVALID_FILE_ATTRIBUTES
+#define INVALID_FILE_ATTRIBUTES 0xffffffff
+#endif
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER 0xffffffff
+#endif
+
/* make the max size large so there is only one cab file */
#define MEDIA_SIZE 999999999
#define FOLDER_THRESHOLD 900000
@@ -38,7 +46,7 @@
struct ExtractFileList {
LPSTR filename;
struct ExtractFileList *next;
- BOOL unknown; /* always 1L */
+ BOOL flag;
};
/* the first parameter of the function extract */
@@ -48,8 +56,10 @@
struct ExtractFileList *filelist; /* 0x010 */
long filecount; /* 0x014 */
long flags; /* 0x018 */
- char directory[0x104]; /* 0x01c */
- char lastfile[0x20c]; /* 0x120 */
+ char directory[MAX_PATH]; /* 0x01c */
+ char lastfile[MAX_PATH]; /* 0x120 */
+ char unknown2[MAX_PATH]; /* 0x224 */
+ struct ExtractFileList *filterlist; /* 0x328 */
} EXTRACTDEST;
/* function pointers */
@@ -310,6 +320,16 @@
ok(res, "Failed to destroy the cabinet\n");
}
+static BOOL check_list(EXTRACTDEST *dest, const char *filename, BOOL flag)
+{
+ struct ExtractFileList *i;
+
+ for (i = dest->filelist; i; i=i->next)
+ if (!lstrcmp(filename, i->filename))
+ return (flag == i->flag);
+ return FALSE;
+}
+
static void test_Extract(void)
{
EXTRACTDEST extractDest;
@@ -362,9 +382,15 @@
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
+ ok(check_list(&extractDest, "testdir\\d.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "testdir\\c.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "b.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "a.txt", FALSE), "list entry wrong\n");
+
/* remove two of the files in the list */
extractDest.filelist->next = extractDest.filelist->next->next;
extractDest.filelist->next->next = NULL;
+ extractDest.filterlist = NULL;
CreateDirectoryA("dest", NULL);
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
@@ -372,6 +398,59 @@
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
+
+ todo_wine {
+ ok(check_list(&extractDest, "testdir\\d.txt", FALSE), "list entry wrong\n");
+ ok(!check_list(&extractDest, "testdir\\c.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "b.txt", FALSE), "list entry wrong\n");
+ ok(!check_list(&extractDest, "a.txt", FALSE), "list entry wrong\n");
+ }
+
+ extractDest.flags = 1;
+ extractDest.filelist = NULL;
+ res = pExtract(&extractDest, "extract.cab");
+ ok(res == S_OK, "Expected S_OK, got %ld\n", res);
+ ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
+ ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
+ ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
+ ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
+
+ todo_wine {
+ ok(check_list(&extractDest, "testdir\\d.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "testdir\\c.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "b.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "a.txt", TRUE), "list entry wrong\n");
+ }
+
+ extractDest.flags = 0;
+ res = pExtract(&extractDest, "extract.cab");
+ ok(res == S_OK, "Expected S_OK, got %ld\n", res);
+ ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
+ ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
+ ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
+ ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
+
+ todo_wine {
+ ok(check_list(&extractDest, "testdir\\d.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "testdir\\c.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "b.txt", TRUE), "list entry wrong\n");
+ ok(check_list(&extractDest, "a.txt", TRUE), "list entry wrong\n");
+ }
+
+ extractDest.flags = 0;
+ extractDest.filterlist = extractDest.filelist;
+ res = pExtract(&extractDest, "extract.cab");
+ ok(res == S_OK, "Expected S_OK, got %ld\n", res);
+ ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
+ ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
+ ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
+ ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
+
+ ok(check_list(&extractDest, "testdir\\d.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "testdir\\c.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "b.txt", FALSE), "list entry wrong\n");
+ ok(check_list(&extractDest, "a.txt", FALSE), "list entry wrong\n");
+
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(RemoveDirectoryA("dest"), "Expected dest\\testdir to exist\n");
}