// Program name: cffdrmgr.h // Programmed by: Anthony Barbachan // Programmed in: C++ (Turbo C++ 3.0 Compatable) // Purpose: source file for cabinet file types and constants. // Version: 1.00 // Last modified on: 10/18/1999 // Changes: Moved class definition to this header file. // Version: 1.01 // Last modified on: 10/24/1999 // Changes: Commented out left over debugging trace statement. #ifndef __CFFDRMGR_CPP__ #define __CFFDRMGR_CPP__ #include #include "zlib.h" #include "cftypes.h" #include "cfdblock.h" #include "cfheader.h" #include "cffdrmgr.h" #include "cffolder.h" ////////////////////////////////////////**************************************** // This function extracts nbytes of data starting at start in in and writes // those bytes out to out. in is assumed to be the file stream with the // associated datablocks for this folder. Decompression is handled on the fly // by this function. int cabinet_folder_manager::extract_data(ostream& out, istream& in, dword start, dword nbytes, cabinet_header& cab_header) { int err = OK; word temp = 0u; word nblock = 0u; cabinet_datablock block; if(in.seekg(data_offset).fail()) return SEEK_ERROR;// Start pos if((err = write_data(out, block, 0u, 0u, COMP_INIT)) != OK) return err; for(nblock = 0u; nblock < ndatablocks; nblock++) // Find start { if((err = block.read(in, cab_header)) != OK) return err; if(start < (dword) block.get_uncompressed_size()) break; if((err = write_data(out, block, 0u, 0u, COMP_DOBLOCK_NOWRITE)) != OK) return err; start -= block.get_uncompressed_size(); } if(nblock >= ndatablocks) return NOT_IN_FOLDER; temp = block.get_uncompressed_size() - (word) start; if(nbytes <= (dword) temp) { return write_data(out, block, (word) start, (word) nbytes, COMP_DOBLOCK_WRITE); } else { if((err = write_data(out, block, (word) start, (word) temp, COMP_DOBLOCK_WRITE)) != OK) return err; nbytes -= temp; } for(nblock++; nblock < ndatablocks; nblock++) // write data { if((err = block.read(in, cab_header)) != OK) return err; if(nbytes <= (dword) block.get_uncompressed_size()) { return write_data(out, block, 0u, (word) nbytes, COMP_DOBLOCK_WRITE); } else { if((err = write_data(out, block, 0u, (word) block.get_uncompressed_size(), COMP_DOBLOCK_WRITE)) != OK) return err; nbytes -= block.get_uncompressed_size(); } } if((err = write_data(out, block, 0u, 0u, COMP_END)) != OK) return err; return DOES_NOT_END; } ////////////////////////////////////////**************************************** // This function write data from a datablock to out. int cabinet_folder_manager::write_data(ostream& out, cabinet_datablock& block, word offset, word nbytes, COMPRESSION_STATE_FLAG state) { int err = OK; if(state == COMP_INIT) { if(compression_type != MSZIP_COMPRESSION) return OK; if(stream != NULL) delete stream; stream = new z_stream; stream->zalloc = (alloc_func) Z_NULL; stream->zfree = (free_func) Z_NULL; if((err = inflateInit(stream)) != Z_OK) { delete stream; stream = NULL; return DECOMPRESSION_ERROR; } return OK; } else if(((state == COMP_DOBLOCK_WRITE) || (state == COMP_DOBLOCK_NOWRITE)) && (stream == NULL) && (compression_type == MSZIP_COMPRESSION)) { return MUST_INIT; } else if(state == COMP_END) { if(compression_type != MSZIP_COMPRESSION) return OK; if(stream != NULL) { if(inflateEnd(stream) != Z_OK) err = DECOMPRESSION_ERROR; delete stream; stream = NULL; } return err; } if(compression_type == NO_COMPRESSION) { return ((err = io_write(out, block.get_compressed_data() + offset, nbytes)) != OK) ? err : OK; } else if(compression_type == MSZIP_COMPRESSION) { byte* buf = new byte[block.get_uncompressed_size()]; stream->next_in = (byte *) block.get_compressed_data(); // cout << (stream->next_in)[0] << (stream->next_in)[1] << endl; stream->avail_in = block.get_compressed_size(); stream->next_out = buf; stream->avail_out = block.get_uncompressed_size(); err = inflate(stream, Z_FINISH); if((err != Z_OK) && (err != Z_STREAM_END)) { err = convert_z_error_code(err); inflateEnd(stream); delete stream; stream = NULL; } else { int err2 = (state == COMP_DOBLOCK_WRITE) ? io_write(out, buf + offset, nbytes) : OK; if((err = inflateReset(stream)) != Z_OK) { err = convert_z_error_code(err); inflateEnd(stream); delete stream; stream = NULL; } else if((err = err2) != OK) { inflateEnd(stream); delete stream; stream = NULL; } } delete[] buf; return err; } else { return UNSUPPORTED_COMPRESSION; } } ////////////////////////////////////////**************************************** #endif