public static bool UnmarshalItpfHeader(ref byte[] pData, ref uint pDataPos, ref uint pDataLen, ref chmItspHeader dest) { /* we only know how to deal with a 0x54 byte structures */ if (pDataLen != CHM_ITSP_V1_LEN) { return(false); } InitialiseItspHeader(ref dest); /* unmarshal fields */ Unmarshal.ToCharArray(ref pData, ref pDataPos, ref pDataLen, ref dest.signature, 4); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.version); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.header_len); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_000c); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_len); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.blockidx_intvl); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_depth); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_root); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_head); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0024); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.num_blocks); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_002c); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.lang_id); Unmarshal.ToUuid(ref pData, ref pDataPos, ref pDataLen, ref dest.system_uuid); Unmarshal.ToByteArray(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0044, 16); /* error check the data */ if (new String(dest.signature).CompareTo("ITSP\0") != 0) { return(false); } if (dest.version != 1) { return(false); } if (dest.header_len != CHM_ITSP_V1_LEN) { return(false); } return(true); }
public static bool UnmarshalItpfHeader(ref byte[] pData, ref uint pDataPos, ref uint pDataLen, ref chmItspHeader dest) { /* we only know how to deal with a 0x54 byte structures */ if (pDataLen != CHM_ITSP_V1_LEN) return false; InitialiseItspHeader(ref dest); /* unmarshal fields */ Unmarshal.ToCharArray(ref pData, ref pDataPos, ref pDataLen, ref dest.signature, 4); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.version); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.header_len); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_000c); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_len); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.blockidx_intvl); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_depth); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_root); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.index_head); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0024); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.num_blocks); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_002c); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.lang_id); Unmarshal.ToUuid(ref pData, ref pDataPos, ref pDataLen, ref dest.system_uuid); Unmarshal.ToByteArray(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0044, 16); /* error check the data */ if (new String(dest.signature).CompareTo("ITSP\0") != 0) return false; if (dest.version != 1) return false; if (dest.header_len != CHM_ITSP_V1_LEN) return false; return true; }
public static void InitialiseItspHeader(ref chmItspHeader h) { h.signature = new char[5]; h.system_uuid = new byte[16]; h.unknown_0044 = new byte[16]; }
public static ChmFile Open(string filename) { byte[] sbuffer = new byte[256]; uint sremain; uint sbufpos; chmItsfHeader itsfHeader = new chmItsfHeader(); chmItspHeader itspHeader = new chmItspHeader(); ChmUnitInfo uiLzxc = new ChmUnitInfo(); chmLzxcControlData ctlData = new chmLzxcControlData(); ChmFile chmf = new ChmFile(filename); /* allocate handle */ chmf._h.fd = null; chmf._h.lzx_state = null; chmf._h.cache_blocks = null; chmf._h.cache_block_indices = null; chmf._h.cache_num_blocks = 0; /* open file */ chmf._h.fd = File.Open(filename, FileMode.Open, FileAccess.Read); /* initialize mutexes, if needed */ chmf._h.mutex = new Mutex(); chmf._h.lzx_mutex = new Mutex(); chmf._h.cache_mutex = new Mutex(); /* read and verify header */ sremain = Itsf.CHM_ITSF_V3_LEN; sbufpos = 0; if (Storage.FetchBytes(ref chmf._h, ref sbuffer, 0, sremain) != sremain || !Itsf.UnmarshalItsfHeader(ref sbuffer, ref sbufpos, ref sremain, ref itsfHeader)) { chmf.Close(); throw new InvalidDataException(); } /* stash important values from header */ chmf._h.dir_offset = itsfHeader.dir_offset; chmf._h.dir_len = itsfHeader.dir_len; chmf._h.data_offset = itsfHeader.data_offset; /* now, read and verify the directory header chunk */ sremain = Itsp.CHM_ITSP_V1_LEN; sbufpos = 0; if (Storage.FetchBytes(ref chmf._h, ref sbuffer, (UInt64)itsfHeader.dir_offset, sremain) != sremain || !Itsp.UnmarshalItpfHeader(ref sbuffer, ref sbufpos, ref sremain, ref itspHeader)) { chmf.Close(); throw new InvalidDataException(); } /* grab essential information from ITSP header */ chmf._h.dir_offset += (ulong)itspHeader.header_len; chmf._h.dir_len -= (ulong)itspHeader.header_len; chmf._h.index_root = itspHeader.index_root; chmf._h.index_head = itspHeader.index_head; chmf._h.block_len = itspHeader.block_len; /* if the index root is -1, this means we don't have any PMGI blocks. * as a result, we must use the sole PMGL block as the index root */ if (chmf._h.index_root <= -1) chmf._h.index_root = chmf._h.index_head; /* By default, compression is enabled. */ chmf._h.compression_enabled = true; /* prefetch most commonly needed unit infos */ if (!chmf.ResolveObject(Storage.CHMU_RESET_TABLE, ref chmf._h.rt_unit) || chmf._h.rt_unit.space == Storage.CHM_COMPRESSED || !chmf.ResolveObject(Storage.CHMU_CONTENT, ref chmf._h.cn_unit) || chmf._h.cn_unit.space == Storage.CHM_COMPRESSED || !chmf.ResolveObject(Storage.CHMU_LZXC_CONTROLDATA, ref uiLzxc) || uiLzxc.space == Storage.CHM_COMPRESSED) { chmf._h.compression_enabled = false; } /* read reset table info */ if (chmf._h.compression_enabled) { sremain = Lzxc.CHM_LZXC_RESETTABLE_V1_LEN; sbufpos = 0; /* TODO bobc: is sbuffer actually at index 0?? */ if (chmf.RetrieveObject(chmf._h.rt_unit, ref sbuffer, 0, sremain) != sremain || !Lzxc.UnmarshalLzxcResetTable(ref sbuffer, ref sbufpos, ref sremain, ref chmf._h.reset_table)) { chmf._h.compression_enabled = false; } } /* read control data */ if (chmf._h.compression_enabled) { sremain = (uint)uiLzxc.length; if (uiLzxc.length > (ulong)sbuffer.Length) { chmf.Close(); throw new InvalidDataException(); } sbufpos = 0; /* TODO bobc: is sbuffer actually at index 0?? */ if (chmf.RetrieveObject(uiLzxc, ref sbuffer, 0, sremain) != sremain || !Lzxc.UnmarshalLzxcControlData(ref sbuffer, ref sbufpos, ref sremain, ref ctlData)) { chmf._h.compression_enabled = false; } chmf._h.window_size = ctlData.windowSize; chmf._h.reset_interval = ctlData.resetInterval; /* Jed, Mon Jun 28: Experimentally, it appears that the reset block count */ /* must be multiplied by this formerly unknown ctrl data field in */ /* order to decompress some files. */ chmf._h.reset_blkcount = chmf._h.reset_interval / (chmf._h.window_size / 2) * ctlData.windowsPerReset; } /* initialize cache */ chmf.SetParam(CHM_PARAM_MAX_BLOCKS_CACHED, CHM_MAX_BLOCKS_CACHED); return chmf; }
public static ChmFile Open(string filename) { byte[] sbuffer = new byte[256]; uint sremain; uint sbufpos; chmItsfHeader itsfHeader = new chmItsfHeader(); chmItspHeader itspHeader = new chmItspHeader(); ChmUnitInfo uiLzxc = new ChmUnitInfo(); chmLzxcControlData ctlData = new chmLzxcControlData(); ChmFile chmf = new ChmFile(filename); /* allocate handle */ chmf._h.fd = null; chmf._h.lzx_state = null; chmf._h.cache_blocks = null; chmf._h.cache_block_indices = null; chmf._h.cache_num_blocks = 0; /* open file */ chmf._h.fd = File.Open(filename, FileMode.Open, FileAccess.Read); /* initialize mutexes, if needed */ chmf._h.mutex = new Mutex(); chmf._h.lzx_mutex = new Mutex(); chmf._h.cache_mutex = new Mutex(); /* read and verify header */ sremain = Itsf.CHM_ITSF_V3_LEN; sbufpos = 0; if (Storage.FetchBytes(ref chmf._h, ref sbuffer, 0, sremain) != sremain || !Itsf.UnmarshalItsfHeader(ref sbuffer, ref sbufpos, ref sremain, ref itsfHeader)) { chmf.Close(); throw new InvalidDataException(); } /* stash important values from header */ chmf._h.dir_offset = itsfHeader.dir_offset; chmf._h.dir_len = itsfHeader.dir_len; chmf._h.data_offset = itsfHeader.data_offset; /* now, read and verify the directory header chunk */ sremain = Itsp.CHM_ITSP_V1_LEN; sbufpos = 0; if (Storage.FetchBytes(ref chmf._h, ref sbuffer, (UInt64)itsfHeader.dir_offset, sremain) != sremain || !Itsp.UnmarshalItpfHeader(ref sbuffer, ref sbufpos, ref sremain, ref itspHeader)) { chmf.Close(); throw new InvalidDataException(); } /* grab essential information from ITSP header */ chmf._h.dir_offset += (ulong)itspHeader.header_len; chmf._h.dir_len -= (ulong)itspHeader.header_len; chmf._h.index_root = itspHeader.index_root; chmf._h.index_head = itspHeader.index_head; chmf._h.block_len = itspHeader.block_len; /* if the index root is -1, this means we don't have any PMGI blocks. * as a result, we must use the sole PMGL block as the index root */ if (chmf._h.index_root <= -1) { chmf._h.index_root = chmf._h.index_head; } /* By default, compression is enabled. */ chmf._h.compression_enabled = true; /* prefetch most commonly needed unit infos */ if (!chmf.ResolveObject(Storage.CHMU_RESET_TABLE, ref chmf._h.rt_unit) || chmf._h.rt_unit.space == Storage.CHM_COMPRESSED || !chmf.ResolveObject(Storage.CHMU_CONTENT, ref chmf._h.cn_unit) || chmf._h.cn_unit.space == Storage.CHM_COMPRESSED || !chmf.ResolveObject(Storage.CHMU_LZXC_CONTROLDATA, ref uiLzxc) || uiLzxc.space == Storage.CHM_COMPRESSED) { chmf._h.compression_enabled = false; } /* read reset table info */ if (chmf._h.compression_enabled) { sremain = Lzxc.CHM_LZXC_RESETTABLE_V1_LEN; sbufpos = 0; /* TODO bobc: is sbuffer actually at index 0?? */ if (chmf.RetrieveObject(chmf._h.rt_unit, ref sbuffer, 0, sremain) != sremain || !Lzxc.UnmarshalLzxcResetTable(ref sbuffer, ref sbufpos, ref sremain, ref chmf._h.reset_table)) { chmf._h.compression_enabled = false; } } /* read control data */ if (chmf._h.compression_enabled) { sremain = (uint)uiLzxc.length; if (uiLzxc.length > (ulong)sbuffer.Length) { chmf.Close(); throw new InvalidDataException(); } sbufpos = 0; /* TODO bobc: is sbuffer actually at index 0?? */ if (chmf.RetrieveObject(uiLzxc, ref sbuffer, 0, sremain) != sremain || !Lzxc.UnmarshalLzxcControlData(ref sbuffer, ref sbufpos, ref sremain, ref ctlData)) { chmf._h.compression_enabled = false; } chmf._h.window_size = ctlData.windowSize; chmf._h.reset_interval = ctlData.resetInterval; /* Jed, Mon Jun 28: Experimentally, it appears that the reset block count */ /* must be multiplied by this formerly unknown ctrl data field in */ /* order to decompress some files. */ chmf._h.reset_blkcount = chmf._h.reset_interval / (chmf._h.window_size / 2) * ctlData.windowsPerReset; } /* initialize cache */ chmf.SetParam(CHM_PARAM_MAX_BLOCKS_CACHED, CHM_MAX_BLOCKS_CACHED); return(chmf); }
public static void InitialiseItspHeader(ref chmItspHeader h) { h.signature = new char[5]; h.system_uuid = new byte[16]; h.unknown_0044 = new byte[16]; }