diff -Nuar oldwine/configure.ac wine/configure.ac
--- oldwine/configure.ac	2005-03-05 03:19:14.000000000 -0800
+++ wine/configure.ac	2005-03-16 02:09:50.750000000 -0800
@@ -1519,6 +1519,7 @@
 dlls/avicap32/Makefile
 dlls/avifil32/Makefile
 dlls/cabinet/Makefile
+dlls/cabinet/tests/Makefile
 dlls/capi2032/Makefile
 dlls/cards/Makefile
 dlls/cfgmgr32/Makefile
diff -Nuar oldwine/dlls/cabinet/Makefile.in wine/dlls/cabinet/Makefile.in
--- oldwine/dlls/cabinet/Makefile.in	2003-12-31 10:56:07.000000000 -0800
+++ wine/dlls/cabinet/Makefile.in	2005-03-16 02:10:47.718750000 -0800
@@ -12,7 +12,7 @@
 	fdi.c
 
 RC_SRCS = cabinet.rc
-
+SUBDIRS = tests
 @MAKE_DLL_RULES@
 
 ### Dependencies:
diff -Naur oldwine/dlls/cabinet/tests/Makefile.in wine/dlls/cabinet/tests/Makefile.in
--- oldwine/dlls/cabinet/tests/Makefile.in	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/Makefile.in	Wed May 11 10:28:31 2005
@@ -0,0 +1,16 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+TESTDLL   = cabinet.dll
+IMPORTS   = kernel32 cabinet
+
+RC_SRCS = cabinet.rc
+
+CTESTS = \
+    tvfs.c \
+	cabinet_fdi.c
+
+@MAKE_TEST_RULES@
+
+### Dependencies:
diff -Naur oldwine/dlls/cabinet/tests/cabinet_fdi.c wine/dlls/cabinet/tests/cabinet_fdi.c
--- oldwine/dlls/cabinet/tests/cabinet_fdi.c	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/cabinet_fdi.c	Wed May 11 14:20:35 2005
@@ -0,0 +1,321 @@
+/*
+ * Unit test suite for cabinet.dll - FDI functions
+ *
+ * Copyright 2005 Rizwan Kassim, Dan Kegel, Alexander Liber, Thomas Kho
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* posix includes */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+ 
+/* windows includes */
+#include <windef.h>
+#include <winbase.h>
+#include <winerror.h>
+#include <fdi.h>
+
+/* our own private includes */
+#include "tvfs.h"
+#include "simplecab.h"
+
+/* To build outside Wine tree, compile with 
+    cl -DSTANDALONE -D_X86_ cabinet_fdi.c tvfs.c FDI.lib 
+*/
+#ifdef STANDALONE
+#include "standalone.h"
+#else
+#include <wine/test.h>
+/* wine/test.h defines a varadic function ok(), but
+ * standalone.h defines one version of ok() for each number of parameters.
+ * Define ok2, etc. so we can compile with either wine/test.h or standalone.h.
+ */
+#define ok2 ok	/* ok(condition, format, arg) */
+#define ok3 ok	/* ok(condition, format, arg1, arg2) */
+#endif 
+
+/* We'd like to build with either cl or winegcc, so let's use the unix
+ * names for open flags, and provide a dummy definition of flags
+ * unix doesn't support
+ */
+#ifndef O_BINARY	
+#define O_BINARY 0
+#endif
+#ifndef O_CREAT
+#define O_CREAT	_O_CREAT
+#define O_WRONLY	_O_WRONLY
+#endif
+/* ditto for stat */
+#ifndef S_IREAD
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+#endif
+
+/* what kind of failure to inject, if any */
+enum TestType { TT_NORMAL, TT_FULL_DISK, TT_NO_FILE };
+
+/* Define callback functions to pass as arguments to FDICreate.
+ * Use the whacky macros FNALLOC() etc. from <fdi.h> to make sure we get 
+ * parameter types right.
+ * Wrap malloc and free solely to avoid compiler warnings.
+ */
+FNALLOC(my_malloc) {
+    return malloc(cb);
+}
+
+FNFREE(my_free) {
+    free(pv);
+}
+
+FNFDINOTIFY(notification_function)
+{
+    switch (fdint)
+    {
+        case fdintCOPY_FILE:
+        {
+	    /* Called by FDICopy to open output file */
+            return tvfs_open (pfdin->psz1,
+                O_BINARY | O_CREAT | O_WRONLY,
+                S_IREAD | S_IWRITE );
+        }    
+        case fdintCLOSE_FILE_INFO:    
+        {
+            tvfs_close(pfdin->hf);
+            return TRUE;
+        }
+    }
+    return 0;
+}
+
+static TestConstant()
+{
+    trace("TestConstant\n");
+    ok(FDIERROR_CABINET_NOT_FOUND==1,"FDIERROR_CABINET_NOT_FOUND is incorrect!\n");
+    ok(FDIERROR_NOT_A_CABINET==2,"FDIERROR_NOT_A_CABINET is incorrect!\n");
+    ok(FDIERROR_CORRUPT_CABINET==4,"FDIERROR_CORRUPT_CABINET is incorrect!\n");    
+    ok(FDIERROR_TARGET_FILE==8,"FDIERROR_TARGET_FILE is incorrect!\n");
+    ok(fdintCABINET_INFO==0,"fdintCABINET_INFO is incorrect!\n");
+    ok(fdintPARTIAL_FILE==1,"fdintPARTIAL_FILE is incorrect!\n");    
+    ok(fdintCOPY_FILE==2,"fdintCOPY_FILE is incorrect!\n");
+    ok(fdintCLOSE_FILE_INFO==3,"fdintCLOSE_FILE_INFO is incorrect!\n");
+    ok(fdintNEXT_CABINET==4,"fdintNEXT_CABINET is incorrect!\n");    
+    ok(fdintENUMERATE==5,"fdintENUMERATE is incorrect!\n");    
+}    
+
+
+/* Copy TestSimple into a seperate block of code for each new cabinet being tested, possibly removing modes 1,2*/
+/* mode=0 - standard work. mode=1 simulates write fail. mode=2 simulates missing cabinet. */
+static void TestSimple(enum TestType mode)
+{
+    int result, fd;
+    FDICABINETINFO  fdi_cabinfo_simple;
+    static HFDI hfdi_simple;
+    ERF error_structure;
+
+    trace("TestSimple: * mode %d\n",mode);
+    
+    switch (mode) {
+    case TT_NORMAL:
+        hfdi_simple = FDICreate(
+            my_malloc, my_free, tvfs_open, tvfs_read, tvfs_write, tvfs_close, tvfs_lseek, cpuUNKNOWN, &error_structure);
+	break;
+    case TT_FULL_DISK:
+        hfdi_simple = FDICreate(
+            my_malloc, my_free, tvfs_open, tvfs_read, tvfs_write_full, tvfs_close, tvfs_lseek, cpuUNKNOWN, &error_structure);
+	break;
+    case TT_NO_FILE:
+        hfdi_simple = FDICreate(
+            my_malloc, my_free, tvfs_open_missing, tvfs_read, tvfs_write, tvfs_close, tvfs_lseek, cpuUNKNOWN, &error_structure);
+	break;
+    }
+
+    ok2(hfdi_simple != NULL,"FDICreate failed! erfOper=%d\n",error_structure.erfOper);    
+
+    tvfs_create( name_simple_cab, file_simple_cab, size_simple_cab);
+    fd = tvfs_open( name_simple_cab, O_RDONLY|O_BINARY, 0 );
+    /* Create virtual cabinet and open it - Modes 0,1,2 */
+
+    ok( FDIIsCabinet( hfdi_simple, fd, &fdi_cabinfo_simple) == TRUE,
+    "FDIIsCabinet failed!\n");
+    /* Check that is is recognized as a cabinet file - Modes 0,1,2 */
+    
+    ok3( fdi_cabinfo_simple.cbCabinet == size_simple_cab, 
+	"cbCabinet is wrong, is %d, should be %d.\n",
+	 fdi_cabinfo_simple.cbCabinet, size_simple_cab);
+    ok2( fdi_cabinfo_simple.cFolders == 1, "cFolders is wrong, is %d, should be 1.\n", fdi_cabinfo_simple.cFolders );
+    ok2( fdi_cabinfo_simple.cFiles == 1, "cFiles is wrong, is %d, should be 1.\n", fdi_cabinfo_simple.cFiles );
+    ok2( fdi_cabinfo_simple.setID == 0, "setID is wrong, is %d, should be 0.\n", fdi_cabinfo_simple.setID );
+    ok2( fdi_cabinfo_simple.iCabinet == 0, "iCabinet is wrong, is %d, should be 0.\n", fdi_cabinfo_simple.iCabinet );
+    ok2( fdi_cabinfo_simple.fReserve == 0, "fReserve is wrong, is %d, should be 0.\n", fdi_cabinfo_simple.fReserve );
+    ok2( fdi_cabinfo_simple.hasprev == 0, "hasprev is wrong, is %d, should be 0.\n", fdi_cabinfo_simple.hasprev );
+    ok2( fdi_cabinfo_simple.hasnext == 0, "hasnext is wrong, is %d, should be 0.\n", fdi_cabinfo_simple.hasnext );
+    /* Check all the fields of the Cabinet Info struct for validity - Modes 0,1,2 */ 
+    
+    tvfs_close(fd);
+    /* close the file handler - Modes 0,1,2 */
+        
+    FDICopy(hfdi_simple, "simple.cab", "", 0, notification_function, NULL,NULL);
+    switch (mode) {
+    case TT_NORMAL:
+        result = tvfs_compare(name_simple_txt, file_simple_txt, size_simple_txt);
+        ok2( result == 0, "File %s compare failed!\n",name_simple_txt);          
+	break;
+    case TT_FULL_DISK:
+        ok3( error_structure.erfOper == FDIERROR_TARGET_FILE,
+		 "erfOper is wrong, is %d, should be %d.\n",
+		 error_structure.erfOper, FDIERROR_TARGET_FILE);
+	break;
+    case TT_NO_FILE:
+        ok3( error_structure.erfOper == FDIERROR_CABINET_NOT_FOUND,
+		 "erfOper is wrong, is %d, should be %d.\n",
+		 error_structure.erfOper, FDIERROR_CABINET_NOT_FOUND);
+	break;
+    }
+    /* Check that file(s) were extracted correctly - Mode 0 */ 
+    /* Check that it was recognized as 'no space to write' - Mode 1 */
+    /* Check that it was recognized as 'cabinet not found' - Mode 2 */
+    
+    ok(FDIDestroy(hfdi_simple), "FDIDestroy failed!\n");  
+
+    tvfs_free();
+}
+
+static void TestCorrupt(void)
+{
+    int result, fd;
+    FDICABINETINFO  fdi_cabinfo_corrupt;
+    static HFDI hfdi_corrupt;
+    ERF error_structure;
+    const char *name_corrupt_cab = "corrupt.cab";
+    static char file_corrupt_cab[65536];
+    int size_corrupt_cab = sizeof(file_simple_cab);
+
+/*  This cabinet is a copy of simple.cab, with a few bytes modified to make it an invalid cabinet file. 
+    The copy is created dynamically to avoid code bloat. The memcpy call and 'corruption' occurs in cabinet_fdi.c 
+    This cabinet is _specifically designed_ to pass FDIIsCabinet but fail on extraction */
+    trace("TestCorrupt\n");
+    
+    /* SPECIAL TO CORRUPT.CAB -- copies simple.cab and corrupts it */
+    memcpy(file_corrupt_cab,file_simple_cab,size_simple_cab);
+    file_corrupt_cab[50]=0xFF;
+    file_corrupt_cab[100]=0xFF;    
+    
+    hfdi_corrupt = FDICreate(
+        my_malloc,
+        my_free, 
+        tvfs_open, tvfs_read, tvfs_write, tvfs_close, tvfs_lseek,
+        cpuUNKNOWN,
+        &error_structure
+    );
+
+    ok2(hfdi_corrupt != NULL,"FDICreate failed! erfOper=%d\n",error_structure.erfOper);  
+
+    tvfs_create( name_corrupt_cab, file_corrupt_cab, size_corrupt_cab);
+    fd = tvfs_open( (char *) name_corrupt_cab, O_RDONLY|O_BINARY, 0 );
+    /* Create virtual cabinet and open it */
+
+    ok( FDIIsCabinet( hfdi_corrupt, fd, &fdi_cabinfo_corrupt) == TRUE,
+    "FDIIsCabinet failed!\n");
+    /* Check that is is recognized as a cabinet file */
+    
+    ok3( fdi_cabinfo_corrupt.cbCabinet == size_corrupt_cab, 
+	"cbCabinet is wrong, is %d, should be %d.\n",
+	 fdi_cabinfo_corrupt.cbCabinet, size_corrupt_cab);
+    ok2( fdi_cabinfo_corrupt.cFolders == 1, "cFolders is wrong, is %d, should be 1.\n", fdi_cabinfo_corrupt.cFolders );
+    ok2( fdi_cabinfo_corrupt.cFiles == 1, "cFiles is wrong, is %d, should be 1.\n", fdi_cabinfo_corrupt.cFiles );
+    ok2( fdi_cabinfo_corrupt.setID == 0, "setID is wrong, is %d, should be 0.\n", fdi_cabinfo_corrupt.setID );
+    ok2( fdi_cabinfo_corrupt.iCabinet == 0, "iCabinet is wrong, is %d, should be 0.\n", fdi_cabinfo_corrupt.iCabinet );
+    ok2( fdi_cabinfo_corrupt.fReserve == 0, "fReserve is wrong, is %d, should be 0.\n", fdi_cabinfo_corrupt.fReserve );
+    ok2( fdi_cabinfo_corrupt.hasprev == 0, "hasprev is wrong, is %d, should be 0.\n", fdi_cabinfo_corrupt.hasprev );
+    ok2( fdi_cabinfo_corrupt.hasnext == 0, "hasnext is wrong, is %d, should be 0.\n", fdi_cabinfo_corrupt.hasnext );
+    /* Check all the fields of the Cabinet Info struct for validity */ 
+    
+    tvfs_close(fd);
+    /* close the file handler */
+        
+    FDICopy(hfdi_corrupt,
+        "corrupt.cab",
+        "",
+        0,
+        notification_function,
+        NULL,
+        NULL);
+    ok2( error_structure.erfOper == FDIERROR_CORRUPT_CABINET, "erfOper is wrong, is %d, should be 4.\n", error_structure.erfOper);
+    
+    result = tvfs_compare(name_simple_txt, file_simple_txt, size_simple_txt);
+    ok2( result, "Wrote %s from a corrupt cabinet - incorrect behavior!\n",name_simple_txt);    
+    
+    ok(FDIDestroy(hfdi_corrupt), "FDIDestroy failed!\n");  
+
+    tvfs_free();
+}
+
+static void TestNotACab(void)
+{
+    int result, fd;
+    FDICABINETINFO  fdi_cabinfo_notacab;
+    static HFDI hfdi_notacab;
+    ERF error_structure;
+
+    trace("TestNotACab\n");
+    
+    hfdi_notacab = FDICreate(
+        my_malloc,
+        my_free, 
+        tvfs_open, tvfs_read, tvfs_write, tvfs_close, tvfs_lseek,
+        cpuUNKNOWN,
+        &error_structure
+    );
+
+    ok2(hfdi_notacab != NULL,"FDICreate failed! erfOper=%d\n",error_structure.erfOper);  
+
+    tvfs_create( name_simple_txt, file_simple_txt, size_simple_txt);
+    fd = tvfs_open( name_simple_txt, O_RDONLY|O_BINARY, 0 );
+    /* Create virtual cabinet and open it */
+
+    ok( FDIIsCabinet( hfdi_notacab, fd, &fdi_cabinfo_notacab) == FALSE,
+    "FDIIsCabinet failed!\n");
+    /* Check that is is recognized as a FALSE cabinet file */
+    
+    FDICopy(hfdi_notacab,
+        "simple.txt",
+        "",
+        0,
+        notification_function,
+        NULL,
+        NULL);
+    ok3( error_structure.erfOper == FDIERROR_NOT_A_CABINET,
+	 "erfOper is wrong, is %d, should be %d.\n",
+	 error_structure.erfOper, FDIERROR_NOT_A_CABINET);
+
+    ok(FDIDestroy(hfdi_notacab), "FDIDestroy failed!\n");  
+
+    tvfs_free();
+}
+
+START_TEST(cabinet_fdi)
+{
+    TestConstant();
+    TestSimple(TT_NORMAL);
+    TestSimple(TT_FULL_DISK);
+    TestSimple(TT_NO_FILE);
+    TestCorrupt();
+    TestNotACab();
+}
diff -Naur oldwine/dlls/cabinet/tests/genfiles.sh wine/dlls/cabinet/tests/genfiles.sh
--- oldwine/dlls/cabinet/tests/genfiles.sh	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/genfiles.sh	Wed May 11 10:28:31 2005
@@ -0,0 +1,33 @@
+#!/bin/sh
+# Generate test archives using cabarc.exe (Windows Cabinet SDK/bin)
+# This is run just once, and generates the file cabinet_files.h,
+# which is then checked into CVS forever.
+# It is here just in case we want to add more test files later.
+# Copyright 2005 Dan Kegel, Rizwan Kassim; LGPL
+
+# remove "wine" before command calls if you're running on Windows
+
+set -ex
+
+# First, get cabinet SDK
+# You might need to download it by hand from ttp://support.microsoft.com/?id=310618
+test -f cabsdk.exe || wget -c http://download.microsoft.com/download/platformsdk/cab/2.0/w98nt42kmexp/en-us/cabsdk.exe
+
+# unpack it (handily, it's a zip file)
+mkdir cabsdk
+cd cabsdk
+unzip ../cabsdk.exe
+cd ..
+chmod 744 cabsdk/BIN/CABARC.EXE
+
+# Simple archive, just one 42 byte file
+echo 'So long, and thanks for all the fish.....' > simple.txt
+wine cabsdk/BIN/CABARC.EXE N simple.cab simple.txt
+
+# Blow away cabinet SDK
+rm -rf cabsdk 
+
+# Pack source files and archives into hex arrays
+perl ../../../tools/chexify.pl simple.txt txt simple.cab  > simplecab.h
+
+rm -fr simple.cab
diff -Naur oldwine/dlls/cabinet/tests/simplecab.h wine/dlls/cabinet/tests/simplecab.h
--- oldwine/dlls/cabinet/tests/simplecab.h	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/simplecab.h	Wed May 11 10:28:31 2005
@@ -0,0 +1,21 @@
+static char name_simple_txt[] = "simple.txt";
+static char file_simple_txt[] = {
+	0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 
+	0x6e, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 
+	0x66, 0x69, 0x73, 0x68, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x0a
+};
+static int size_simple_txt = sizeof(file_simple_txt);
+
+
+static char name_simple_cab[] = "simple.cab";
+static char file_simple_cab[] = {
+	0x4d, 0x53, 0x43, 0x46, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x32, 0x0c, 0x0c, 0x20, 0x00, 0x73, 0x69, 0x6d, 0x70, 
+	0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x9e, 0x7f, 0x24, 0xf5, 0x2a, 0x00, 0x2a, 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, 0x40, 0x80, 0x0b, 0x00
+};
+static int size_simple_cab = sizeof(file_simple_cab);
diff -Naur oldwine/dlls/cabinet/tests/standalone.h wine/dlls/cabinet/tests/standalone.h
--- oldwine/dlls/cabinet/tests/standalone.h	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/standalone.h	Wed May 11 13:31:24 2005
@@ -0,0 +1,49 @@
+/* Lightweight version of wine/test.h for use when compiling tests
+ * outside the wine source tree
+ *
+ * Implements ok(condition, fmt, ...) in a hacky way, by
+ * defining one version per possible number of parameters.
+ * Implements a no-op version of todo_wine.
+ * Implements a hacky version of START_TEST().
+ * Implements trace() properly.
+ */
+
+#include <assert.h> 
+#include <stdarg.h> 
+#include <stdio.h> 
+
+#define START_TEST(name) main(int argc, char **argv)
+
+/* If you haven't seen the do ... while (0) idiom before,
+ * it's the only way in C to do a multi-statement macro
+ * that acts like a single statement.  This is important
+ * for when the macro is invoked inside an if without braces.
+ */
+
+#define ok(condition, msg)    \
+    do { if(!(condition)) {  \
+        fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__); \
+    exit(1);    \
+    } } while(0)
+
+#define ok2(condition, msg, arg) \
+    do { if(!(condition)) {  \
+        fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__, arg); \
+    exit(1);    \
+    } } while(0)
+
+#define ok3(condition, msg, arg1, arg2) \
+    do { if(!(condition)) {  \
+        fprintf(stderr,"failed at %d, msg:" msg "\n",__LINE__, arg1, arg2); \
+    exit(1);    \
+    } } while(0)
+
+#define todo_wine
+
+static void trace(const char *s, ...)
+{
+    va_list ellipsis;
+    va_start (ellipsis, s);
+    vprintf(s, ellipsis);
+    va_end(ellipsis);
+}
diff -Naur oldwine/dlls/cabinet/tests/tvfs.c wine/dlls/cabinet/tests/tvfs.c
--- oldwine/dlls/cabinet/tests/tvfs.c	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/tvfs.c	Wed May 11 13:05:04 2005
@@ -0,0 +1,336 @@
+/*--------------------------------------------------------------------------
+Trivial virtual file system for cabinet conformance test.
+(C) 2005 Dan Kegel and Rizwan Kassim
+LGPL License
+--------------------------------------------------------------------------*/
+
+#include "tvfs.h"
+#include <string.h>
+
+#define MAXFILES 20
+#define MAXHANDLES 20
+#define MAXFNAME 255
+#define MAXFLEN 65536*2
+
+#include <fcntl.h>
+#include <stdlib.h> 
+#include <stdio.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifndef _O_BINARY
+#define _O_BINARY 0
+#endif
+
+/*
+#define TVFS_MAIN 
+*/
+#include <errno.h>
+
+#ifndef STANDALONE
+#include "wine/test.h"
+#define ok2 ok
+#else
+#include "standalone.h"
+#undef START_TEST
+#endif 
+
+struct tvfs_file {
+    char fname[MAXFNAME];
+    int bytes_used;
+    char buf[MAXFLEN];
+};
+static struct tvfs_file *files[MAXFILES];
+
+struct tvfs_fcb {
+    int pos;
+    int inode;
+};
+static struct tvfs_fcb *handles[MAXHANDLES];
+
+int nhandles = 0;
+int nfiles = 0;
+
+/* tvfs_create does NOT correspond to _creat - it is an internal function
+use to put a file directly into our virtual file system. */
+
+int tvfs_create(const char *fname, const char *buf, int len)
+{
+    int inode;
+    struct tvfs_file *f;
+
+/*    trace("tvfs_create called with %s, %d, %d\n", fname, buf, len); */
+    
+    if (nfiles >= MAXFILES)
+        return -1;
+    inode = nfiles++;
+
+    f = malloc(sizeof(struct tvfs_file));
+    strcpy(f->fname, fname);
+    f->bytes_used = len;
+
+    if (buf)
+        memcpy(f->buf, buf, len);
+    
+    files[inode] = f;
+    return inode;
+}
+
+int tvfs_open(char *fname, int flags, int mode)
+{
+    /* mode and flags are not handled */
+    int h;
+    int inode;
+    struct tvfs_fcb *handler;
+    
+/*    trace("tvfs_open called with %s, %d, %d\n", fname, flags, mode); */
+
+    /* Existing file? */
+    for (inode=0; inode<nfiles; inode++) {
+        if (!files[inode])
+            continue;
+        if (!strcmp(files[inode]->fname, fname))
+            break;    
+    }
+    
+    if (inode == nfiles) {
+        /* File did not exist */
+        if ((flags & O_CREAT) == 0) {
+            /* ENOENT */
+            trace("tvfs_open returning -1\n");
+        return -1;
+        }
+
+        inode = tvfs_create(fname, 0, 0);
+    }
+
+    handler = malloc(sizeof(struct tvfs_fcb));
+    handler->inode = inode;
+    handler->pos=0;
+    h = nhandles++;
+    handles[h] = handler;
+    
+/*    trace("tvfs_open returning with %d\n", h); */
+    
+    return h;
+}
+
+int tvfs_open_missing(char *fname, int flags, int mode)
+{
+    /* fake, 'file not found' */
+    errno = ENOENT;
+    return -1;
+}
+
+unsigned int tvfs_read(int h, void *buf, unsigned int len)
+{
+    int inode = handles[h]->inode;
+    int pos = handles[h]->pos;
+    int size = files[inode]->bytes_used;
+
+/*    trace("tvfs_read called with %d, %d, %d\n", h, buf, len); */
+    
+    /* Edge Case 1 : Request beyond boundary of file */
+    if (pos + len > size) {
+        len = size-pos;
+    }
+    
+    memcpy(buf, files[inode]->buf+pos, len);
+    handles[h]->pos += len;
+
+    return len;
+}
+
+void tvfs_free()
+{
+    int inode;
+    int handle;
+
+/*    trace("tvfs_free\n"); */
+    
+    nfiles=0;
+    nhandles=0;
+
+    for (inode=0; inode<nfiles; inode++) {
+        if (!files[inode])
+            continue;
+        free(files[inode]);
+        }
+
+    for (handle=0; handle<nhandles; handle++) {
+        if (!handles[handle])
+            continue;
+        free(handles[handle]);
+    }
+    
+}
+
+/* Compare given file with given contents, return 0 on equal, else nonzero */
+int tvfs_compare(const char *fname, const char *buf, int len)
+{
+    int inode;
+    
+    for (inode=0; inode<nfiles; inode++) {
+        if (!files[inode])
+            continue;
+        if (!strcmp(files[inode]->fname, fname))
+        break;
+    }    
+    
+    if (inode == nfiles) {
+        /* File did not exist */
+        return -1;
+    }
+
+    return (memcmp(files[inode]->buf,buf,len));
+    /* does not check for out of bound */
+}
+
+long tvfs_lseek(int h, long whence, int whither )
+{
+    int inode = handles[h]->inode;
+    int size = files[inode]->bytes_used;  
+/*    trace("tvfs_lseek called with %d, %d, %d\n", h, whither, whence); */
+    
+/*  if (whence > size) 
+    whence = size;*/
+/*  Legit lseek does NOT do boundary checking */    
+    
+    switch(whither) {
+        case SEEK_SET: {
+            handles[h]->pos = whence;
+            break;
+        }
+        case SEEK_CUR: {
+            handles[h]->pos += whence;
+            break;
+        }
+        case SEEK_END: {
+            handles[h]->pos = size+whence;
+            break;
+        }
+        case 5: {
+            handles[h]->pos = size+whence;
+            break;
+        }    
+        default:
+        {
+            trace("lseek was called with an invalid whither %d\n",whither);
+            return -1;
+        }
+    }
+    return handles[h]->pos;
+  }
+
+int tvfs_close(int h)
+{
+    int inode = handles[h]->inode;
+/*    trace("tvfs_close called with %d\n", h); */
+    if (!files[inode]) {
+        return -1;
+    }
+    free(handles[h]);
+    /* Currently does NOT enabled open to reuse this handle */
+    return 0;
+}
+ 
+unsigned int tvfs_write(int h, void *buf, unsigned int len)
+{
+    int inode = handles[h]->inode;
+    int pos = handles[h]->pos;
+/*    trace("tvfs_write called with %d, %d, %d\n", h, buf, len); */
+    memcpy(files[inode]->buf+pos, buf, len);
+    files[inode]->bytes_used += len;
+    handles[h]->pos += len;
+ 
+    return len;
+    /* return -1 to simulate diskfull or some other error */
+}
+
+unsigned int tvfs_write_full(int h, void *buf, unsigned int len) 
+{
+    errno = ENOSPC;
+    return -1;
+}
+    
+    
+START_TEST(tvfs){
+   printf("dummy!");
+}
+  
+
+#ifdef TVFS_MAIN
+
+const static char name_test_txt[] = "test.txt";
+const static char file_test_txt[] = "This is a test. Don't Panic!";
+const static int size_test_txt = sizeof(file_test_txt);
+
+/* If TVFSMain is defined, this compiles a test of the TVFS suite */
+main()
+{
+    int result;
+    int active_handler;
+
+    char *filebuf;
+    
+    char dummy_filename[] = "dummy.txt";
+    char bad_filename[] = "chicken.txt";
+
+    filebuf = malloc(MAXFLEN);
+    
+    trace("Testing TVFS implementation, creating %s\n",name_test_txt);
+    result = tvfs_create( dummy_filename, file_test_txt, size_test_txt);
+    result = tvfs_create( name_test_txt, file_test_txt,size_test_txt); 
+    trace("Created virtual file with inode %d\n",result);
+    
+    trace("Attempting to open non-existent file\n");
+    result = tvfs_open(bad_filename, _O_BINARY, 0 ); 
+    trace("Result code %d\n",result); 
+    trace("Attempting to open existent file\n");    
+    result = tvfs_open(name_test_txt, _O_BINARY, 0 );
+    trace("Result code %d\n",result); 
+
+    active_handler = result;
+
+    memset (filebuf,0,MAXFLEN);
+
+    trace("Testing reading from file %s\n",name_test_txt);
+    result = tvfs_read(active_handler, filebuf, 9);
+    trace("Read _%s_\n", filebuf);
+    if ( strcmp(filebuf,"This is a")) 
+    trace("File read check failed!\n");    
+
+    trace("Testing sequential reading from file %s\n",name_test_txt);
+    result = tvfs_read(active_handler, filebuf, 12);
+    trace("Read _%s_\n", filebuf);
+    if ( strcmp(filebuf," test. Don't")) 
+    trace("File read check failed!\n");
+    
+    trace("Testing edge reading from file %s\n",name_test_txt);
+    result = tvfs_read(active_handler, filebuf, 42);
+    trace("Read %d bytes - _%s_\n", result, filebuf);
+    if ( result != 8 ) 
+    trace("File read check failed!\n");
+    
+    trace("Testing direct file compare and lseek of %s\n", name_test_txt);
+    trace("Seeking to 0 (not needed) - ");
+    tvfs_lseek( active_handler, SEEK_SET, 0);
+    trace("Comparing file\n");
+    result = tvfs_compare( name_test_txt , file_test_txt, size_test_txt);
+    if (result)
+    trace ("File compare failed!\n"); 
+    
+    /* Does not test writing */
+    
+    trace("Closing %s\n",name_test_txt);
+    tvfs_close(active_handler);
+    if (result)
+    trace ("File close failed!\n");
+    
+    tvfs_free();
+    free(filebuf);
+    
+}
+
+#endif
diff -Naur oldwine/dlls/cabinet/tests/tvfs.h wine/dlls/cabinet/tests/tvfs.h
--- oldwine/dlls/cabinet/tests/tvfs.h	Wed Dec 31 16:00:00 1969
+++ wine/dlls/cabinet/tests/tvfs.h	Wed May 11 11:57:15 2005
@@ -0,0 +1,36 @@
+/*--------------------------------------------------------------------------
+Trivial virtual file system for cabinet conformance test.
+
+Provides versions of the filesystem calls needed by cabinet:
+open, read, write, lseek, close.  Each returns the same
+return values as the corresponding _open, _read, _write, _lseek, _close
+calls in Win32, i.e. on error, they return -1,
+and on success, open returns a file handle,
+read and write return # of bytes transferred,
+seek returns the position,
+and close returns 0.
+
+Also provides functions for creating whole files from binary arrays,
+and comparing whole files to binary arrays.
+
+--------------------------------------------------------------------------*/
+
+#ifndef tvfs_h
+#define tvfs_h
+
+int tvfs_open(char *fname, int flags, int mode);
+unsigned int tvfs_read(int h, void *buf, unsigned int len);
+unsigned int tvfs_write(int h, void *buf, unsigned int len);
+int tvfs_close(int h);
+long tvfs_lseek(int h,  long whence, int whither);
+
+/* Create given file with given contents, return inode number or -1 on fail */
+int tvfs_create(const char *fname, const char *buf, int len);
+
+/* Compare given file with given contents, return 0 on equal, else nonzero */
+int tvfs_compare(const char *fname, const char *buf, int len);
+
+void tvfs_free();
+int tvfs_open_missing(char *fname, int flags, int mode);
+unsigned int tvfs_write_full(int h, void *buf, unsigned int len);
+#endif
