ReactOS  0.4.13-dev-544-gede3fdd
vfdzip.c
Go to the documentation of this file.
1 /*
2  vfdzip.c
3 
4  Virtual Floppy Drive for Windows
5  Driver control library
6  Zip compressed floppy image handling
7 
8  Copyright (C) 2003-2005 Ken Kato
9 */
10 
11 #ifdef __cplusplus
12 #pragma message(__FILE__": Compiled as C++ for testing purpose.")
13 #endif // __cplusplus
14 
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17 
18 #include "vfdtypes.h"
19 #include "vfdio.h"
20 #include "vfdlib.h"
21 
22 #ifndef __REACTOS__
23 #define ZLIB_WINAPI
24 #else
25 #define Z_SOLO
26 #define ZLIB_INTERNAL
27 #endif
28 #include "zlib.h"
29 
30 #ifdef VFD_NO_ZLIB
31 #pragma message("ZIP image support is disabled.")
32 
34  HANDLE hFile,
35  ULONG *pSize)
36 {
39  return ERROR_NOT_SUPPORTED;
40 }
41 
43  HANDLE hFile,
44  PUCHAR *pBuffer,
45  PULONG pLength)
46 {
49  UNREFERENCED_PARAMETER(pLength);
50  return ERROR_NOT_SUPPORTED;
51 }
52 
53 #else // VFD_NO_ZLIB
54 
55 #ifdef _DEBUG
56 static const char *ZLIB_ERROR(int err)
57 {
58  switch (err) {
59  case Z_OK : return "Z_OK";
60  case Z_STREAM_END : return "Z_STREAM_END";
61  case Z_NEED_DICT : return "Z_NEED_DICT";
62  case Z_ERRNO : return "Z_ERRNO";
63  case Z_STREAM_ERROR : return "Z_STREAM_ERROR";
64  case Z_DATA_ERROR : return "Z_DATA_ERROR";
65  case Z_MEM_ERROR : return "Z_MEM_ERROR";
66  case Z_BUF_ERROR : return "Z_BUF_ERROR";
67  case Z_VERSION_ERROR: return "Z_VERSION_ERROR";
68  default : return "unknown";
69  }
70 }
71 #endif // _DEBUG
72 
73 voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size))
74 {
75  UNREFERENCED_PARAMETER(opaque);
76  return LocalAlloc(LPTR, items * size);
77 }
78 
79 void zcfree OF((voidpf opaque, voidpf ptr))
80 {
81  UNREFERENCED_PARAMETER(opaque);
82  LocalFree(ptr);
83 }
84 
85 #define ZIP_LOCAL_SIGNATURE 0x04034b50
86 
87 #define ZIP_FLAG_ENCRYPTED 0x01
88 
89 #define ZIP_FLAG_DEFLATE_NORMAL 0x00
90 #define ZIP_FLAG_DEFLATE_MAX 0x02
91 #define ZIP_FLAG_DEFLATE_FAST 0x04
92 #define ZIP_FLAG_DEFLATE_SUPER 0x06
93 #define ZIP_FLAG_DEFLATE_MASK 0x06
94 
95 #define ZIP_FLAG_SIZE_IN_DESC 0x08
96 
97 #define ZIP_METHOD_STORED 0
98 #define ZIP_METHOD_SHRUNK 1
99 #define ZIP_METHOD_REDUCED1 2
100 #define ZIP_METHOD_REDUCED2 3
101 #define ZIP_METHOD_REDUCED3 4
102 #define ZIP_METHOD_REDUCED4 5
103 #define ZIP_METHOD_IMPLODED 6
104 #define ZIP_METHOD_TOKENIZED 7
105 #define ZIP_METHOD_DEFLATED 8
106 #define ZIP_METHOD_DEFLATE64 9
107 #define ZIP_METHOD_PKWARE_IMP 10
108 #define ZIP_METHOD_RESERVED 11
109 #define ZIP_METHOD_BZIP2 12
110 
111 #pragma pack(1)
112 
113 typedef struct _zip_local_file_header {
126  // followed by extra field data, then compressed data
127 }
129 
130 //
131 // Check if the file is ZIP compressed
132 //
134  HANDLE hFile,
135  ULONG *pSize)
136 {
137  ZIP_HEADER zip_hdr;
138  DWORD result;
139  DWORD ret;
140 
141  if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
142  ret = GetLastError();
143 
144  VFDTRACE(0,
145  ("SetFilePointer() - %s\n",
146  SystemMessage(ret)));
147 
148  return ret;
149  }
150 
151  if (!ReadFile(hFile, &zip_hdr, sizeof(zip_hdr), &result, NULL)) {
152  ret = GetLastError();
153 
154  VFDTRACE(0,
155  ("ReadFile() - %s\n",
156  SystemMessage(ret)));
157 
158  return ret;
159  }
160 
161  if (result != sizeof(zip_hdr) ||
164  (zip_hdr.general_flags & ZIP_FLAG_ENCRYPTED)) {
165 
166  VFDTRACE(0,
167  ("[VFD] Invalid ZIP file\n"));
168 
169  return ERROR_INVALID_DATA;
170  }
171 
172  // correct (and supported) ZIP header detected
173 
174  *pSize = zip_hdr.uncompressed_size;
175 
176  return ERROR_SUCCESS;
177 }
178 
179 //
180 // Extract original data from IMZ file
181 //
183  HANDLE hFile,
184  PUCHAR *pBuffer,
185  PULONG pLength)
186 {
188  DWORD result;
189  DWORD ret;
190 
191  PZIP_HEADER zip_hdr;
192  ULONG compressed;
194  PUCHAR file_cache;
196  int zlib_ret;
197 
198  VFDTRACE(0,
199  ("[VFD] VfdExtractImz - IN\n"));
200 
201  *pBuffer = NULL;
202  *pLength = 0;
203 
204  //
205  // Read PKZIP local file header of the first file in the file
206  // -- An IMZ file actually is just a ZIP file with a different
207  // extension, which contains a single floppy image file
208  //
209  if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
210  ret = GetLastError();
211 
212  VFDTRACE(0,(
213  "SetFilePointer - %s", SystemMessage(ret)));;
214 
215  return ret;
216  }
217 
220 
221  ret = GetLastError();
222 
223  VFDTRACE(0,(
224  "ReadFile - %s", SystemMessage(ret)));;
225 
226  return ret;
227  }
228 
229  zip_hdr = (PZIP_HEADER)buf;
230 
231  // check local file header signature
232 
233  if (zip_hdr->header_signature != ZIP_LOCAL_SIGNATURE) {
234 
235  VFDTRACE(0,
236  ("[VFD] PKZIP header signature not found.\n"));
237 
238  return ERROR_INVALID_DATA;
239  }
240 
241  // check compression method
242 
243  if (zip_hdr->compression_method != Z_DEFLATED) {
244 
245  VFDTRACE(0,
246  ("[VFD] Bad PKZIP compression method.\n"));
247 
248  return ERROR_NOT_SUPPORTED;
249  }
250 
251  if (zip_hdr->general_flags & 0x01) {
252  // encrypted zip not supported
253 
254  VFDTRACE(0,
255  ("[VFD] PKZIP encrypted.\n"));
256 
257  return ERROR_NOT_SUPPORTED;
258  }
259 
260  // check uncompressed image size
261 
262  compressed = zip_hdr->compressed_size;
263  uncompressed = zip_hdr->uncompressed_size;
264 
265  switch (uncompressed) {
266  case VFD_SECTOR_TO_BYTE(320):
267  case VFD_SECTOR_TO_BYTE(360):
268  case VFD_SECTOR_TO_BYTE(640):
269  case VFD_SECTOR_TO_BYTE(720):
270  case VFD_SECTOR_TO_BYTE(1280):
271  case VFD_SECTOR_TO_BYTE(1440):
272  case VFD_SECTOR_TO_BYTE(1640):
273  case VFD_SECTOR_TO_BYTE(2400):
274  case VFD_SECTOR_TO_BYTE(2880):
275  case VFD_SECTOR_TO_BYTE(3360):
276  case VFD_SECTOR_TO_BYTE(3444):
277  case VFD_SECTOR_TO_BYTE(5760):
278  break;
279 
280  default:
281  VFDTRACE(0,
282  ("[VFD] Unsupported image size %lu.\n",
283  uncompressed));
284 
285  return ERROR_NOT_SUPPORTED;
286  }
287 
288  // check local file header length
289  // -- Just for simplicity, the compressed data must start in the
290  // first sector in the file: this is not a problem in most cases.
291 
293  zip_hdr->file_name_length +
295 
296  VFDTRACE(0,
297  ("[VFD] PKZIP header too long.\n"));
298 
299  return ERROR_NOT_SUPPORTED;
300  }
301 
302  // allocate memory to store uncompressed data
303 
304  file_cache = (PUCHAR)LocalAlloc(LPTR, uncompressed);
305 
306  if (!file_cache) {
307 
308  VFDTRACE(0,
309  ("[VFD] Failed to allocate file cache.\n"));
310 
311  return ERROR_OUTOFMEMORY;
312  }
313 
314  // initialize the zlib stream
315 
316  ZeroMemory(&stream, sizeof(stream));
317 
318  // set initial input data information
319 
320  stream.next_in = (PUCHAR)zip_hdr->file_name +
321  zip_hdr->file_name_length + zip_hdr->extra_field_length;
322 
323  stream.avail_in = VFD_BYTES_PER_SECTOR -
325  zip_hdr->file_name_length - zip_hdr->extra_field_length;
326 
327  // set output buffer information
328 
329  stream.next_out = file_cache;
330  stream.avail_out = uncompressed;
331 
332  zlib_ret = inflateInit2(&stream, -MAX_WBITS);
333 
334  // negative MAX_WBITS value passed to the inflateInit2() function
335  // indicates that there is no zlib header.
336  // In this case inflate() function requires an extra "dummy" byte
337  // after the compressed stream in order to complete decompression
338  // and return Z_STREAM_END. However, both compressed and uncompressed
339  // data size are already known from the pkzip header, Z_STREAM_END
340  // is not absolutely necessary to know the completion of the operation.
341 
342  if (zlib_ret != Z_OK) {
343  LocalFree(file_cache);
344 
345  VFDTRACE(0,
346  ("[VFD] inflateInit2() failed - %s.\n",
347  ZLIB_ERROR(zlib_ret)));
348 
349  return ERROR_INVALID_FUNCTION;
350  }
351 
352  for (;;) {
353 
354  // uncompress current block
355 
356  zlib_ret = inflate(&stream, Z_NO_FLUSH);
357 
358  if (zlib_ret != Z_OK) {
359  if (zlib_ret == Z_STREAM_END) {
360  ret = ERROR_SUCCESS;
361  }
362  else {
363  VFDTRACE(0,
364  ("[VFD] inflate() failed - %s.\n",
365  ZLIB_ERROR(zlib_ret)));
366 
368  }
369  break;
370  }
371 
372  if (stream.total_out >= uncompressed) {
373  // uncompress completed - no need to wait for Z_STREAM_END
374  // (inflate() would return Z_STREAM_END on the next call)
375  ret = ERROR_SUCCESS;
376  break;
377  }
378 
379  if (stream.total_in >= compressed) {
380  // somehow there is not enought compressed data
382  break;
383  }
384 
385  // read next block from file
386 
388  result <= 0) {
389 
390  ret = GetLastError();
391 
392  VFDTRACE(0,
393  ("[VFD] Read compressed data - %s.\n",
394  SystemMessage(ret)));
395  break;
396  }
397 
398  stream.avail_in = result;
399  stream.next_in = buf;
400  }
401 
402  // cleanup the zlib stream
403 
404  inflateEnd(&stream);
405 
406  // set the return information
407 
408  if (ret == ERROR_SUCCESS) {
409  *pBuffer = file_cache;
410  *pLength = uncompressed;
411  }
412  else {
413  LocalFree(file_cache);
414  }
415 
416  VFDTRACE(0,
417  ("[VFD] VfdExtractImz - OUT\n"));
418 
419  return ret;
420 }
421 
422 #endif // VFD_NO_ZLIB
#define ZIP_METHOD_DEFLATED
Definition: vfdzip.c:105
#define Z_ERRNO
Definition: zlib.h:180
#define ZIP_FLAG_ENCRYPTED
Definition: vfdzip.c:87
#define ERROR_SUCCESS
Definition: deptool.c:10
USHORT extra_field_length
Definition: vfdzip.c:124
#define VFD_BYTES_PER_SECTOR
Definition: vfdio.h:40
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1277
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
#define Z_NEED_DICT
Definition: zlib.h:179
#define Z_STREAM_ERROR
Definition: zlib.h:181
static const BYTE uncompressed[]
Definition: misc.c:392
#define Z_STREAM_END
Definition: zlib.h:178
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
#define Z_BUF_ERROR
Definition: zlib.h:184
#define Z_OK
Definition: zlib.h:177
static PVOID ptr
Definition: dispmode.c:27
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
#define Z_DEFLATED
Definition: zlib.h:209
GLsizeiptr size
Definition: glext.h:5919
PCSTR SystemMessage(DWORD nError)
Definition: vfdlib.c:147
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1800
unsigned long DWORD
Definition: ntddk_ex.h:95
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
#define Z_DATA_ERROR
Definition: zlib.h:182
#define Z_NO_FLUSH
Definition: zlib.h:168
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:622
struct _zip_local_file_header ZIP_HEADER
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size))
Definition: vfdzip.c:73
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
#define err(...)
_In_ HANDLE hFile
Definition: mswsock.h:90
#define ERROR_INVALID_DATA
Definition: winerror.h:116
Byte FAR * voidpf
Definition: zconf.h:413
#define FILE_BEGIN
Definition: winbase.h:112
USHORT required_version
Definition: vfdzip.c:115
#define Z_VERSION_ERROR
Definition: zlib.h:185
unsigned short USHORT
Definition: pedump.c:61
void zcfree(voidpf opaque, voidpf ptr)
Definition: zutil.c:173
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
DWORD ExtractZipInfo(HANDLE hFile, ULONG *pSize)
Definition: vfdzip.c:133
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
voidpf zcalloc(voidpf opaque, unsigned items, unsigned size)
Definition: zutil.c:164
unsigned int * PULONG
Definition: retypes.h:1
#define ZIP_LOCAL_SIGNATURE
Definition: vfdzip.c:85
static LPCWSTR file_name
Definition: protocol.c:146
#define ERROR_NOT_SUPPORTED
Definition: compat.h:90
USHORT file_name_length
Definition: vfdzip.c:123
unsigned int ULONG
Definition: retypes.h:1
#define LPTR
Definition: winbase.h:362
USHORT compression_method
Definition: vfdzip.c:117
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1373
static TCHAR * items[]
Definition: page1.c:45
DWORD ExtractZipImage(HANDLE hFile, PUCHAR *pBuffer, PULONG pLength)
Definition: vfdzip.c:182
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
GLuint64EXT * result
Definition: glext.h:11304
#define MAX_WBITS
Definition: zconf.h:270
struct _zip_local_file_header * PZIP_HEADER
#define Z_MEM_ERROR
Definition: zlib.h:183
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13