lz32/tests: More checks for various LZOpenFile[AW] operations on existing files.
[wine] / dlls / lz32 / tests / lzexpand_main.c
1 /*
2  * Unit test suite for lz32 functions
3  *
4  * Copyright 2004 Evan Parry, Daniel Kegel
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <stdlib.h>
25 #include <winerror.h>
26 #include <lzexpand.h>
27
28 #include "wine/test.h"
29
30 /* Compressed file names end with underscore. */
31 static char filename [] = "testfile.xxx";
32 static char filename_[] = "testfile.xx_";
33 static WCHAR filenameW [] = {'t','e','s','t','f','i','l','e','.','x','x','x',0};
34 static WCHAR filenameW_[] = {'t','e','s','t','f','i','l','e','.','x','x','_',0};
35
36 static char dotless [] = "dotless";
37 static char dotless_[] = "dotless._";
38 static WCHAR dotlessW [] = {'d','o','t','l','e','s','s', 0};
39 static WCHAR dotlessW_[] = {'d','o','t','l','e','s','s','.','_', 0};
40
41 static char extless [] = "extless.";
42 static char extless_[] = "extless._";
43 static WCHAR extlessW [] = {'e','x','t','l','e','s','s','.', 0};
44 static WCHAR extlessW_[] = {'e','x','t','l','e','s','s','.','_', 0};
45
46 static char _terminated [] = "_terminated.xxxx_";
47 static char _terminated_[] = "_terminated.xxxx_";
48 static WCHAR _terminatedW [] = {'_','t','e','r','m','i','n','a','t','e','d','.','x','x','x','x','_', 0};
49 static WCHAR _terminatedW_[] = {'_','t','e','r','m','i','n','a','t','e','d','.','x','x','x','x','_', 0};
50
51 static char filename2[] = "testfile.yyy";
52
53 /* This is the hex string representation of the file created by compressing
54    a simple text file with the contents "This is a test file."
55  
56    The file was created using COMPRESS.EXE from the Windows Server 2003
57    Resource Kit from Microsoft.  The resource kit was retrieved from the
58    following URL:  
59
60    http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
61  */
62 static const unsigned char compressed_file[] = 
63   {0x53,0x5A,0x44,0x44,0x88,0xF0,0x27,0x33,0x41,
64    0x74,0x75,0x14,0x00,0x00,0xDF,0x54,0x68,0x69,
65    0x73,0x20,0xF2,0xF0,0x61,0x20,0xFF,0x74,0x65,
66    0x73,0x74,0x20,0x66,0x69,0x6C,0x03,0x65,0x2E};
67 static const DWORD compressed_file_size = sizeof(compressed_file);
68
69 static const char uncompressed_data[] = "This is a test file.";
70 static const DWORD uncompressed_data_size = sizeof(uncompressed_data) - 1;
71
72 static char *buf;
73
74 static void full_file_path_name_in_a_CWD(const char *src, char *dst, BOOL expect_short)
75 {
76   DWORD retval;
77   char shortname[MAX_PATH];
78
79   retval = GetCurrentDirectoryA(MAX_PATH, dst);
80   ok(retval > 0, "GetCurrentDirectoryA returned %ld, GLE=0x%lx\n", 
81      retval, GetLastError());
82   lstrcatA(dst, "\\");
83   lstrcatA(dst, src);
84   if(expect_short) 
85   {
86     memcpy(shortname, dst, MAX_PATH);
87     GetShortPathName(shortname, dst, MAX_PATH-1);
88   }
89 }
90
91 static void create_file(char *fname)
92 {
93   INT file;
94   OFSTRUCT ofs;
95   DWORD retval;
96
97   file = LZOpenFileA(fname, &ofs, OF_CREATE);
98   ok(file >= 0, "LZOpenFileA failed on creation\n");
99   LZClose(file);
100   retval = GetFileAttributesA(fname);
101   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA('%s'): error %ld\n", ofs.szPathName, GetLastError());
102 }
103
104 static void delete_file(char *fname)
105 {
106   INT file;
107   OFSTRUCT ofs;
108   DWORD retval;
109
110   file = LZOpenFileA(fname, &ofs, OF_DELETE);
111   ok(file >= 0, "LZOpenFileA failed on delete\n");
112   LZClose(file);
113   retval = GetFileAttributesA(fname);
114   ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file ('%s')\n", ofs.szPathName);
115 }
116
117 static void test_LZOpenFileA_existing_compressed(void)
118 {
119   OFSTRUCT test;
120   INT file;
121   char expected[MAX_PATH];
122   char short_expected[MAX_PATH];
123   char filled_0xA5[OFS_MAXPATHNAME];
124
125   /* Try to open existing compressed files: */
126   create_file(filename_);
127   create_file(dotless_);
128   create_file(extless_);
129   create_file(_terminated_);
130
131   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
132   memset(&test, 0xA5, sizeof(test));
133   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
134   SetLastError(0xfaceabee);
135
136   /* a, using 8.3-conformant file name. */
137   file = LZOpenFileA(filename, &test, OF_EXIST);
138   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
139      check for the file "foo.xx_" and open that -- at least on some
140      operating systems.  Doesn't seem to on my copy of Win98.   
141    */
142   if(file != LZERROR_BADINHANDLE) {
143     ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", filename);
144     ok(test.cBytes == sizeof(OFSTRUCT), 
145        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
146     ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n", 
147        test.nErrCode);
148     ok(lstrcmpA(test.szPathName, expected) == 0, 
149        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
150        test.szPathName, expected);
151     LZClose(file);
152   } else { /* Win9x */
153     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
154        "GetLastError() returns %ld\n", GetLastError());
155     ok(test.cBytes == 0xA5, 
156        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
157     ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
158        "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
159     ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 
160        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
161        test.szPathName, filled_0xA5);
162   }
163
164   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
165   memset(&test, 0xA5, sizeof(test));
166   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
167   SetLastError(0xfaceabee);
168
169   /* b, using dotless file name. */
170   file = LZOpenFileA(dotless, &test, OF_EXIST);
171   if(file != LZERROR_BADINHANDLE) {
172     ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", dotless);
173     ok(test.cBytes == sizeof(OFSTRUCT), 
174        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
175     ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n", 
176        test.nErrCode);
177     ok(lstrcmpA(test.szPathName, expected) == 0, 
178        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
179        test.szPathName, expected);
180     LZClose(file);
181   } else { /* Win9x */
182     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
183        "GetLastError() returns %ld\n", GetLastError());
184     todo_wine
185     ok(test.cBytes == 0xA5, 
186        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
187     ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
188        "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
189     todo_wine
190     ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 
191        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
192        test.szPathName, filled_0xA5);
193   }
194
195   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
196   memset(&test, 0xA5, sizeof(test));
197   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
198   SetLastError(0xfaceabee);
199
200   /* c, using extensionless file name. */
201   file = LZOpenFileA(extless, &test, OF_EXIST);
202   if(file != LZERROR_BADINHANDLE) {
203     ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", extless);
204     ok(test.cBytes == sizeof(OFSTRUCT), 
205        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
206     ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n", 
207        test.nErrCode);
208     ok(lstrcmpA(test.szPathName, expected) == 0, 
209        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
210        test.szPathName, expected);
211     LZClose(file);
212   } else { /* Win9x */
213     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
214        "GetLastError() returns %ld\n", GetLastError());
215     ok(test.cBytes == 0xA5, 
216        "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
217     ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
218        "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
219     ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, 
220        "LZOpenFileA returned '%s', but was expected to return '%s'\n", 
221        test.szPathName, filled_0xA5);
222   }
223
224   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
225   memset(&test, 0xA5, sizeof(test));
226   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
227   full_file_path_name_in_a_CWD(_terminated_, short_expected, TRUE);
228
229   /* d, using underscore-terminated file name. */
230   file = LZOpenFileA(_terminated, &test, OF_EXIST);
231   ok(file >= 0, "LZOpenFileA failed on switching to a compressed file name\n");
232   ok(test.cBytes == sizeof(OFSTRUCT), 
233      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
234   ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n", 
235      test.nErrCode);
236   ok(lstrcmpA(test.szPathName, expected) == 0 ||
237      lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
238      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n", 
239      test.szPathName, expected, short_expected);
240   LZClose(file);
241
242   delete_file(filename_);
243   delete_file(dotless_);
244   delete_file(extless_);
245   delete_file(_terminated_);
246 }
247
248 static void test_LZOpenFileA_nonexisting_compressed(void)
249 {
250   OFSTRUCT test;
251   INT file;
252   char expected[MAX_PATH];
253   char filled_0xA5[OFS_MAXPATHNAME];
254
255   /* Try to open nonexisting compressed files: */
256   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
257   memset(&test, 0xA5, sizeof(test));
258   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
259   SetLastError(0xfaceabee);
260
261   /* a, using 8.3-conformant file name. */
262   file = LZOpenFileA(filename, &test, OF_EXIST);
263   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
264      check for the file "foo.xx_" and open that -- at least on some
265      operating systems.  Doesn't seem to on my copy of Win98.   
266    */
267   ok(file == LZERROR_BADINHANDLE, 
268      "LZOpenFileA succeeded on nonexistent file\n");
269   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
270      "GetLastError() returns %ld\n", GetLastError());
271   todo_wine
272   ok(test.cBytes == 0xA5, 
273      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
274   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
275      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
276   ok(lstrcmpA(test.szPathName, expected) == 0 ||
277      strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
278      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n", 
279      test.szPathName, expected, filled_0xA5);
280
281   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
282   memset(&test, 0xA5, sizeof(test));
283   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
284   SetLastError(0xfaceabee);
285
286   /* b, using dotless file name. */
287   file = LZOpenFileA(dotless, &test, OF_EXIST);
288   ok(file == LZERROR_BADINHANDLE, 
289      "LZOpenFileA succeeded on nonexistent file\n");
290   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
291      "GetLastError() returns %ld\n", GetLastError());
292   todo_wine
293   ok(test.cBytes == 0xA5, 
294      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
295   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
296      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
297   ok(lstrcmpA(test.szPathName, expected) == 0 ||
298      strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
299      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n", 
300      test.szPathName, expected, filled_0xA5);
301
302   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
303   memset(&test, 0xA5, sizeof(test));
304   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
305   SetLastError(0xfaceabee);
306
307   /* c, using extensionless file name. */
308   file = LZOpenFileA(extless, &test, OF_EXIST);
309   ok(file == LZERROR_BADINHANDLE, 
310      "LZOpenFileA succeeded on nonexistent file\n");
311   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
312      "GetLastError() returns %ld\n", GetLastError());
313   todo_wine
314   ok(test.cBytes == 0xA5, 
315      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
316   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
317      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
318   ok(lstrcmpA(test.szPathName, expected) == 0 ||
319      strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
320      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n", 
321      test.szPathName, expected, filled_0xA5);
322
323   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
324   memset(&test, 0xA5, sizeof(test));
325   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
326   SetLastError(0xfaceabee);
327
328   /* d, using underscore-terminated file name. */
329   file = LZOpenFileA(_terminated, &test, OF_EXIST);
330   ok(file == LZERROR_BADINHANDLE, 
331      "LZOpenFileA succeeded on nonexistent file\n");
332   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
333      "GetLastError() returns %ld\n", GetLastError());
334   todo_wine
335   ok(test.cBytes == 0xA5, 
336      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
337   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
338      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
339   ok(lstrcmpA(test.szPathName, expected) == 0 ||
340      strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
341      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n", 
342      test.szPathName, expected, filled_0xA5);
343 }
344
345 static void test_LZOpenFileA(void)
346 {
347   OFSTRUCT test;
348   DWORD retval;
349   INT file;
350   static char badfilename_[] = "badfilename_";
351   char expected[MAX_PATH];
352
353   SetLastError(0xfaceabee);
354   /* Check for nonexistent file. */
355   file = LZOpenFileA(badfilename_, &test, OF_READ);
356   ok(file == LZERROR_BADINHANDLE, 
357      "LZOpenFileA succeeded on nonexistent file\n");
358   ok(GetLastError() == ERROR_FILE_NOT_FOUND, 
359      "GetLastError() returns %ld\n", GetLastError());
360   LZClose(file);
361
362   memset(&test, 0xA5, sizeof(test));
363   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
364
365   /* Create an empty file. */
366   file = LZOpenFileA(filename_, &test, OF_CREATE);
367   ok(file >= 0, "LZOpenFileA failed on creation\n");
368   ok(test.cBytes == sizeof(OFSTRUCT),
369      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
370   ok(test.nErrCode == ERROR_SUCCESS,
371      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
372   ok(lstrcmpA(test.szPathName, expected) == 0,
373      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
374      test.szPathName, expected);
375   LZClose(file);
376
377   retval = GetFileAttributesA(filename_);
378   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %ld\n", 
379      GetLastError());
380
381   /* Check various opening options: */
382   memset(&test, 0xA5, sizeof(test));
383
384   /* a, for reading. */
385   file = LZOpenFileA(filename_, &test, OF_READ);
386   ok(file >= 0, "LZOpenFileA failed on read\n");
387   ok(test.cBytes == sizeof(OFSTRUCT),
388      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
389   ok(test.nErrCode == ERROR_SUCCESS,
390      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
391   ok(lstrcmpA(test.szPathName, expected) == 0,
392      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
393      test.szPathName, expected);
394   LZClose(file);
395
396   memset(&test, 0xA5, sizeof(test));
397
398   /* b, for writing. */
399   file = LZOpenFileA(filename_, &test, OF_WRITE);
400   ok(file >= 0, "LZOpenFileA failed on write\n");
401   ok(test.cBytes == sizeof(OFSTRUCT),
402      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
403   ok(test.nErrCode == ERROR_SUCCESS,
404      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
405   ok(lstrcmpA(test.szPathName, expected) == 0,
406      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
407      test.szPathName, expected);
408   LZClose(file);
409
410   memset(&test, 0xA5, sizeof(test));
411
412   /* c, for reading and writing. */
413   file = LZOpenFileA(filename_, &test, OF_READWRITE);
414   ok(file >= 0, "LZOpenFileA failed on read/write\n");
415   ok(test.cBytes == sizeof(OFSTRUCT),
416      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
417   ok(test.nErrCode == ERROR_SUCCESS,
418      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
419   ok(lstrcmpA(test.szPathName, expected) == 0,
420      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
421      test.szPathName, expected);
422   LZClose(file);
423
424   memset(&test, 0xA5, sizeof(test));
425
426   /* d, for checking file existance. */
427   file = LZOpenFileA(filename_, &test, OF_EXIST);
428   ok(file >= 0, "LZOpenFileA failed on read/write\n");
429   ok(test.cBytes == sizeof(OFSTRUCT),
430      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
431   ok(test.nErrCode == ERROR_SUCCESS,
432      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
433   ok(lstrcmpA(test.szPathName, expected) == 0,
434      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
435      test.szPathName, expected);
436   LZClose(file);
437
438   memset(&test, 0xA5, sizeof(test));
439
440   /* Delete the file then make sure it doesn't exist anymore. */
441   file = LZOpenFileA(filename_, &test, OF_DELETE);
442   ok(file >= 0, "LZOpenFileA failed on delete\n");
443   ok(test.cBytes == sizeof(OFSTRUCT),
444      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
445   ok(test.nErrCode == ERROR_SUCCESS,
446      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
447   ok(lstrcmpA(test.szPathName, expected) == 0,
448      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
449      test.szPathName, expected);
450   LZClose(file);
451
452   retval = GetFileAttributesA(filename_);
453   ok(retval == INVALID_FILE_ATTRIBUTES, 
454      "GetFileAttributesA succeeded on deleted file\n");
455
456   test_LZOpenFileA_existing_compressed();
457   test_LZOpenFileA_nonexisting_compressed();
458 }
459
460 static void test_LZRead(void)
461 {
462   HANDLE file;
463   DWORD ret;
464   int cfile;
465   OFSTRUCT test;
466   BOOL retok;
467
468   /* Create the compressed file. */
469   file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
470   ok(file != INVALID_HANDLE_VALUE, "Could not create test file\n");
471   retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
472   ok( retok, "WriteFile: error %ld\n", GetLastError());
473   ok(ret == compressed_file_size, "Wrote wrong number of bytes with WriteFile?\n");
474   CloseHandle(file);
475
476   cfile = LZOpenFileA(filename_, &test, OF_READ);
477   ok(cfile > 0, "LZOpenFileA failed\n");
478
479   ret = LZRead(cfile, buf, uncompressed_data_size);
480   ok(ret == uncompressed_data_size, "Read wrong number of bytes\n");
481
482   /* Compare what we read with what we think we should read. */
483   ok(memcmp(buf, uncompressed_data, uncompressed_data_size) == 0,
484      "buffer contents mismatch\n");
485
486   todo_wine {
487      /* Wine returns the number of bytes actually read instead of an error */
488      ret = LZRead(cfile, buf, uncompressed_data_size);
489      ok(ret == LZERROR_READ, "Expected read-past-EOF to return LZERROR_READ\n");
490   }
491
492   LZClose(cfile);
493
494   ret = DeleteFileA(filename_);
495   ok(ret, "DeleteFileA: error %ld\n", GetLastError());
496 }
497
498 static void test_LZCopy(void)
499 {
500   HANDLE file;
501   DWORD ret;
502   int source, dest;
503   OFSTRUCT stest, dtest;
504   BOOL retok;
505
506   /* Create the compressed file. */
507   file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
508   ok(file != INVALID_HANDLE_VALUE, 
509      "CreateFileA: error %ld\n", GetLastError());
510   retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
511   ok( retok, "WriteFile error %ld\n", GetLastError());
512   ok(ret == compressed_file_size, "Wrote wrong number of bytes\n");
513   CloseHandle(file);
514
515   source = LZOpenFileA(filename_, &stest, OF_READ);
516   ok(source >= 0, "LZOpenFileA failed on compressed file\n");
517   dest = LZOpenFileA(filename2, &dtest, OF_CREATE);
518   ok(dest >= 0, "LZOpenFileA failed on creating new file %d\n", dest);
519
520   ret = LZCopy(source, dest);
521   ok(ret > 0, "LZCopy error\n");
522
523   LZClose(source);
524   LZClose(dest);
525
526   file = CreateFileA(filename2, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
527   ok(file != INVALID_HANDLE_VALUE,
528      "CreateFileA: error %ld\n", GetLastError());
529
530   retok = ReadFile(file, buf, uncompressed_data_size*2, &ret, 0);
531   ok( retok && ret == uncompressed_data_size, "ReadFile: error %ld\n", GetLastError());
532   /* Compare what we read with what we think we should read. */
533   ok(!memcmp(buf, uncompressed_data, uncompressed_data_size),
534      "buffer contents mismatch\n");
535   CloseHandle(file);
536
537   ret = DeleteFileA(filename_);
538   ok(ret, "DeleteFileA: error %ld\n", GetLastError());
539   ret = DeleteFileA(filename2);
540   ok(ret, "DeleteFileA: error %ld\n", GetLastError());
541 }
542
543 static void create_fileW(WCHAR *fnameW)
544 {
545   INT file;
546   OFSTRUCT ofs;
547   DWORD retval;
548
549   file = LZOpenFileW(fnameW, &ofs, OF_CREATE);
550   ok(file >= 0, "LZOpenFileW failed on creation\n");
551   LZClose(file);
552   retval = GetFileAttributesW(fnameW);
553   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesW('%s'): error %ld\n", ofs.szPathName, GetLastError());
554 }
555
556 static void delete_fileW(WCHAR *fnameW)
557 {
558   INT file;
559   OFSTRUCT ofs;
560   DWORD retval;
561
562   file = LZOpenFileW(fnameW, &ofs, OF_DELETE);
563   ok(file >= 0, "LZOpenFileW failed on delete\n");
564   LZClose(file);
565   retval = GetFileAttributesW(fnameW);
566   ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesW succeeded on deleted file ('%s')\n", ofs.szPathName);
567 }
568
569 static void test_LZOpenFileW_existing_compressed(void)
570 {
571   OFSTRUCT test;
572   INT file;
573   char expected[MAX_PATH];
574
575   /* Try to open existing compressed files: */
576   create_fileW(filenameW_);
577   create_fileW(dotlessW_);
578   create_fileW(extlessW_);
579   create_fileW(_terminatedW_);
580
581   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
582   memset(&test, 0xA5, sizeof(test));
583
584   /* a, using 8.3-conformant file name. */
585   file = LZOpenFileW(filenameW, &test, OF_EXIST);
586   /* If the file "foo.xxx" does not exist, LZOpenFileW should then
587      check for the file "foo.xx_" and open that.
588    */
589   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
590   ok(test.cBytes == sizeof(OFSTRUCT), 
591      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
592   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n", 
593      test.nErrCode);
594   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
595   ok(lstrcmpA(test.szPathName, expected) == 0, 
596      "LZOpenFileW returned '%s', but was expected to return '%s'\n", 
597      test.szPathName, expected);
598   LZClose(file);
599
600   memset(&test, 0xA5, sizeof(test));
601   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
602
603   /* b, using dotless file name. */
604   file = LZOpenFileW(dotlessW, &test, OF_EXIST);
605   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
606   ok(test.cBytes == sizeof(OFSTRUCT), 
607      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
608   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n", 
609      test.nErrCode);
610   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
611   ok(lstrcmpA(test.szPathName, expected) == 0, 
612      "LZOpenFileW returned '%s', but was expected to return '%s'\n", 
613      test.szPathName, expected);
614   LZClose(file);
615
616   memset(&test, 0xA5, sizeof(test));
617   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
618
619   /* c, using extensionless file name. */
620   file = LZOpenFileW(extlessW, &test, OF_EXIST);
621   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
622   ok(test.cBytes == sizeof(OFSTRUCT), 
623      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
624   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n", 
625      test.nErrCode);
626   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
627   ok(lstrcmpA(test.szPathName, expected) == 0, 
628      "LZOpenFileW returned '%s', but was expected to return '%s'\n", 
629      test.szPathName, expected);
630   LZClose(file);
631
632   memset(&test, 0xA5, sizeof(test));
633   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
634
635   /* d, using underscore-terminated file name. */
636   file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
637   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
638   ok(test.cBytes == sizeof(OFSTRUCT), 
639      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
640   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n", 
641      test.nErrCode);
642   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
643   ok(lstrcmpA(test.szPathName, expected) == 0, 
644      "LZOpenFileW returned '%s', but was expected to return '%s'\n", 
645      test.szPathName, expected);
646   LZClose(file);
647
648   delete_fileW(filenameW_);
649   delete_fileW(dotlessW_);
650   delete_fileW(extlessW_);
651   delete_fileW(_terminatedW_);
652 }
653
654 static void test_LZOpenFileW_nonexisting_compressed(void)
655 {
656   OFSTRUCT test;
657   INT file;
658   char expected[MAX_PATH];
659   char filled_0xA5[OFS_MAXPATHNAME];
660
661   /* Try to open nonexisting compressed files: */
662   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
663   memset(&test, 0xA5, sizeof(test));
664   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
665   SetLastError(0xfaceabee);
666
667   /* a, using 8.3-conformant file name. */
668   file = LZOpenFileW(filenameW, &test, OF_EXIST);
669   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
670      check for the file "foo.xx_" and open that -- at least on some
671      operating systems.  Doesn't seem to on my copy of Win98.   
672    */
673   ok(file == LZERROR_BADINHANDLE, 
674      "LZOpenFileW succeeded on nonexistent file\n");
675   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
676      "GetLastError() returns %ld\n", GetLastError());
677   todo_wine
678   ok(test.cBytes == 0xA5, 
679      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
680   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
681      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
682   ok(lstrcmpA(test.szPathName, expected) == 0,
683      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n", 
684      test.szPathName, expected, filled_0xA5);
685
686   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
687   memset(&test, 0xA5, sizeof(test));
688   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
689   SetLastError(0xfaceabee);
690
691   /* b, using dotless file name. */
692   file = LZOpenFileW(dotlessW, &test, OF_EXIST);
693   ok(file == LZERROR_BADINHANDLE, 
694      "LZOpenFileW succeeded on nonexistent file\n");
695   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
696      "GetLastError() returns %ld\n", GetLastError());
697   todo_wine
698   ok(test.cBytes == 0xA5, 
699      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
700   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
701      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
702   ok(lstrcmpA(test.szPathName, expected) == 0,
703      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n", 
704      test.szPathName, expected, filled_0xA5);
705
706   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
707   memset(&test, 0xA5, sizeof(test));
708   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
709   SetLastError(0xfaceabee);
710
711   /* c, using extensionless file name. */
712   file = LZOpenFileW(extlessW, &test, OF_EXIST);
713   ok(file == LZERROR_BADINHANDLE, 
714      "LZOpenFileW succeeded on nonexistent file\n");
715   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
716      "GetLastError() returns %ld\n", GetLastError());
717   todo_wine
718   ok(test.cBytes == 0xA5, 
719      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
720   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
721      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
722   ok(lstrcmpA(test.szPathName, expected) == 0,
723      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n", 
724      test.szPathName, expected, filled_0xA5);
725
726   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
727   memset(&test, 0xA5, sizeof(test));
728   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
729   SetLastError(0xfaceabee);
730
731   /* d, using underscore-terminated file name. */
732   file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
733   ok(file == LZERROR_BADINHANDLE, 
734      "LZOpenFileW succeeded on nonexistent file\n");
735   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
736      "GetLastError() returns %ld\n", GetLastError());
737   todo_wine
738   ok(test.cBytes == 0xA5, 
739      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
740   ok(test.nErrCode == ERROR_FILE_NOT_FOUND, 
741      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
742   ok(lstrcmpA(test.szPathName, expected) == 0,
743      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
744      test.szPathName, expected, filled_0xA5);
745 }
746
747 static void test_LZOpenFileW(void)
748 {
749   OFSTRUCT test;
750   DWORD retval;
751   INT file;
752   static WCHAR badfilenameW[] = {'b','a','d','f','i','l','e','n','a','m','e','.','x','t','n',0};
753   char expected[MAX_PATH];
754
755   SetLastError(0xfaceabee);
756   /* Check for nonexistent file. */
757   file = LZOpenFileW(badfilenameW, &test, OF_READ);
758   ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
759      "GetLastError() returns %ld\n", GetLastError());
760   if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
761   {
762     trace("LZOpenFileW call not implemented, skipping rest of the test\n");
763     return;
764   }
765   ok(file == LZERROR_BADINHANDLE, "LZOpenFileW succeeded on nonexistent file\n");
766   LZClose(file);
767
768   memset(&test, 0xA5, sizeof(test));
769   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
770
771   /* Create an empty file. */
772   file = LZOpenFileW(filenameW_, &test, OF_CREATE);
773   ok(file >= 0, "LZOpenFile failed on creation\n");
774   ok(test.cBytes == sizeof(OFSTRUCT),
775      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
776   ok(test.nErrCode == ERROR_SUCCESS,
777      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
778   ok(lstrcmpA(test.szPathName, expected) == 0,
779      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
780      test.szPathName, expected);
781   LZClose(file);
782
783   retval = GetFileAttributesW(filenameW_);
784   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributes: error %ld\n", 
785     GetLastError());
786
787   /* Check various opening options: */
788   memset(&test, 0xA5, sizeof(test));
789
790   /* a, for reading. */
791   file = LZOpenFileW(filenameW_, &test, OF_READ);
792   ok(file >= 0, "LZOpenFileW failed on read\n");
793   ok(test.cBytes == sizeof(OFSTRUCT),
794      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
795   ok(test.nErrCode == ERROR_SUCCESS,
796      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
797   ok(lstrcmpA(test.szPathName, expected) == 0,
798      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
799      test.szPathName, expected);
800   LZClose(file);
801
802   memset(&test, 0xA5, sizeof(test));
803
804   /* b, for writing. */
805   file = LZOpenFileW(filenameW_, &test, OF_WRITE);
806   ok(file >= 0, "LZOpenFileW failed on write\n");
807   ok(test.cBytes == sizeof(OFSTRUCT),
808      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
809   ok(test.nErrCode == ERROR_SUCCESS,
810      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
811   ok(lstrcmpA(test.szPathName, expected) == 0,
812      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
813      test.szPathName, expected);
814   LZClose(file);
815
816   memset(&test, 0xA5, sizeof(test));
817
818   /* c, for reading and writing. */
819   file = LZOpenFileW(filenameW_, &test, OF_READWRITE);
820   ok(file >= 0, "LZOpenFileW failed on read/write\n");
821   ok(test.cBytes == sizeof(OFSTRUCT),
822      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
823   ok(test.nErrCode == ERROR_SUCCESS,
824      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
825   ok(lstrcmpA(test.szPathName, expected) == 0,
826      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
827      test.szPathName, expected);
828   LZClose(file);
829
830   memset(&test, 0xA5, sizeof(test));
831
832   /* d, for checking file existance. */
833   file = LZOpenFileW(filenameW_, &test, OF_EXIST);
834   ok(file >= 0, "LZOpenFileW failed on read/write\n");
835   ok(test.cBytes == sizeof(OFSTRUCT),
836      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
837   ok(test.nErrCode == ERROR_SUCCESS,
838      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
839   ok(lstrcmpA(test.szPathName, expected) == 0,
840      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
841      test.szPathName, expected);
842   LZClose(file);
843
844   memset(&test, 0xA5, sizeof(test));
845
846   /* Delete the file then make sure it doesn't exist anymore. */
847   file = LZOpenFileW(filenameW_, &test, OF_DELETE);
848   ok(file >= 0, "LZOpenFileW failed on delete\n");
849   ok(test.cBytes == sizeof(OFSTRUCT),
850      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
851   ok(test.nErrCode == ERROR_SUCCESS,
852      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
853   ok(lstrcmpA(test.szPathName, expected) == 0,
854      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
855      test.szPathName, expected);
856   LZClose(file);
857
858   retval = GetFileAttributesW(filenameW_);
859   ok(retval == INVALID_FILE_ATTRIBUTES, 
860      "GetFileAttributesW succeeded on deleted file\n");
861
862   test_LZOpenFileW_existing_compressed();
863   test_LZOpenFileW_nonexisting_compressed();
864 }
865
866
867 START_TEST(lzexpand_main)
868 {
869   buf = malloc(uncompressed_data_size * 2);
870   test_LZOpenFileA();
871   test_LZOpenFileW();
872   test_LZRead();
873   test_LZCopy();
874   free(buf);
875 }