version 1.5, 2005/02/04 09:37:43
|
version 1.8, 2005/02/11 09:56:01
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ | */ |
| |
|
|
#include <stdlib.h> | #include <stdlib.h> |
| |
#ifndef STANDALONE | #ifndef STANDALONE |
|
|
#define todo_wine | #define todo_wine |
#endif | #endif |
| |
|
|
#include <winerror.h> | #include <winerror.h> |
#include <fdi.h> | #include <fdi.h> |
|
#include <fcntl.h> |
|
|
|
/* Do malloc and free output debug messages? |
|
#define DEBUG_ALLOC |
|
*/ |
|
|
|
/* What is our "Fake" Filedescriptor? */ |
|
static int fakeFD = 22881; |
|
|
|
/* |
|
This hex data is the output of compress.exe (Windows Server 2003 Resource Kit) |
|
|
|
The cab file is mirrored in the file system as simple.cab |
|
|
|
The 'test.txt' in the cab file contains the string 'So long, and thanks for all the fish.' |
|
*/ |
|
static unsigned char compressed_file[] = |
|
{0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x75,0x00, |
|
0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0x00,0x00,0x00, |
|
0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x01,0x00, |
|
0x00,0x00,0x39,0x30,0x00,0x00,0x45,0x00,0x00,0x00, |
|
0x01,0x00,0x01,0x00,0x26,0x00,0x00,0x00,0x00,0x00, |
|
0x00,0x00,0x00,0x00,0x4A,0x32,0xB2,0xBE,0x20,0x00, |
|
0x74,0x65,0x73,0x74,0x2E,0x74,0x78,0x74,0x00,0x9C, |
|
0x74,0xD0,0x75,0x28,0x00,0x26,0x00,0x43,0x4B,0x0B, |
|
0xCE,0x57,0xC8,0xC9,0xCF,0x4B,0xD7,0x51,0x48,0xCC, |
|
0x4B,0x51,0x28,0xC9,0x48,0xCC,0xCB,0x2E,0x56,0x48, |
|
0xCB,0x2F,0x52,0x48,0xCC,0xC9,0x01,0x72,0x53,0x15, |
|
0xD2,0x32,0x8B,0x33,0xF4,0xB8,0x00}; |
|
static int szcompressed_file = sizeof(compressed_file); |
|
|
|
|
|
/* |
|
static const char uncompressed_data[] = "This is a test file."; |
|
static const DWORD uncompressed_data_size = sizeof(uncompressed_data) - 1; |
|
|
|
static char *buf; |
|
*/ |
| |
/* To do in FDI: -from wine/include/fdi.h |
/* |
|
To do in FDI: -from wine/include/fdi.h |
FDICreate | FDICreate |
Memory Allocation -FNALLOC(cb) |
|
Memory Free -FNFREE(pv) |
|
File Open -FNOPEN(pszFile,oflag,pmode) |
|
File Read -FNREAD(hf, pv, cb) |
|
File Write -FNWRITE(hf, pv, cb) | File Write -FNWRITE(hf, pv, cb) |
File Close -FNCLOSE(hf) |
|
File Seek -FNSEEK(hf,dist,seektype) | File Seek -FNSEEK(hf,dist,seektype) |
Error Structure | Error Structure |
FDIlsCabinet |
|
FDICabinetInfo Structure |
|
FDICopy | FDICopy |
Notification function | Notification function |
Decryption function | Decryption function |
|
|
| |
/* Currently mostly dummy function pointers */ | /* Currently mostly dummy function pointers */ |
| |
FNALLOC(debug_alloc) { |
#ifndef DEBUG_ALLOC |
|
FNALLOC(final_alloc) { |
|
return malloc(cb); |
|
} |
|
FNFREE(final_free) { |
|
free(pv); |
|
return; |
|
} |
|
#else |
|
FNALLOC(final_alloc) { |
printf(" FNALLOC just called with %d\n",cb); | printf(" FNALLOC just called with %d\n",cb); |
return malloc(cb); | return malloc(cb); |
} | } |
|
FNFREE(final_free) { |
FNFREE(debug_free) { |
|
printf(" FNFREE just called with %d\n",pv); | printf(" FNFREE just called with %d\n",pv); |
free(pv); | free(pv); |
return; | return; |
} | } |
|
#endif |
|
|
|
|
|
/* |
|
It is not necessary for these functions to actually call _open etc.; |
|
these functions could instead call fopen, fread, fwrite, fclose, and fseek, |
|
or CreateFile, ReadFile, WriteFile, CloseHandle, and SetFilePointer, etc. |
|
However, the parameters and return codes will have to be translated |
|
appropriately (e.g. the file open mode passed in to pfnopen). |
|
|
|
Match i/o specs of _open, _read, _write, _close, and _lseek. |
|
|
|
*/ |
| |
/* | /* |
It is not necessary for these functions to actually call _open etc.; these functions could instead call fopen, fread, fwrite, fclose, and fseek, or CreateFile, ReadFile, WriteFile, CloseHandle, and SetFilePointer, etc. However, the parameters and return codes will have to be translated appropriately (e.g. the file open mode passed in to pfnopen). |
http://msdn.microsoft.com/library/en-us/vclib/html/_crt__open.2c_._wopen.asp |
|
_open I: const char *filename, int oflag, int pmode O: int (handler), -1 for err. |
|
DUMMY : FUNCTIONAL FAKE : FUNCTIONAL REAL : FUNCTIONAL |
*/ | */ |
| |
FNOPEN(dummy_open) { | FNOPEN(dummy_open) { |
printf(" FNOPEN just called with %d, %d, %d\n",pszFile, oflag, pmode); |
printf(" FNOPEN (dummy) just called with %d, %d, %d\n",pszFile, oflag, pmode); |
return 0; | return 0; |
} | } |
| |
|
FNOPEN(fake_open) { |
|
printf(" FNOPEN (fake) just called with %d, %d, %d\n",pszFile, oflag, pmode); |
|
printf(" Returning %d as file descriptor\n",fakeFD); |
|
return 12; |
|
} |
|
|
|
FNOPEN(real_open) { |
|
int handler = _open(pszFile,oflag,pmode); |
|
printf(" FNOPEN (real) just called with %s, %d, %d\n",pszFile, oflag, pmode); |
|
printf(" FNOPEN (real) returning handler (%d)\n",handler); |
|
return handler; |
|
} |
|
|
|
/* |
|
http://msdn.microsoft.com/library/en-us/vclib/html/_CRT__read.asp |
|
_read I: int fd, void *buffer, unsigned int count O: int (szBuffer) |
|
DUMMY : FUNCTIONAL FAKE : FUNCTIONAL, INCOMPLETE REAL : FUNCTIONAL |
|
*/ |
|
|
FNREAD(dummy_read) { | FNREAD(dummy_read) { |
printf(" FNREAD just called with %d, %d, %d\n",hf, pv, cb); |
printf(" FNREAD (dummy) just called with %d, %d, %d\n",hf, pv, cb); |
return 0; | return 0; |
} | } |
| |
FNWRITE(dummy_write) { |
/* Doesn't keep virtual file location pointer */ |
printf(" FNWRITE just called with %d, %d, %d\n",hf, pv, cb); |
FNREAD(fake_read) { |
return 0; |
printf(" FNREAD (fake) just called with %d, %d, %d\n",hf, pv, cb); |
|
if (hf == fakeFD) { |
|
printf (" Called with fake file descriptor, populating buffer and size (%d)\n",cb); |
|
memcpy (pv, compressed_file ,cb); |
|
} |
|
else { |
|
printf (" FNREAD (fake) was called with the unknown file handler. Failed!\n",hf); |
|
} |
|
return cb; |
} | } |
| |
|
FNREAD(real_read) { |
|
int szBuffer = _read(hf,pv,cb); |
|
printf(" FNREAD (read) just called with %d, %d, %d\n",hf, pv, cb); |
|
printf(" FNREAD (read) returning size (%d)\n",szBuffer); |
|
return szBuffer; |
|
} |
|
|
|
/* |
|
http://msdn.microsoft.com/library/en-us/vclib/html/_CRT__close.asp |
|
_close I: int fd O: int (0=success 1=failure) |
|
DUMMY : FUNCTIONAL FAKE : FUNCTIONAL REAL : FUNCTIONAL |
|
*/ |
| |
FNCLOSE(dummy_close) { | FNCLOSE(dummy_close) { |
printf(" FNCLOSE just called with %d\n",hf); |
printf(" FNCLOSE (dummy) just called with %d - returning %d\n",hf,0); |
|
return 0; |
|
} |
|
|
|
FNCLOSE(fake_close) { |
|
printf(" FNCLOSE (fake) just called with %d - returning %d\n",hf,0); |
|
return 0; |
|
} |
|
|
|
FNCLOSE(real_close) { |
|
int closevalue = _close(hf); |
|
printf(" FNCLOSE (real) just called with %d - returning %d\n",hf,closevalue); |
|
return closevalue; |
|
} |
|
|
|
|
|
FNWRITE(dummy_write) { |
|
printf(" FNWRITE just called with %d, %d, %d\n",hf, pv, cb); |
return 0; | return 0; |
} | } |
| |
|
|
return 0; | return 0; |
} | } |
| |
HFDI hfdi_386, hfdi_286, hfdi_unknown; |
HFDI hfdi_unknown_dummy, hfdi_unknown_fake,hfdi_unknown_real; |
/* yes its global and ugly */ | /* yes its global and ugly */ |
| |
static void TestDestroy(void) { |
|
printf("Starting TestDestroy()\n"); |
|
/* Only two things to check in FDIDestroy |
|
1=> Does it return T if its passed an hfdi |
|
2=> Does it return F if its passed a non hfdi |
|
EDIT : Causes GPL if FDIDestroy is called on an invalid pointer. |
|
ok( 0 == FDIDestroy(0), "Return true incorrectly in TestDestroy()!\n"); |
|
*/ |
|
ok(FDIDestroy(hfdi_386), "Failed on destroying 386 hfdi!\n"); |
|
ok(FDIDestroy(hfdi_286), "Failed on destroying 286 hfdi!\n"); |
|
ok(FDIDestroy(hfdi_unknown), "Failed on destroying unknown hfdi!\n"); |
|
printf("Ending TestDestroy()\n"); |
|
|
|
} |
|
| |
static void TestCreate(void) { | static void TestCreate(void) { |
| |
|
|
| |
printf("Starting TestCreate()\n"); | printf("Starting TestCreate()\n"); |
| |
hfdi_386 = FDICreate( |
hfdi_unknown_dummy = FDICreate( |
debug_alloc, |
final_alloc, |
debug_free, |
final_free, |
dummy_open, | dummy_open, |
dummy_read, | dummy_read, |
dummy_write, | dummy_write, |
dummy_close, | dummy_close, |
dummy_seek, | dummy_seek, |
cpu80386, |
cpuUNKNOWN, |
&error_structure | &error_structure |
); | ); |
ok(hfdi_386 != NULL,"FDICreate (CPU = cpu80386) failed!\n"); |
ok(hfdi_unknown_dummy != NULL,"FDICreate (CPU = unknown) (functions=dummy) failed!\n"); |
| |
hfdi_286 = FDICreate( |
hfdi_unknown_fake = FDICreate( |
debug_alloc, |
final_alloc, |
debug_free, |
final_free, |
dummy_open, |
fake_open, |
dummy_read, |
fake_read, |
dummy_write, | dummy_write, |
dummy_close, | dummy_close, |
dummy_seek, | dummy_seek, |
cpu80286, |
cpuUNKNOWN, |
&error_structure | &error_structure |
); | ); |
ok(hfdi_286 != NULL,"FDICreate (CPU = cpu80286) failed!\n"); |
ok(hfdi_unknown_fake != NULL,"FDICreate (CPU = unknown) (functions=fake) failed!\n"); |
| |
hfdi_unknown = FDICreate( |
hfdi_unknown_real = FDICreate( |
debug_alloc, |
final_alloc, |
debug_free, |
final_free, |
dummy_open, |
real_open, |
dummy_read, |
real_read, |
dummy_write, | dummy_write, |
dummy_close, |
real_close, |
dummy_seek, | dummy_seek, |
cpuUNKNOWN, | cpuUNKNOWN, |
&error_structure | &error_structure |
); | ); |
ok(hfdi_unknown != NULL,"FDICreate (CPU = unknown) failed!\n"); |
ok(hfdi_unknown_real != NULL,"FDICreate (CPU = unknown) (functions=real) failed!\n"); |
|
|
|
printf("Ending TestCreate()\n"); |
|
} |
| |
|
static void TestInfo(void) { |
|
/* Noticed Behavior : |
|
FDIIsCabinet does not open the file on its own, it requires a file open/close to be done externally. |
|
WHY? |
|
The only functions in HFDI that FDIIsCabinet directly accesses is FNREAD |
|
Important cases to check : |
|
If the filedescriptor == ERR, does it FAIL? (dummy_read) |
|
If the filedescriptor == NOTCABINET, does it FAIL? (fake_read, real_read) |
|
If the filedescriptor == CABINET, does it SUCCEED? (fake_read, real_read) |
|
If the filedescriptor == CABINET, does it populate FDICABINETINFO? (fake_read, real_read) |
|
*/ |
| |
|
int realfd; |
|
int sizer; |
|
FDICABINETINFO fdi_cabinfo_dummy, fdi_cabinfo_simple, fdi_cabinfo_complex; |
|
|
|
printf("Starting TestInfo()\n"); |
|
|
|
/* TEST : ERR filehandle associated, dummy functions should return FALSE */ |
|
ok ( FDIIsCabinet( hfdi_unknown_dummy, -1, &fdi_cabinfo_dummy) == FALSE, |
|
"FDIIsCabinet (File = Error) failed!\n"); |
|
|
|
/* TEST : Fake filehandle associated, memory manually copied, should return TRUE */ |
|
ok ( FDIIsCabinet( hfdi_unknown_fake, fakeFD, &fdi_cabinfo_simple) == TRUE, |
|
"FDIIsCabinet (FakeFile = Cabinet) failed!\n"); |
|
|
|
ok ( fdi_cabinfo_simple.cbCabinet == 117, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.cFolders == 1, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.cFiles == 1, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.setID == 12345, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.iCabinet == 0, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.fReserve == 'b', "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.hasprev == 117, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
ok ( fdi_cabinfo_simple.hasnext == 117, "FDIIsCabinet,cabinfo (FakeFile = Cabinet) data did not match! Failed!\n"); |
|
|
|
realfd = real_open( "working.cab" , _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0); |
|
ok ( FDIIsCabinet( hfdi_unknown_real, realfd, &fdi_cabinfo_complex) == TRUE, |
|
"FDIIsCabinet (File = Cabinet) failed!\n"); |
|
real_close(realfd); |
|
|
|
printf("Cabinet Data : cbC %d cF %d cFi %d si %d iC %d fr %b hp %d hn %d\n,", |
|
fdi_cabinfo_complex.cbCabinet, |
|
fdi_cabinfo_complex.cFolders , |
|
fdi_cabinfo_complex.cFiles , |
|
fdi_cabinfo_complex.setID, |
|
fdi_cabinfo_complex.iCabinet, |
|
fdi_cabinfo_complex.fReserve , |
|
fdi_cabinfo_complex.hasprev , |
|
fdi_cabinfo_complex.hasnext ); |
| |
|
} |
|
|
|
|
|
static void TestDestroy(void) { |
|
printf("Starting TestDestroy()\n"); |
|
/* Only two things to check in FDIDestroy |
|
1=> Does it return T if its passed an hfdi |
|
2=> Does it return F if its passed a non hfdi |
|
EDIT : Causes GPL if FDIDestroy is called on an invalid pointer. |
|
ok( 0 == FDIDestroy(0), "Return true incorrectly in TestDestroy()!\n"); |
|
*/ |
|
|
|
ok(FDIDestroy(hfdi_unknown_dummy), "FDIDestroy (CPU = unknown) (functions=fake) failed!\n"); |
|
ok(FDIDestroy(hfdi_unknown_fake), "FDIDestroy (CPU = unknown) (functions=fake) failed!\n"); |
|
printf("Ending TestDestroy()\n"); |
| |
printf("Ending TestCreate()\n"); |
|
} | } |
| |
|
|
START_TEST(paths) | START_TEST(paths) |
{ | { |
| |
TestCreate(); | TestCreate(); |
/* |
|
TestInfo(); | TestInfo(); |
|
/* |
TestCopy(); | TestCopy(); |
*/ | */ |
TestDestroy(); | TestDestroy(); |