Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423/* vfdzip.c
Virtual Floppy Drive for Windows Driver control library Zip compressed floppy image handling
Copyright (C) 2003-2005 Ken Kato*/
#ifdef __cplusplus#pragma message(__FILE__": Compiled as C++ for testing purpose.")#endif // __cplusplus
#define WIN32_LEAN_AND_MEAN#include <windows.h>
#include "vfdtypes.h"#include "vfdio.h"#include "vfdlib.h"
#ifndef __REACTOS__#define ZLIB_WINAPI#else#define Z_SOLO#define ZLIB_INTERNAL#endif#include "zlib.h"
#ifdef VFD_NO_ZLIB#pragma message("ZIP image support is disabled.")
DWORD ExtractZipInfo( HANDLE hFile, ULONG *pSize){ UNREFERENCED_PARAMETER(hFile); UNREFERENCED_PARAMETER(pSize); return ERROR_NOT_SUPPORTED;}
DWORD ExtractZipImage( HANDLE hFile, PUCHAR *pBuffer, PULONG pLength){ UNREFERENCED_PARAMETER(hFile); UNREFERENCED_PARAMETER(pBuffer); UNREFERENCED_PARAMETER(pLength); return ERROR_NOT_SUPPORTED;}
#else // VFD_NO_ZLIB
#ifdef _DEBUGstatic const char *ZLIB_ERROR(int err){ switch (err) { case Z_OK : return "Z_OK"; case Z_STREAM_END : return "Z_STREAM_END"; case Z_NEED_DICT : return "Z_NEED_DICT"; case Z_ERRNO : return "Z_ERRNO"; case Z_STREAM_ERROR : return "Z_STREAM_ERROR"; case Z_DATA_ERROR : return "Z_DATA_ERROR"; case Z_MEM_ERROR : return "Z_MEM_ERROR"; case Z_BUF_ERROR : return "Z_BUF_ERROR"; case Z_VERSION_ERROR: return "Z_VERSION_ERROR"; default : return "unknown"; }}#endif // _DEBUG
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)){ UNREFERENCED_PARAMETER(opaque); return LocalAlloc(LPTR, items * size);}
void zcfree OF((voidpf opaque, voidpf ptr)){ UNREFERENCED_PARAMETER(opaque); LocalFree(ptr);}
#define ZIP_LOCAL_SIGNATURE 0x04034b50
#define ZIP_FLAG_ENCRYPTED 0x01
#define ZIP_FLAG_DEFLATE_NORMAL 0x00#define ZIP_FLAG_DEFLATE_MAX 0x02#define ZIP_FLAG_DEFLATE_FAST 0x04#define ZIP_FLAG_DEFLATE_SUPER 0x06#define ZIP_FLAG_DEFLATE_MASK 0x06
#define ZIP_FLAG_SIZE_IN_DESC 0x08
#define ZIP_METHOD_STORED 0#define ZIP_METHOD_SHRUNK 1#define ZIP_METHOD_REDUCED1 2#define ZIP_METHOD_REDUCED2 3#define ZIP_METHOD_REDUCED3 4#define ZIP_METHOD_REDUCED4 5#define ZIP_METHOD_IMPLODED 6#define ZIP_METHOD_TOKENIZED 7#define ZIP_METHOD_DEFLATED 8#define ZIP_METHOD_DEFLATE64 9#define ZIP_METHOD_PKWARE_IMP 10#define ZIP_METHOD_RESERVED 11#define ZIP_METHOD_BZIP2 12
#pragma pack(1)
typedef struct _zip_local_file_header { ULONG header_signature; USHORT required_version; USHORT general_flags; USHORT compression_method; USHORT last_mod_time; USHORT last_mod_date; ULONG crc32; ULONG compressed_size; ULONG uncompressed_size; USHORT file_name_length; USHORT extra_field_length; CHAR file_name[1]; // followed by extra field data, then compressed data}ZIP_HEADER, *PZIP_HEADER;
//// Check if the file is ZIP compressed//DWORD ExtractZipInfo( HANDLE hFile, ULONG *pSize){ ZIP_HEADER zip_hdr; DWORD result; DWORD ret;
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { ret = GetLastError();
VFDTRACE(0, ("SetFilePointer() - %s\n", SystemMessage(ret)));
return ret; }
if (!ReadFile(hFile, &zip_hdr, sizeof(zip_hdr), &result, NULL)) { ret = GetLastError();
VFDTRACE(0, ("ReadFile() - %s\n", SystemMessage(ret)));
return ret; }
if (result != sizeof(zip_hdr) || zip_hdr.header_signature != ZIP_LOCAL_SIGNATURE || zip_hdr.compression_method != ZIP_METHOD_DEFLATED || (zip_hdr.general_flags & ZIP_FLAG_ENCRYPTED)) {
VFDTRACE(0, ("[VFD] Invalid ZIP file\n"));
return ERROR_INVALID_DATA; }
// correct (and supported) ZIP header detected
*pSize = zip_hdr.uncompressed_size;
return ERROR_SUCCESS;}
//// Extract original data from IMZ file//DWORD ExtractZipImage( HANDLE hFile, PUCHAR *pBuffer, PULONG pLength){ UCHAR buf[VFD_BYTES_PER_SECTOR]; DWORD result; DWORD ret;
PZIP_HEADER zip_hdr; ULONG compressed; ULONG uncompressed; PUCHAR file_cache; z_stream stream; int zlib_ret;
VFDTRACE(0, ("[VFD] VfdExtractImz - IN\n"));
*pBuffer = NULL; *pLength = 0;
// // Read PKZIP local file header of the first file in the file // -- An IMZ file actually is just a ZIP file with a different // extension, which contains a single floppy image file // if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { ret = GetLastError();
VFDTRACE(0,( "SetFilePointer - %s", SystemMessage(ret)));;
return ret; }
if (!ReadFile(hFile, buf, VFD_BYTES_PER_SECTOR, &result, NULL) || result < VFD_BYTES_PER_SECTOR) {
ret = GetLastError();
VFDTRACE(0,( "ReadFile - %s", SystemMessage(ret)));;
return ret; }
zip_hdr = (PZIP_HEADER)buf;
// check local file header signature
if (zip_hdr->header_signature != ZIP_LOCAL_SIGNATURE) {
VFDTRACE(0, ("[VFD] PKZIP header signature not found.\n"));
return ERROR_INVALID_DATA; }
// check compression method
if (zip_hdr->compression_method != Z_DEFLATED) {
VFDTRACE(0, ("[VFD] Bad PKZIP compression method.\n"));
return ERROR_NOT_SUPPORTED; }
if (zip_hdr->general_flags & 0x01) { // encrypted zip not supported
VFDTRACE(0, ("[VFD] PKZIP encrypted.\n"));
return ERROR_NOT_SUPPORTED; }
// check uncompressed image size
compressed = zip_hdr->compressed_size; uncompressed = zip_hdr->uncompressed_size;
switch (uncompressed) { case VFD_SECTOR_TO_BYTE(320): case VFD_SECTOR_TO_BYTE(360): case VFD_SECTOR_TO_BYTE(640): case VFD_SECTOR_TO_BYTE(720): case VFD_SECTOR_TO_BYTE(1280): case VFD_SECTOR_TO_BYTE(1440): case VFD_SECTOR_TO_BYTE(1640): case VFD_SECTOR_TO_BYTE(2400): case VFD_SECTOR_TO_BYTE(2880): case VFD_SECTOR_TO_BYTE(3360): case VFD_SECTOR_TO_BYTE(3444): case VFD_SECTOR_TO_BYTE(5760): break;
default: VFDTRACE(0, ("[VFD] Unsupported image size %lu.\n", uncompressed));
return ERROR_NOT_SUPPORTED; }
// check local file header length // -- Just for simplicity, the compressed data must start in the // first sector in the file: this is not a problem in most cases.
if (FIELD_OFFSET(ZIP_HEADER, file_name) + zip_hdr->file_name_length + zip_hdr->extra_field_length >= VFD_BYTES_PER_SECTOR) {
VFDTRACE(0, ("[VFD] PKZIP header too long.\n"));
return ERROR_NOT_SUPPORTED; }
// allocate memory to store uncompressed data
file_cache = (PUCHAR)LocalAlloc(LPTR, uncompressed);
if (!file_cache) {
VFDTRACE(0, ("[VFD] Failed to allocate file cache.\n"));
return ERROR_OUTOFMEMORY; }
// initialize the zlib stream
ZeroMemory(&stream, sizeof(stream));
// set initial input data information
stream.next_in = (PUCHAR)zip_hdr->file_name + zip_hdr->file_name_length + zip_hdr->extra_field_length;
stream.avail_in = VFD_BYTES_PER_SECTOR - FIELD_OFFSET(ZIP_HEADER, file_name) - zip_hdr->file_name_length - zip_hdr->extra_field_length;
// set output buffer information
stream.next_out = file_cache; stream.avail_out = uncompressed;
zlib_ret = inflateInit2(&stream, -MAX_WBITS);
// negative MAX_WBITS value passed to the inflateInit2() function // indicates that there is no zlib header. // In this case inflate() function requires an extra "dummy" byte // after the compressed stream in order to complete decompression // and return Z_STREAM_END. However, both compressed and uncompressed // data size are already known from the pkzip header, Z_STREAM_END // is not absolutely necessary to know the completion of the operation.
if (zlib_ret != Z_OK) { LocalFree(file_cache);
VFDTRACE(0, ("[VFD] inflateInit2() failed - %s.\n", ZLIB_ERROR(zlib_ret)));
return ERROR_INVALID_FUNCTION; }
for (;;) {
// uncompress current block
zlib_ret = inflate(&stream, Z_NO_FLUSH);
if (zlib_ret != Z_OK) { if (zlib_ret == Z_STREAM_END) { ret = ERROR_SUCCESS; } else { VFDTRACE(0, ("[VFD] inflate() failed - %s.\n", ZLIB_ERROR(zlib_ret)));
ret = ERROR_INVALID_FUNCTION; } break; }
if (stream.total_out >= uncompressed) { // uncompress completed - no need to wait for Z_STREAM_END // (inflate() would return Z_STREAM_END on the next call) ret = ERROR_SUCCESS; break; }
if (stream.total_in >= compressed) { // somehow there is not enought compressed data ret = ERROR_INVALID_FUNCTION; break; }
// read next block from file
if (!ReadFile(hFile, buf, VFD_BYTES_PER_SECTOR, &result, NULL) || result <= 0) {
ret = GetLastError();
VFDTRACE(0, ("[VFD] Read compressed data - %s.\n", SystemMessage(ret))); break; }
stream.avail_in = result; stream.next_in = buf; }
// cleanup the zlib stream
inflateEnd(&stream);
// set the return information
if (ret == ERROR_SUCCESS) { *pBuffer = file_cache; *pLength = uncompressed; } else { LocalFree(file_cache); }
VFDTRACE(0, ("[VFD] VfdExtractImz - OUT\n"));
return ret;}
#endif // VFD_NO_ZLIB