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.
58  */
59 static const unsigned char compressed_file[] =
60   {0x53,0x5A,0x44,0x44,0x88,0xF0,0x27,0x33,0x41,
61    0x74,0x75,0x14,0x00,0x00,0xDF,0x54,0x68,0x69,
62    0x73,0x20,0xF2,0xF0,0x61,0x20,0xFF,0x74,0x65,
63    0x73,0x74,0x20,0x66,0x69,0x6C,0x03,0x65,0x2E};
64 static const DWORD compressed_file_size = sizeof(compressed_file);
65 
66 static const char uncompressed_data[] = "This is a test file.";
67 static const DWORD uncompressed_data_size = sizeof(uncompressed_data) - 1;
68 
69 static char *buf;
70 
71 static void full_file_path_name_in_a_CWD(const char *src, char *dst, BOOL expect_short)
72 {
73   DWORD retval;
74   char shortname[MAX_PATH];
75 
76   retval = GetCurrentDirectoryA(MAX_PATH, dst);
77   ok(retval > 0, "GetCurrentDirectoryA returned %d, GLE=%d\n",
78      retval, GetLastError());
79   if(dst[retval-1] != '\\')
80     /* Append backslash only when it's missing */
81       lstrcatA(dst, "\\");
82   lstrcatA(dst, src);
83   if(expect_short)
84   {
85     memcpy(shortname, dst, MAX_PATH);
86     retval = GetShortPathNameA(shortname, dst, MAX_PATH-1);
87     ok(retval > 0, "GetShortPathNameA returned %d for '%s', GLE=%d\n",
88        retval, dst, GetLastError());
89   }
90 }
91 
92 static void create_file(char *fname)
93 {
94   INT file;
95   OFSTRUCT ofs;
96   DWORD retval;
97 
98   file = LZOpenFileA(fname, &ofs, OF_CREATE);
99   ok(file >= 0, "LZOpenFileA failed to create '%s'\n", fname);
100   LZClose(file);
101   retval = GetFileAttributesA(fname);
102   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA('%s'): error %d\n", ofs.szPathName, GetLastError());
103 }
104 
105 static void delete_file(char *fname)
106 {
107   INT file;
108   OFSTRUCT ofs;
109   DWORD retval;
110 
111   file = LZOpenFileA(fname, &ofs, OF_DELETE);
112   ok(file >= 0, "LZOpenFileA failed to delete '%s'\n", fname);
113   LZClose(file);
114   retval = GetFileAttributesA(fname);
115   ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file ('%s')\n", ofs.szPathName);
116 }
117 
118 static void test_LZOpenFileA_existing_compressed(void)
119 {
120   OFSTRUCT test;
121   INT file;
122   char expected[MAX_PATH];
123   char short_expected[MAX_PATH];
124   char filled_0xA5[OFS_MAXPATHNAME];
125 
126   /* Try to open existing compressed files: */
127   create_file(filename_);
128   create_file(dotless_);
129   create_file(extless_);
130   create_file(_terminated_);
131 
132   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
133   memset(&test, 0xA5, sizeof(test));
134   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
135   SetLastError(0xfaceabee);
136 
137   /* a, using 8.3-conformant file name. */
138   file = LZOpenFileA(filename, &test, OF_EXIST);
139   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
140      check for the file "foo.xx_" and open that -- at least on some
141      operating systems.  Doesn't seem to on my copy of Win98.
142    */
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 
153   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
154   memset(&test, 0xA5, sizeof(test));
155   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
156   SetLastError(0xfaceabee);
157 
158   /* b, using dotless file name. */
159   file = LZOpenFileA(dotless, &test, OF_EXIST);
160   ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", dotless);
161   ok(test.cBytes == sizeof(OFSTRUCT),
162      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
163   ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
164      test.nErrCode);
165   ok(lstrcmpA(test.szPathName, expected) == 0,
166      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
167      test.szPathName, expected);
168   LZClose(file);
169 
170   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
171   memset(&test, 0xA5, sizeof(test));
172   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
173   SetLastError(0xfaceabee);
174 
175   /* c, using extensionless file name. */
176   file = LZOpenFileA(extless, &test, OF_EXIST);
177   ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", extless);
178   ok(test.cBytes == sizeof(OFSTRUCT),
179      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
180   ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
181      test.nErrCode);
182   ok(lstrcmpA(test.szPathName, expected) == 0,
183      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
184      test.szPathName, expected);
185   LZClose(file);
186 
187   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
188   memset(&test, 0xA5, sizeof(test));
189   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
190   full_file_path_name_in_a_CWD(_terminated_, short_expected, TRUE);
191 
192   /* d, using underscore-terminated file name. */
193   file = LZOpenFileA(_terminated, &test, OF_EXIST);
194   ok(file >= 0, "LZOpenFileA failed on switching to a compressed file name\n");
195   ok(test.cBytes == sizeof(OFSTRUCT), "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
196   ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
197      test.nErrCode);
198   ok(lstrcmpA(test.szPathName, expected) == 0,
199      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
200      test.szPathName, expected, short_expected);
201   LZClose(file);
202 
203   delete_file(filename_);
204   delete_file(dotless_);
205   delete_file(extless_);
206   delete_file(_terminated_);
207 }
208 
209 static void test_LZOpenFileA_nonexisting_compressed(void)
210 {
211   OFSTRUCT test;
212   INT file;
213   char expected[MAX_PATH];
214   char filled_0xA5[OFS_MAXPATHNAME];
215 
216   /* Try to open nonexisting compressed files: */
217   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
218   memset(&test, 0xA5, sizeof(test));
219   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
220   SetLastError(0xfaceabee);
221 
222   /* a, using 8.3-conformant file name. */
223   file = LZOpenFileA(filename, &test, OF_EXIST);
224   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
225      check for the file "foo.xx_" and open that -- at least on some
226      operating systems.  Doesn't seem to on my copy of Win98.
227    */
228   ok(file == LZERROR_BADINHANDLE,
229      "LZOpenFileA succeeded on nonexistent file\n");
230   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
231      "GetLastError() returns %d\n", GetLastError());
232   ok(test.cBytes == 0xA5,
233      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
234   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
235      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
236   ok(lstrcmpA(test.szPathName, expected) == 0,
237      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
238      test.szPathName, expected, filled_0xA5);
239 
240   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
241   memset(&test, 0xA5, sizeof(test));
242   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
243   SetLastError(0xfaceabee);
244 
245   /* b, using dotless file name. */
246   file = LZOpenFileA(dotless, &test, OF_EXIST);
247   ok(file == LZERROR_BADINHANDLE,
248      "LZOpenFileA succeeded on nonexistent file\n");
249   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
250      "GetLastError() returns %d\n", GetLastError());
251   ok(test.cBytes == 0xA5,
252      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
253   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
254      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
255   ok(lstrcmpA(test.szPathName, expected) == 0,
256      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
257      test.szPathName, expected, filled_0xA5);
258 
259   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
260   memset(&test, 0xA5, sizeof(test));
261   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
262   SetLastError(0xfaceabee);
263 
264   /* c, using extensionless file name. */
265   file = LZOpenFileA(extless, &test, OF_EXIST);
266   ok(file == LZERROR_BADINHANDLE,
267      "LZOpenFileA succeeded on nonexistent file\n");
268   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
269      "GetLastError() returns %d\n", GetLastError());
270   ok(test.cBytes == 0xA5,
271      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
272   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
273      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
274   ok(lstrcmpA(test.szPathName, expected) == 0,
275      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
276      test.szPathName, expected, filled_0xA5);
277 
278   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
279   memset(&test, 0xA5, sizeof(test));
280   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
281   SetLastError(0xfaceabee);
282 
283   /* d, using underscore-terminated file name. */
284   file = LZOpenFileA(_terminated, &test, OF_EXIST);
285   ok(file == LZERROR_BADINHANDLE,
286      "LZOpenFileA succeeded on nonexistent file\n");
287   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
288      "GetLastError() returns %d\n", GetLastError());
289   ok(test.cBytes == 0xA5,
290      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
291   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
292      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
293   ok(lstrcmpA(test.szPathName, expected) == 0,
294      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
295      test.szPathName, expected, filled_0xA5);
296 }
297 
298 static void test_LZOpenFileA(void)
299 {
300   OFSTRUCT test;
301   DWORD retval;
302   INT file;
303   static char badfilename_[] = "badfilename_";
304   char expected[MAX_PATH];
305   char short_expected[MAX_PATH];
306 
307   SetLastError(0xfaceabee);
308   /* Check for nonexistent file. */
309   file = LZOpenFileA(badfilename_, &test, OF_READ);
310   ok(file == LZERROR_BADINHANDLE,
311      "LZOpenFileA succeeded on nonexistent file\n");
312   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
313      "GetLastError() returns %d\n", GetLastError());
314   LZClose(file);
315 
316   memset(&test, 0xA5, sizeof(test));
317   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
318 
319   /* Create an empty file. */
320   file = LZOpenFileA(filename_, &test, OF_CREATE);
321   ok(file >= 0, "LZOpenFileA failed on creation\n");
322   ok(test.cBytes == sizeof(OFSTRUCT),
323      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
324   ok(test.nErrCode == ERROR_SUCCESS,
325      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
326   ok(lstrcmpA(test.szPathName, expected) == 0,
327      "LZOpenFileA returned '%s', but was expected to return '%s'\n",
328      test.szPathName, expected);
329   LZClose(file);
330 
331   retval = GetFileAttributesA(filename_);
332   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n",
333      GetLastError());
334 
335   /* Check various opening options: */
336   memset(&test, 0xA5, sizeof(test));
337   full_file_path_name_in_a_CWD(filename_, short_expected, TRUE);
338 
339   /* a, for reading. */
340   file = LZOpenFileA(filename_, &test, OF_READ);
341   ok(file >= 0, "LZOpenFileA failed on read\n");
342   ok(test.cBytes == sizeof(OFSTRUCT),
343      "LZOpenFileA set test.cBytes to %d '%s'('%s')\n", test.cBytes, expected, short_expected);
344   ok(test.nErrCode == ERROR_SUCCESS,
345      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
346   ok(lstrcmpA(test.szPathName, expected) == 0,
347      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
348      test.szPathName, expected, short_expected);
349   LZClose(file);
350 
351   memset(&test, 0xA5, sizeof(test));
352 
353   /* b, for writing. */
354   file = LZOpenFileA(filename_, &test, OF_WRITE);
355   ok(file >= 0, "LZOpenFileA failed on write\n");
356   ok(test.cBytes == sizeof(OFSTRUCT),
357      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
358   ok(test.nErrCode == ERROR_SUCCESS,
359      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
360   ok(lstrcmpA(test.szPathName, expected) == 0,
361      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
362      test.szPathName, expected, short_expected);
363   LZClose(file);
364 
365   memset(&test, 0xA5, sizeof(test));
366 
367   /* c, for reading and writing. */
368   file = LZOpenFileA(filename_, &test, OF_READWRITE);
369   ok(file >= 0, "LZOpenFileA failed on read/write\n");
370   ok(test.cBytes == sizeof(OFSTRUCT),
371      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
372   ok(test.nErrCode == ERROR_SUCCESS,
373      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
374   ok(lstrcmpA(test.szPathName, expected) == 0,
375      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
376      test.szPathName, expected, short_expected);
377   LZClose(file);
378 
379   memset(&test, 0xA5, sizeof(test));
380 
381   /* d, for checking file existence. */
382   file = LZOpenFileA(filename_, &test, OF_EXIST);
383   ok(file >= 0, "LZOpenFileA failed on read/write\n");
384   ok(test.cBytes == sizeof(OFSTRUCT),
385      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
386   ok(test.nErrCode == ERROR_SUCCESS,
387      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
388   ok(lstrcmpA(test.szPathName, expected) == 0,
389      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
390      test.szPathName, expected, short_expected);
391   LZClose(file);
392 
393   memset(&test, 0xA5, sizeof(test));
394 
395   /* Delete the file then make sure it doesn't exist anymore. */
396   file = LZOpenFileA(filename_, &test, OF_DELETE);
397   ok(file >= 0, "LZOpenFileA failed on delete\n");
398   ok(test.cBytes == sizeof(OFSTRUCT),
399      "LZOpenFileA set test.cBytes to %d\n", test.cBytes);
400   ok(test.nErrCode == ERROR_SUCCESS,
401      "LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
402   ok(lstrcmpA(test.szPathName, expected) == 0,
403      "LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
404      test.szPathName, expected, short_expected);
405   LZClose(file);
406 
407   retval = GetFileAttributesA(filename_);
408   ok(retval == INVALID_FILE_ATTRIBUTES,
409      "GetFileAttributesA succeeded on deleted file\n");
410 
411   test_LZOpenFileA_existing_compressed();
412   test_LZOpenFileA_nonexisting_compressed();
413 }
414 
415 static void test_LZRead(void)
416 {
417   HANDLE file;
418   DWORD ret;
419   int cfile;
420   OFSTRUCT test;
421   BOOL retok;
422 
423   /* Create the compressed file. */
424   file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
425   ok(file != INVALID_HANDLE_VALUE, "Could not create test file\n");
426   retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
427   ok( retok, "WriteFile: error %d\n", GetLastError());
428   ok(ret == compressed_file_size, "Wrote wrong number of bytes with WriteFile?\n");
429   CloseHandle(file);
430 
431   cfile = LZOpenFileA(filename_, &test, OF_READ);
432   ok(cfile > 0, "LZOpenFileA failed\n");
433 
434   ret = LZRead(cfile, buf, uncompressed_data_size);
435   ok(ret == uncompressed_data_size, "Read wrong number of bytes\n");
436 
437   /* Compare what we read with what we think we should read. */
438   ok(memcmp(buf, uncompressed_data, uncompressed_data_size) == 0,
439      "buffer contents mismatch\n");
440 
441   todo_wine {
442      /* Wine returns the number of bytes actually read instead of an error */
443      ret = LZRead(cfile, buf, uncompressed_data_size);
444      ok(ret == LZERROR_READ, "Expected read-past-EOF to return LZERROR_READ\n");
445   }
446 
447   LZClose(cfile);
448 
449   ret = DeleteFileA(filename_);
450   ok(ret, "DeleteFileA: error %d\n", GetLastError());
451 }
452 
453 static void test_LZCopy(void)
454 {
455   HANDLE file;
456   DWORD ret;
457   int source, dest;
458   OFSTRUCT stest, dtest;
459   BOOL retok;
460 
461   /* Create the compressed file. */
462   file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
463   ok(file != INVALID_HANDLE_VALUE,
464      "CreateFileA: error %d\n", GetLastError());
465   retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
466   ok( retok, "WriteFile error %d\n", GetLastError());
467   ok(ret == compressed_file_size, "Wrote wrong number of bytes\n");
468   CloseHandle(file);
469 
470   source = LZOpenFileA(filename_, &stest, OF_READ);
471   ok(source >= 0, "LZOpenFileA failed on compressed file\n");
472   dest = LZOpenFileA(filename2, &dtest, OF_CREATE);
473   ok(dest >= 0, "LZOpenFileA failed on creating new file %d\n", dest);
474 
475   ret = LZCopy(source, dest);
476   ok(ret > 0, "LZCopy error\n");
477 
478   LZClose(source);
479   LZClose(dest);
480 
481   file = CreateFileA(filename2, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
482   ok(file != INVALID_HANDLE_VALUE,
483      "CreateFileA: error %d\n", GetLastError());
484 
485   retok = ReadFile(file, buf, uncompressed_data_size*2, &ret, 0);
486   ok( retok && ret == uncompressed_data_size, "ReadFile: error %d\n", GetLastError());
487   /* Compare what we read with what we think we should read. */
488   ok(!memcmp(buf, uncompressed_data, uncompressed_data_size),
489      "buffer contents mismatch\n");
490   CloseHandle(file);
491 
492   ret = DeleteFileA(filename_);
493   ok(ret, "DeleteFileA: error %d\n", GetLastError());
494   ret = DeleteFileA(filename2);
495   ok(ret, "DeleteFileA: error %d\n", GetLastError());
496 }
497 
498 static void create_fileW(WCHAR *fnameW)
499 {
500   INT file;
501   OFSTRUCT ofs;
502   DWORD retval;
503 
504   file = LZOpenFileW(fnameW, &ofs, OF_CREATE);
505   ok(file >= 0, "LZOpenFileW failed on creation\n");
506   LZClose(file);
507   retval = GetFileAttributesW(fnameW);
508   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesW('%s'): error %d\n", ofs.szPathName, GetLastError());
509 }
510 
511 static void delete_fileW(WCHAR *fnameW)
512 {
513   INT file;
514   OFSTRUCT ofs;
515   DWORD retval;
516 
517   file = LZOpenFileW(fnameW, &ofs, OF_DELETE);
518   ok(file >= 0, "LZOpenFileW failed on delete\n");
519   LZClose(file);
520   retval = GetFileAttributesW(fnameW);
521   ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesW succeeded on deleted file ('%s')\n", ofs.szPathName);
522 }
523 
524 static void test_LZOpenFileW_existing_compressed(void)
525 {
526   OFSTRUCT test;
527   INT file;
528   char expected[MAX_PATH];
529 
530   /* Try to open existing compressed files: */
531   create_fileW(filenameW_);
532   create_fileW(dotlessW_);
533   create_fileW(extlessW_);
534   create_fileW(_terminatedW_);
535 
536   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
537   memset(&test, 0xA5, sizeof(test));
538 
539   /* a, using 8.3-conformant file name. */
540   file = LZOpenFileW(filenameW, &test, OF_EXIST);
541   /* If the file "foo.xxx" does not exist, LZOpenFileW should then
542      check for the file "foo.xx_" and open that.
543    */
544   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
545   ok(test.cBytes == sizeof(OFSTRUCT),
546      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
547   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
548      test.nErrCode);
549   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
550   ok(lstrcmpA(test.szPathName, expected) == 0,
551      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
552      test.szPathName, expected);
553   LZClose(file);
554 
555   memset(&test, 0xA5, sizeof(test));
556   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
557 
558   /* b, using dotless file name. */
559   file = LZOpenFileW(dotlessW, &test, OF_EXIST);
560   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
561   ok(test.cBytes == sizeof(OFSTRUCT),
562      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
563   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
564      test.nErrCode);
565   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
566   ok(lstrcmpA(test.szPathName, expected) == 0,
567      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
568      test.szPathName, expected);
569   LZClose(file);
570 
571   memset(&test, 0xA5, sizeof(test));
572   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
573 
574   /* c, using extensionless file name. */
575   file = LZOpenFileW(extlessW, &test, OF_EXIST);
576   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
577   ok(test.cBytes == sizeof(OFSTRUCT),
578      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
579   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
580      test.nErrCode);
581   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
582   ok(lstrcmpA(test.szPathName, expected) == 0,
583      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
584      test.szPathName, expected);
585   LZClose(file);
586 
587   memset(&test, 0xA5, sizeof(test));
588   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
589 
590   /* d, using underscore-terminated file name. */
591   file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
592   ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
593   ok(test.cBytes == sizeof(OFSTRUCT),
594      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
595   ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
596      test.nErrCode);
597   /* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
598   ok(lstrcmpA(test.szPathName, expected) == 0,
599      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
600      test.szPathName, expected);
601   LZClose(file);
602 
603   delete_fileW(filenameW_);
604   delete_fileW(dotlessW_);
605   delete_fileW(extlessW_);
606   delete_fileW(_terminatedW_);
607 }
608 
609 static void test_LZOpenFileW_nonexisting_compressed(void)
610 {
611   OFSTRUCT test;
612   INT file;
613   char expected[MAX_PATH];
614   char filled_0xA5[OFS_MAXPATHNAME];
615 
616   /* Try to open nonexisting compressed files: */
617   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
618   memset(&test, 0xA5, sizeof(test));
619   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
620   SetLastError(0xfaceabee);
621 
622   /* a, using 8.3-conformant file name. */
623   file = LZOpenFileW(filenameW, &test, OF_EXIST);
624   /* If the file "foo.xxx" does not exist, LZOpenFileA should then
625      check for the file "foo.xx_" and open that -- at least on some
626      operating systems.  Doesn't seem to on my copy of Win98.
627    */
628   ok(file == LZERROR_BADINHANDLE,
629      "LZOpenFileW succeeded on nonexistent file\n");
630   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
631      "GetLastError() returns %d\n", GetLastError());
632   ok(test.cBytes == 0xA5,
633      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
634   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
635      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
636   ok(lstrcmpA(test.szPathName, expected) == 0,
637      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
638      test.szPathName, expected, filled_0xA5);
639 
640   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
641   memset(&test, 0xA5, sizeof(test));
642   full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
643   SetLastError(0xfaceabee);
644 
645   /* b, using dotless file name. */
646   file = LZOpenFileW(dotlessW, &test, OF_EXIST);
647   ok(file == LZERROR_BADINHANDLE,
648      "LZOpenFileW succeeded on nonexistent file\n");
649   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
650      "GetLastError() returns %d\n", GetLastError());
651   ok(test.cBytes == 0xA5,
652      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
653   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
654      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
655   ok(lstrcmpA(test.szPathName, expected) == 0,
656      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
657      test.szPathName, expected, filled_0xA5);
658 
659   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
660   memset(&test, 0xA5, sizeof(test));
661   full_file_path_name_in_a_CWD(extless_, expected, FALSE);
662   SetLastError(0xfaceabee);
663 
664   /* c, using extensionless file name. */
665   file = LZOpenFileW(extlessW, &test, OF_EXIST);
666   ok(file == LZERROR_BADINHANDLE,
667      "LZOpenFileW succeeded on nonexistent file\n");
668   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
669      "GetLastError() returns %d\n", GetLastError());
670   ok(test.cBytes == 0xA5,
671      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
672   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
673      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
674   ok(lstrcmpA(test.szPathName, expected) == 0,
675      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
676      test.szPathName, expected, filled_0xA5);
677 
678   memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
679   memset(&test, 0xA5, sizeof(test));
680   full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
681   SetLastError(0xfaceabee);
682 
683   /* d, using underscore-terminated file name. */
684   file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
685   ok(file == LZERROR_BADINHANDLE,
686      "LZOpenFileW succeeded on nonexistent file\n");
687   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
688      "GetLastError() returns %d\n", GetLastError());
689   ok(test.cBytes == 0xA5,
690      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
691   ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
692      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
693   ok(lstrcmpA(test.szPathName, expected) == 0,
694      "LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
695      test.szPathName, expected, filled_0xA5);
696 }
697 
698 static void test_LZOpenFileW(void)
699 {
700   OFSTRUCT test;
701   DWORD retval;
702   INT file;
703   static WCHAR badfilenameW[] = {'b','a','d','f','i','l','e','n','a','m','e','.','x','t','n',0};
704   char expected[MAX_PATH];
705 
706   SetLastError(0xfaceabee);
707   /* Check for nonexistent file. */
708   file = LZOpenFileW(badfilenameW, &test, OF_READ);
709   if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
710   {
711     win_skip("LZOpenFileW call is not implemented\n");
712     return;
713   }
714   ok(GetLastError() == ERROR_FILE_NOT_FOUND,
715      "GetLastError() returns %d\n", GetLastError());
716   ok(file == LZERROR_BADINHANDLE, "LZOpenFileW succeeded on nonexistent file\n");
717   LZClose(file);
718 
719   memset(&test, 0xA5, sizeof(test));
720   full_file_path_name_in_a_CWD(filename_, expected, FALSE);
721 
722   /* Create an empty file. */
723   file = LZOpenFileW(filenameW_, &test, OF_CREATE);
724   ok(file >= 0, "LZOpenFile failed on creation\n");
725   ok(test.cBytes == sizeof(OFSTRUCT),
726      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
727   ok(test.nErrCode == ERROR_SUCCESS,
728      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
729   ok(lstrcmpA(test.szPathName, expected) == 0,
730      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
731      test.szPathName, expected);
732   LZClose(file);
733 
734   retval = GetFileAttributesW(filenameW_);
735   ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributes: error %d\n",
736     GetLastError());
737 
738   /* Check various opening options: */
739   memset(&test, 0xA5, sizeof(test));
740 
741   /* a, for reading. */
742   file = LZOpenFileW(filenameW_, &test, OF_READ);
743   ok(file >= 0, "LZOpenFileW failed on read\n");
744   ok(test.cBytes == sizeof(OFSTRUCT),
745      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
746   ok(test.nErrCode == ERROR_SUCCESS,
747      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
748   ok(lstrcmpA(test.szPathName, expected) == 0,
749      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
750      test.szPathName, expected);
751   LZClose(file);
752 
753   memset(&test, 0xA5, sizeof(test));
754 
755   /* b, for writing. */
756   file = LZOpenFileW(filenameW_, &test, OF_WRITE);
757   ok(file >= 0, "LZOpenFileW failed on write\n");
758   ok(test.cBytes == sizeof(OFSTRUCT),
759      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
760   ok(test.nErrCode == ERROR_SUCCESS,
761      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
762   ok(lstrcmpA(test.szPathName, expected) == 0,
763      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
764      test.szPathName, expected);
765   LZClose(file);
766 
767   memset(&test, 0xA5, sizeof(test));
768 
769   /* c, for reading and writing. */
770   file = LZOpenFileW(filenameW_, &test, OF_READWRITE);
771   ok(file >= 0, "LZOpenFileW failed on read/write\n");
772   ok(test.cBytes == sizeof(OFSTRUCT),
773      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
774   ok(test.nErrCode == ERROR_SUCCESS,
775      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
776   ok(lstrcmpA(test.szPathName, expected) == 0,
777      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
778      test.szPathName, expected);
779   LZClose(file);
780 
781   memset(&test, 0xA5, sizeof(test));
782 
783   /* d, for checking file existence. */
784   file = LZOpenFileW(filenameW_, &test, OF_EXIST);
785   ok(file >= 0, "LZOpenFileW failed on read/write\n");
786   ok(test.cBytes == sizeof(OFSTRUCT),
787      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
788   ok(test.nErrCode == ERROR_SUCCESS,
789      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
790   ok(lstrcmpA(test.szPathName, expected) == 0,
791      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
792      test.szPathName, expected);
793   LZClose(file);
794 
795   memset(&test, 0xA5, sizeof(test));
796 
797   /* Delete the file then make sure it doesn't exist anymore. */
798   file = LZOpenFileW(filenameW_, &test, OF_DELETE);
799   ok(file >= 0, "LZOpenFileW failed on delete\n");
800   ok(test.cBytes == sizeof(OFSTRUCT),
801      "LZOpenFileW set test.cBytes to %d\n", test.cBytes);
802   ok(test.nErrCode == ERROR_SUCCESS,
803      "LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
804   ok(lstrcmpA(test.szPathName, expected) == 0,
805      "LZOpenFileW returned '%s', but was expected to return '%s'\n",
806      test.szPathName, expected);
807   LZClose(file);
808 
809   retval = GetFileAttributesW(filenameW_);
810   ok(retval == INVALID_FILE_ATTRIBUTES,
811      "GetFileAttributesW succeeded on deleted file\n");
812 
813   test_LZOpenFileW_existing_compressed();
814   test_LZOpenFileW_nonexisting_compressed();
815 }
816 
817 
818 START_TEST(lzexpand_main)
819 {
820   buf = HeapAlloc(GetProcessHeap(), 0, uncompressed_data_size * 2);
821   test_LZOpenFileA();
822   test_LZOpenFileW();
823   test_LZRead();
824   test_LZCopy();
825   HeapFree(GetProcessHeap(), 0, buf);
826 }
827