ReactOS 0.4.17-dev-966-gf06eace
chm_lib.c File Reference
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "chm_lib.h"
#include "lzx.h"
Include dependency graph for chm_lib.c:

Go to the source code of this file.

Classes

struct  chmItsfHeader
 
struct  chmItspHeader
 
struct  chmPmglHeader
 
struct  chmPmgiHeader
 
struct  chmLzxcResetTable
 
struct  chmLzxcControlData
 
struct  chmFile
 

Macros

#define CHM_ACQUIRE_LOCK(a)
 
#define CHM_RELEASE_LOCK(a)
 
#define CHM_NULL_FD   (INVALID_HANDLE_VALUE)
 
#define CHM_CLOSE_FILE(fd)   CloseHandle((fd))
 
#define CHM_MAX_BLOCKS_CACHED   5
 
#define CHM_PARAM_MAX_BLOCKS_CACHED   0
 
#define _CHM_ITSF_V2_LEN   (0x58)
 
#define _CHM_ITSF_V3_LEN   (0x60)
 
#define _CHM_ITSP_V1_LEN   (0x54)
 
#define _CHM_PMGL_LEN   (0x14)
 
#define _CHM_PMGI_LEN   (0x08)
 
#define _CHM_LZXC_RESETTABLE_V1_LEN   (0x28)
 
#define _CHM_LZXC_MIN_LEN   (0x18)
 
#define _CHM_LZXC_V2_LEN   (0x1c)
 

Typedefs

typedef BYTE UChar
 
typedef SHORT Int16
 
typedef USHORT UInt16
 
typedef LONG Int32
 
typedef DWORD UInt32
 
typedef LONGLONG Int64
 
typedef ULONGLONG UInt64
 

Functions

static BOOL _unmarshal_char_array (unsigned char **pData, unsigned int *pLenRemain, char *dest, int count)
 
static BOOL _unmarshal_uchar_array (unsigned char **pData, unsigned int *pLenRemain, unsigned char *dest, int count)
 
static BOOL _unmarshal_int32 (unsigned char **pData, unsigned int *pLenRemain, Int32 *dest)
 
static BOOL _unmarshal_uint32 (unsigned char **pData, unsigned int *pLenRemain, UInt32 *dest)
 
static BOOL _unmarshal_int64 (unsigned char **pData, unsigned int *pLenRemain, Int64 *dest)
 
static BOOL _unmarshal_uint64 (unsigned char **pData, unsigned int *pLenRemain, UInt64 *dest)
 
static BOOL _unmarshal_uuid (unsigned char **pData, unsigned int *pDataLen, unsigned char *dest)
 
static BOOL _unmarshal_itsf_header (unsigned char **pData, unsigned int *pDataLen, struct chmItsfHeader *dest)
 
static BOOL _unmarshal_itsp_header (unsigned char **pData, unsigned int *pDataLen, struct chmItspHeader *dest)
 
static BOOL _unmarshal_pmgl_header (unsigned char **pData, unsigned int *pDataLen, struct chmPmglHeader *dest)
 
static BOOL _unmarshal_pmgi_header (unsigned char **pData, unsigned int *pDataLen, struct chmPmgiHeader *dest)
 
static BOOL _unmarshal_lzxc_reset_table (unsigned char **pData, unsigned int *pDataLen, struct chmLzxcResetTable *dest)
 
static BOOL _unmarshal_lzxc_control_data (unsigned char **pData, unsigned int *pDataLen, struct chmLzxcControlData *dest)
 
static Int64 _chm_fetch_bytes (struct chmFile *h, UChar *buf, UInt64 os, Int64 len)
 
static void chm_set_param (struct chmFile *h, int paramType, int paramVal)
 
struct chmFile * chm_openW (const WCHAR *filename)
 
struct chmFile * chm_dup (struct chmFile *oldHandle)
 
void chm_close (struct chmFile *h)
 
static void _chm_skip_cword (UChar **pEntry)
 
static void _chm_skip_PMGL_entry_data (UChar **pEntry)
 
static UInt64 _chm_parse_cword (UChar **pEntry)
 
static BOOL _chm_parse_UTF8 (UChar **pEntry, UInt64 count, WCHAR *path)
 
static BOOL _chm_parse_PMGL_entry (UChar **pEntry, struct chmUnitInfo *ui)
 
static UChar * _chm_find_in_PMGL (UChar *page_buf, UInt32 block_len, const WCHAR *objPath)
 
static Int32 _chm_find_in_PMGI (UChar *page_buf, UInt32 block_len, const WCHAR *objPath)
 
int chm_resolve_object (struct chmFile *h, const WCHAR *objPath, struct chmUnitInfo *ui)
 
static BOOL _chm_get_cmpblock_bounds (struct chmFile *h, UInt64 block, UInt64 *start, Int64 *len)
 
static Int64 _chm_decompress_block (struct chmFile *h, UInt64 block, UChar **ubuffer)
 
static Int64 _chm_decompress_region (struct chmFile *h, UChar *buf, UInt64 start, Int64 len)
 
LONGINT64 chm_retrieve_object (struct chmFile *h, struct chmUnitInfo *ui, unsigned char *buf, LONGUINT64 addr, LONGINT64 len)
 
BOOL chm_enumerate_dir (struct chmFile *h, const WCHAR *prefix, int what, CHM_ENUMERATOR e, void *context)
 

Variables

static const char _chm_pmgl_marker [4] = "PMGL"
 
static const char _chm_pmgi_marker [4] = "PMGI"
 

Macro Definition Documentation

◆ _CHM_ITSF_V2_LEN

#define _CHM_ITSF_V2_LEN   (0x58)

Definition at line 211 of file chm_lib.c.

◆ _CHM_ITSF_V3_LEN

#define _CHM_ITSF_V3_LEN   (0x60)

Definition at line 212 of file chm_lib.c.

◆ _CHM_ITSP_V1_LEN

#define _CHM_ITSP_V1_LEN   (0x54)

Definition at line 288 of file chm_lib.c.

◆ _CHM_LZXC_MIN_LEN

#define _CHM_LZXC_MIN_LEN   (0x18)

Definition at line 444 of file chm_lib.c.

◆ _CHM_LZXC_RESETTABLE_V1_LEN

#define _CHM_LZXC_RESETTABLE_V1_LEN   (0x28)

Definition at line 407 of file chm_lib.c.

◆ _CHM_LZXC_V2_LEN

#define _CHM_LZXC_V2_LEN   (0x1c)

Definition at line 445 of file chm_lib.c.

◆ _CHM_PMGI_LEN

#define _CHM_PMGI_LEN   (0x08)

Definition at line 380 of file chm_lib.c.

◆ _CHM_PMGL_LEN

#define _CHM_PMGL_LEN   (0x14)

Definition at line 346 of file chm_lib.c.

◆ CHM_ACQUIRE_LOCK

#define CHM_ACQUIRE_LOCK (   a)
Value:
do { \
EnterCriticalSection(&(a)); \
} while(0)
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204

Definition at line 70 of file chm_lib.c.

◆ CHM_CLOSE_FILE

#define CHM_CLOSE_FILE (   fd)    CloseHandle((fd))

Definition at line 78 of file chm_lib.c.

◆ CHM_MAX_BLOCKS_CACHED

#define CHM_MAX_BLOCKS_CACHED   5

Definition at line 84 of file chm_lib.c.

◆ CHM_NULL_FD

#define CHM_NULL_FD   (INVALID_HANDLE_VALUE)

Definition at line 77 of file chm_lib.c.

◆ CHM_PARAM_MAX_BLOCKS_CACHED

#define CHM_PARAM_MAX_BLOCKS_CACHED   0

Definition at line 86 of file chm_lib.c.

◆ CHM_RELEASE_LOCK

#define CHM_RELEASE_LOCK (   a)
Value:
do { \
LeaveCriticalSection(&(a)); \
} while(0)

Definition at line 73 of file chm_lib.c.

Typedef Documentation

◆ Int16

typedef SHORT Int16

Definition at line 101 of file chm_lib.c.

◆ Int32

typedef LONG Int32

Definition at line 103 of file chm_lib.c.

◆ Int64

typedef LONGLONG Int64

Definition at line 105 of file chm_lib.c.

◆ UChar

typedef BYTE UChar

Definition at line 100 of file chm_lib.c.

◆ UInt16

typedef USHORT UInt16

Definition at line 102 of file chm_lib.c.

◆ UInt32

typedef DWORD UInt32

Definition at line 104 of file chm_lib.c.

◆ UInt64

typedef ULONGLONG UInt64

Definition at line 106 of file chm_lib.c.

Function Documentation

◆ _chm_decompress_block()

static Int64 _chm_decompress_block ( struct chmFile *  h,
UInt64  block,
UChar **  ubuffer 
)
static

Definition at line 1152 of file chm_lib.c.

1155{
1156 UChar *cbuffer = HeapAlloc( GetProcessHeap(), 0,
1157 ((unsigned int)h->reset_table.block_len + 6144));
1158 UInt64 cmpStart; /* compressed start */
1159 Int64 cmpLen; /* compressed len */
1160 int indexSlot; /* cache index slot */
1161 UChar *lbuffer; /* local buffer ptr */
1162 UInt32 blockAlign = (UInt32)(block % h->reset_blkcount); /* reset interval align */
1163 UInt32 i; /* local loop index */
1164
1165 /* let the caching system pull its weight! */
1166 if (block - blockAlign <= h->lzx_last_block &&
1167 block >= h->lzx_last_block)
1168 blockAlign = (block - h->lzx_last_block);
1169
1170 /* check if we need previous blocks */
1171 if (blockAlign != 0)
1172 {
1173 /* fetch all required previous blocks since last reset */
1174 for (i = blockAlign; i > 0; i--)
1175 {
1176 UInt32 curBlockIdx = block - i;
1177
1178 /* check if we most recently decompressed the previous block */
1179 if (h->lzx_last_block != curBlockIdx)
1180 {
1181 if ((curBlockIdx % h->reset_blkcount) == 0)
1182 {
1183#ifdef CHM_DEBUG
1184 fprintf(stderr, "***RESET (1)***\n");
1185#endif
1186 LZXreset(h->lzx_state);
1187 }
1188
1189 indexSlot = (int)((curBlockIdx) % h->cache_num_blocks);
1190 h->cache_block_indices[indexSlot] = curBlockIdx;
1191 if (! h->cache_blocks[indexSlot])
1192 h->cache_blocks[indexSlot] =
1194 (unsigned int)(h->reset_table.block_len));
1195 lbuffer = h->cache_blocks[indexSlot];
1196
1197 /* decompress the previous block */
1198#ifdef CHM_DEBUG
1199 fprintf(stderr, "Decompressing block #%4d (EXTRA)\n", curBlockIdx);
1200#endif
1201 if (!_chm_get_cmpblock_bounds(h, curBlockIdx, &cmpStart, &cmpLen) ||
1202 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen ||
1203 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen,
1204 (int)h->reset_table.block_len) != DECR_OK)
1205 {
1206#ifdef CHM_DEBUG
1207 fprintf(stderr, " (DECOMPRESS FAILED!)\n");
1208#endif
1209 HeapFree(GetProcessHeap(), 0, cbuffer);
1210 return 0;
1211 }
1212
1213 h->lzx_last_block = (int)curBlockIdx;
1214 }
1215 }
1216 }
1217 else
1218 {
1219 if ((block % h->reset_blkcount) == 0)
1220 {
1221#ifdef CHM_DEBUG
1222 fprintf(stderr, "***RESET (2)***\n");
1223#endif
1224 LZXreset(h->lzx_state);
1225 }
1226 }
1227
1228 /* allocate slot in cache */
1229 indexSlot = (int)(block % h->cache_num_blocks);
1230 h->cache_block_indices[indexSlot] = block;
1231 if (! h->cache_blocks[indexSlot])
1232 h->cache_blocks[indexSlot] =
1233 HeapAlloc(GetProcessHeap(), 0, ((unsigned int)h->reset_table.block_len));
1234 lbuffer = h->cache_blocks[indexSlot];
1235 *ubuffer = lbuffer;
1236
1237 /* decompress the block we actually want */
1238#ifdef CHM_DEBUG
1239 fprintf(stderr, "Decompressing block #%4d (REAL )\n", block);
1240#endif
1241 if (! _chm_get_cmpblock_bounds(h, block, &cmpStart, &cmpLen) ||
1242 _chm_fetch_bytes(h, cbuffer, cmpStart, cmpLen) != cmpLen ||
1243 LZXdecompress(h->lzx_state, cbuffer, lbuffer, (int)cmpLen,
1244 (int)h->reset_table.block_len) != DECR_OK)
1245 {
1246#ifdef CHM_DEBUG
1247 fprintf(stderr, " (DECOMPRESS FAILED!)\n");
1248#endif
1249 HeapFree(GetProcessHeap(), 0, cbuffer);
1250 return 0;
1251 }
1252 h->lzx_last_block = (int)block;
1253
1254 /* XXX: modify LZX routines to return the length of the data they
1255 * decompressed and return that instead, for an extra sanity check.
1256 */
1257 HeapFree(GetProcessHeap(), 0, cbuffer);
1258 return h->reset_table.block_len;
1259}
DWORD UInt32
Definition: chm_lib.c:104
LONGLONG Int64
Definition: chm_lib.c:105
BYTE UChar
Definition: chm_lib.c:100
ULONGLONG UInt64
Definition: chm_lib.c:106
static BOOL _chm_get_cmpblock_bounds(struct chmFile *h, UInt64 block, UInt64 *start, Int64 *len)
Definition: chm_lib.c:1090
static Int64 _chm_fetch_bytes(struct chmFile *h, UChar *buf, UInt64 os, Int64 len)
Definition: chm_lib.c:541
#define DECR_OK
Definition: mszip.h:79
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
int WINAPIV fprintf(FILE *file, const char *format,...)
Definition: file.c:5549
#define stderr
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int LZXdecompress(struct LZXstate *pState, unsigned char *inpos, unsigned char *outpos, int inlen, int outlen)
Definition: lzx.c:461
int LZXreset(struct LZXstate *pState)
Definition: lzx.c:218
static unsigned int block
Definition: xmlmemory.c:101

Referenced by _chm_decompress_region().

◆ _chm_decompress_region()

static Int64 _chm_decompress_region ( struct chmFile *  h,
UChar *  buf,
UInt64  start,
Int64  len 
)
static

Definition at line 1262 of file chm_lib.c.

1266{
1267 UInt64 nBlock, nOffset;
1268 UInt64 nLen;
1269 UInt64 gotLen;
1270 UChar *ubuffer = NULL;
1271
1272 if (len <= 0)
1273 return 0;
1274
1275 /* figure out what we need to read */
1276 nBlock = start / h->reset_table.block_len;
1277 nOffset = start % h->reset_table.block_len;
1278 nLen = len;
1279 if (nLen > (h->reset_table.block_len - nOffset))
1280 nLen = h->reset_table.block_len - nOffset;
1281
1282 /* if block is cached, return data from it. */
1283 CHM_ACQUIRE_LOCK(h->lzx_mutex);
1284 CHM_ACQUIRE_LOCK(h->cache_mutex);
1285 if (h->cache_block_indices[nBlock % h->cache_num_blocks] == nBlock &&
1286 h->cache_blocks[nBlock % h->cache_num_blocks] != NULL)
1287 {
1288 memcpy(buf,
1289 h->cache_blocks[nBlock % h->cache_num_blocks] + nOffset,
1290 (unsigned int)nLen);
1291 CHM_RELEASE_LOCK(h->cache_mutex);
1292 CHM_RELEASE_LOCK(h->lzx_mutex);
1293 return nLen;
1294 }
1295 CHM_RELEASE_LOCK(h->cache_mutex);
1296
1297 /* data request not satisfied, so... start up the decompressor machine */
1298 if (! h->lzx_state)
1299 {
1300 h->lzx_last_block = -1;
1301 h->lzx_state = LZXinit(h->window_size);
1302 }
1303
1304 /* decompress some data */
1305 gotLen = _chm_decompress_block(h, nBlock, &ubuffer);
1306 if (gotLen < nLen)
1307 nLen = gotLen;
1308 memcpy(buf, ubuffer+nOffset, (unsigned int)nLen);
1309 CHM_RELEASE_LOCK(h->lzx_mutex);
1310 return nLen;
1311}
#define CHM_RELEASE_LOCK(a)
Definition: chm_lib.c:73
#define CHM_ACQUIRE_LOCK(a)
Definition: chm_lib.c:70
static Int64 _chm_decompress_block(struct chmFile *h, UInt64 block, UChar **ubuffer)
Definition: chm_lib.c:1152
#define NULL
Definition: types.h:112
GLuint start
Definition: gl.h:1545
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
struct LZXstate * LZXinit(int wndsize)
Definition: lzx.c:172
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by chm_retrieve_object().

◆ _chm_fetch_bytes()

static Int64 _chm_fetch_bytes ( struct chmFile *  h,
UChar *  buf,
UInt64  os,
Int64  len 
)
static

Definition at line 541 of file chm_lib.c.

545{
546 Int64 readLen=0;
547 if (h->fd == CHM_NULL_FD)
548 return readLen;
549
550 CHM_ACQUIRE_LOCK(h->mutex);
551 /* NOTE: this might be better done with CreateFileMapping, et cetera... */
552 {
553 LARGE_INTEGER old_pos, new_pos;
554 DWORD actualLen=0;
555
556 /* awkward Win32 Seek/Tell */
557 new_pos.QuadPart = 0;
558 SetFilePointerEx( h->fd, new_pos, &old_pos, FILE_CURRENT );
559 new_pos.QuadPart = os;
560 SetFilePointerEx( h->fd, new_pos, NULL, FILE_BEGIN );
561
562 /* read the data */
563 if (ReadFile(h->fd,
564 buf,
565 (DWORD)len,
566 &actualLen,
567 NULL))
568 readLen = actualLen;
569 else
570 readLen = 0;
571
572 /* restore original position */
573 SetFilePointerEx( h->fd, old_pos, NULL, FILE_BEGIN );
574 }
575 CHM_RELEASE_LOCK(h->mutex);
576 return readLen;
577}
#define CHM_NULL_FD
Definition: chm_lib.c:77
#define FILE_BEGIN
Definition: compat.h:761
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
BOOL WINAPI SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Definition: fileinfo.c:177
unsigned long DWORD
Definition: ntddk_ex.h:95
LONGLONG QuadPart
Definition: typedefs.h:114
#define FILE_CURRENT
Definition: winbase.h:116

Referenced by _chm_decompress_block(), _chm_get_cmpblock_bounds(), chm_enumerate_dir(), chm_openW(), chm_resolve_object(), and chm_retrieve_object().

◆ _chm_find_in_PMGI()

static Int32 _chm_find_in_PMGI ( UChar *  page_buf,
UInt32  block_len,
const WCHAR *  objPath 
)
static

Definition at line 978 of file chm_lib.c.

981{
982 /* XXX: modify this to do a binary search using the nice index structure
983 * that is provided for us
984 */
985 struct chmPmgiHeader header;
986 unsigned int hremain;
987 int page=-1;
988 UChar *end;
989 UChar *cur;
990 UInt64 strLen;
992
993 /* figure out where to start and end */
994 cur = page_buf;
995 hremain = _CHM_PMGI_LEN;
996 if (! _unmarshal_pmgi_header(&cur, &hremain, &header))
997 return -1;
998 end = page_buf + block_len - (header.free_space);
999
1000 /* now, scan progressively */
1001 while (cur < end)
1002 {
1003 /* grab the name */
1004 strLen = _chm_parse_cword(&cur);
1005 if (! _chm_parse_UTF8(&cur, strLen, buffer))
1006 return -1;
1007
1008 /* check if it is the right name */
1009 if (wcsicmp(buffer, objPath) > 0)
1010 return page;
1011
1012 /* load next value for path */
1014 }
1015
1016 return page;
1017}
static BOOL _unmarshal_pmgi_header(unsigned char **pData, unsigned int *pDataLen, struct chmPmgiHeader *dest)
Definition: chm_lib.c:387
static BOOL _chm_parse_UTF8(UChar **pEntry, UInt64 count, WCHAR *path)
Definition: chm_lib.c:906
static UInt64 _chm_parse_cword(UChar **pEntry)
Definition: chm_lib.c:892
#define _CHM_PMGI_LEN
Definition: chm_lib.c:380
#define CHM_MAX_PATHLEN
Definition: chm_lib.h:66
#define wcsicmp
Definition: compat.h:15
FxCollectionEntry * cur
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
short WCHAR
Definition: pedump.c:58
Definition: module.h:576

Referenced by chm_resolve_object().

◆ _chm_find_in_PMGL()

static UChar * _chm_find_in_PMGL ( UChar *  page_buf,
UInt32  block_len,
const WCHAR *  objPath 
)
static

Definition at line 936 of file chm_lib.c.

939{
940 /* XXX: modify this to do a binary search using the nice index structure
941 * that is provided for us.
942 */
943 struct chmPmglHeader header;
944 unsigned int hremain;
945 UChar *end;
946 UChar *cur;
947 UChar *temp;
948 UInt64 strLen;
950
951 /* figure out where to start and end */
952 cur = page_buf;
953 hremain = _CHM_PMGL_LEN;
954 if (! _unmarshal_pmgl_header(&cur, &hremain, &header))
955 return NULL;
956 end = page_buf + block_len - (header.free_space);
957
958 /* now, scan progressively */
959 while (cur < end)
960 {
961 /* grab the name */
962 temp = cur;
963 strLen = _chm_parse_cword(&cur);
964 if (! _chm_parse_UTF8(&cur, strLen, buffer))
965 return NULL;
966
967 /* check if it is the right name */
968 if (! wcsicmp(buffer, objPath))
969 return temp;
970
972 }
973
974 return NULL;
975}
static void _chm_skip_PMGL_entry_data(UChar **pEntry)
Definition: chm_lib.c:884
static BOOL _unmarshal_pmgl_header(unsigned char **pData, unsigned int *pDataLen, struct chmPmglHeader *dest)
Definition: chm_lib.c:356
#define _CHM_PMGL_LEN
Definition: chm_lib.c:346
static calc_node_t temp
Definition: rpn_ieee.c:38

Referenced by chm_resolve_object().

◆ _chm_get_cmpblock_bounds()

static BOOL _chm_get_cmpblock_bounds ( struct chmFile *  h,
UInt64  block,
UInt64 *  start,
Int64 *  len 
)
static

Definition at line 1090 of file chm_lib.c.

1094{
1095 UChar buffer[8], *dummy;
1096 unsigned int remain;
1097
1098 /* for all but the last block, use the reset table */
1099 if (block < h->reset_table.block_count-1)
1100 {
1101 /* unpack the start address */
1102 dummy = buffer;
1103 remain = 8;
1105 h->data_offset
1106 + h->rt_unit.start
1107 + h->reset_table.table_offset
1108 + block*8,
1109 remain) != remain ||
1110 !_unmarshal_uint64(&dummy, &remain, start))
1111 return FALSE;
1112
1113 /* unpack the end address */
1114 dummy = buffer;
1115 remain = 8;
1117 h->data_offset
1118 + h->rt_unit.start
1119 + h->reset_table.table_offset
1120 + block*8 + 8,
1121 remain) != remain ||
1122 !_unmarshal_int64(&dummy, &remain, len))
1123 return FALSE;
1124 }
1125
1126 /* for the last block, use the span in addition to the reset table */
1127 else
1128 {
1129 /* unpack the start address */
1130 dummy = buffer;
1131 remain = 8;
1133 h->data_offset
1134 + h->rt_unit.start
1135 + h->reset_table.table_offset
1136 + block*8,
1137 remain) != remain ||
1138 !_unmarshal_uint64(&dummy, &remain, start))
1139 return FALSE;
1140
1141 *len = h->reset_table.compressed_len;
1142 }
1143
1144 /* compute the length and absolute start address */
1145 *len -= *start;
1146 *start += h->data_offset + h->cn_unit.start;
1147
1148 return TRUE;
1149}
static BOOL _unmarshal_int64(unsigned char **pData, unsigned int *pLenRemain, Int64 *dest)
Definition: chm_lib.c:159
static BOOL _unmarshal_uint64(unsigned char **pData, unsigned int *pLenRemain, UInt64 *dest)
Definition: chm_lib.c:179
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117

Referenced by _chm_decompress_block().

◆ _chm_parse_cword()

static UInt64 _chm_parse_cword ( UChar **  pEntry)
static

Definition at line 892 of file chm_lib.c.

893{
894 UInt64 accum = 0;
895 UChar temp;
896 while ((temp=*(*pEntry)++) >= 0x80)
897 {
898 accum <<= 7;
899 accum += temp & 0x7f;
900 }
901
902 return (accum << 7) + temp;
903}
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484

Referenced by _chm_find_in_PMGI(), _chm_find_in_PMGL(), and _chm_parse_PMGL_entry().

◆ _chm_parse_PMGL_entry()

static BOOL _chm_parse_PMGL_entry ( UChar **  pEntry,
struct chmUnitInfo *  ui 
)
static

Definition at line 915 of file chm_lib.c.

916{
917 UInt64 strLen;
918
919 /* parse str len */
920 strLen = _chm_parse_cword(pEntry);
921 if (strLen > CHM_MAX_PATHLEN)
922 return FALSE;
923
924 /* parse path */
925 if (! _chm_parse_UTF8(pEntry, strLen, ui->path))
926 return FALSE;
927
928 /* parse info */
929 ui->space = (int)_chm_parse_cword(pEntry);
930 ui->start = _chm_parse_cword(pEntry);
931 ui->length = _chm_parse_cword(pEntry);
932 return TRUE;
933}
UINT ui
Definition: oleauto.h:49

Referenced by chm_enumerate_dir(), and chm_resolve_object().

◆ _chm_parse_UTF8()

static BOOL _chm_parse_UTF8 ( UChar **  pEntry,
UInt64  count,
WCHAR *  path 
)
static

Definition at line 906 of file chm_lib.c.

907{
909 path[length] = '\0';
910 *pEntry += count;
911 return !!length;
912}
#define MultiByteToWideChar
Definition: compat.h:110
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define CP_UTF8
Definition: nls.h:20

Referenced by _chm_find_in_PMGI(), _chm_find_in_PMGL(), and _chm_parse_PMGL_entry().

◆ _chm_skip_cword()

static void _chm_skip_cword ( UChar **  pEntry)
static

Definition at line 877 of file chm_lib.c.

878{
879 while (*(*pEntry)++ >= 0x80)
880 ;
881}

Referenced by _chm_skip_PMGL_entry_data().

◆ _chm_skip_PMGL_entry_data()

static void _chm_skip_PMGL_entry_data ( UChar **  pEntry)
static

Definition at line 884 of file chm_lib.c.

885{
889}
static void _chm_skip_cword(UChar **pEntry)
Definition: chm_lib.c:877

Referenced by _chm_find_in_PMGL().

◆ _unmarshal_char_array()

static BOOL _unmarshal_char_array ( unsigned char **  pData,
unsigned int *  pLenRemain,
char *  dest,
int  count 
)
static

Definition at line 109 of file chm_lib.c.

113{
114 if (count <= 0 || (unsigned int)count > *pLenRemain)
115 return FALSE;
116 memcpy(dest, (*pData), count);
117 *pData += count;
118 *pLenRemain -= count;
119 return TRUE;
120}
static char * dest
Definition: rtl.c:149
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830

Referenced by _unmarshal_itsf_header(), _unmarshal_itsp_header(), _unmarshal_lzxc_control_data(), _unmarshal_pmgi_header(), and _unmarshal_pmgl_header().

◆ _unmarshal_int32()

static BOOL _unmarshal_int32 ( unsigned char **  pData,
unsigned int *  pLenRemain,
Int32 *  dest 
)
static

Definition at line 135 of file chm_lib.c.

138{
139 if (4 > *pLenRemain)
140 return FALSE;
141 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24;
142 *pData += 4;
143 *pLenRemain -= 4;
144 return TRUE;
145}

Referenced by _unmarshal_itsf_header(), _unmarshal_itsp_header(), and _unmarshal_pmgl_header().

◆ _unmarshal_int64()

static BOOL _unmarshal_int64 ( unsigned char **  pData,
unsigned int *  pLenRemain,
Int64 *  dest 
)
static

Definition at line 159 of file chm_lib.c.

162{
163 Int64 temp;
164 int i;
165 if (8 > *pLenRemain)
166 return FALSE;
167 temp=0;
168 for(i=8; i>0; i--)
169 {
170 temp <<= 8;
171 temp |= (*pData)[i-1];
172 }
173 *dest = temp;
174 *pData += 8;
175 *pLenRemain -= 8;
176 return TRUE;
177}

Referenced by _chm_get_cmpblock_bounds().

◆ _unmarshal_itsf_header()

static BOOL _unmarshal_itsf_header ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmItsfHeader *  dest 
)
static

Definition at line 230 of file chm_lib.c.

233{
234 /* we only know how to deal with the 0x58 and 0x60 byte structures */
235 if (*pDataLen != _CHM_ITSF_V2_LEN && *pDataLen != _CHM_ITSF_V3_LEN)
236 return FALSE;
237
238 /* unmarshal common fields */
239 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
240 _unmarshal_int32 (pData, pDataLen, &dest->version);
241 _unmarshal_int32 (pData, pDataLen, &dest->header_len);
242 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c);
243 _unmarshal_uint32 (pData, pDataLen, &dest->last_modified);
244 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id);
245 _unmarshal_uuid (pData, pDataLen, dest->dir_uuid);
246 _unmarshal_uuid (pData, pDataLen, dest->stream_uuid);
247 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_offset);
248 _unmarshal_uint64 (pData, pDataLen, &dest->unknown_len);
249 _unmarshal_uint64 (pData, pDataLen, &dest->dir_offset);
250 _unmarshal_uint64 (pData, pDataLen, &dest->dir_len);
251
252 /* error check the data */
253 /* XXX: should also check UUIDs, probably, though with a version 3 file,
254 * current MS tools do not seem to use them.
255 */
256 if (memcmp(dest->signature, "ITSF", 4) != 0)
257 return FALSE;
258 if (dest->version == 2)
259 {
260 if (dest->header_len < _CHM_ITSF_V2_LEN)
261 return FALSE;
262 }
263 else if (dest->version == 3)
264 {
265 if (dest->header_len < _CHM_ITSF_V3_LEN)
266 return FALSE;
267 }
268 else
269 return FALSE;
270
271 /* now, if we have a V3 structure, unmarshal the rest.
272 * otherwise, compute it
273 */
274 if (dest->version == 3)
275 {
276 if (*pDataLen != 0)
277 _unmarshal_uint64(pData, pDataLen, &dest->data_offset);
278 else
279 return FALSE;
280 }
281 else
282 dest->data_offset = dest->dir_offset + dest->dir_len;
283
284 return TRUE;
285}
#define _CHM_ITSF_V2_LEN
Definition: chm_lib.c:211
static BOOL _unmarshal_int32(unsigned char **pData, unsigned int *pLenRemain, Int32 *dest)
Definition: chm_lib.c:135
static BOOL _unmarshal_uint32(unsigned char **pData, unsigned int *pLenRemain, UInt32 *dest)
Definition: chm_lib.c:147
static BOOL _unmarshal_uuid(unsigned char **pData, unsigned int *pDataLen, unsigned char *dest)
Definition: chm_lib.c:199
static BOOL _unmarshal_char_array(unsigned char **pData, unsigned int *pLenRemain, char *dest, int count)
Definition: chm_lib.c:109
#define _CHM_ITSF_V3_LEN
Definition: chm_lib.c:212
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807

Referenced by chm_openW().

◆ _unmarshal_itsp_header()

static BOOL _unmarshal_itsp_header ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmItspHeader *  dest 
)
static

Definition at line 308 of file chm_lib.c.

311{
312 /* we only know how to deal with a 0x54 byte structures */
313 if (*pDataLen != _CHM_ITSP_V1_LEN)
314 return FALSE;
315
316 /* unmarshal fields */
317 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
318 _unmarshal_int32 (pData, pDataLen, &dest->version);
319 _unmarshal_int32 (pData, pDataLen, &dest->header_len);
320 _unmarshal_int32 (pData, pDataLen, &dest->unknown_000c);
321 _unmarshal_uint32 (pData, pDataLen, &dest->block_len);
322 _unmarshal_int32 (pData, pDataLen, &dest->blockidx_intvl);
323 _unmarshal_int32 (pData, pDataLen, &dest->index_depth);
324 _unmarshal_int32 (pData, pDataLen, &dest->index_root);
325 _unmarshal_int32 (pData, pDataLen, &dest->index_head);
326 _unmarshal_int32 (pData, pDataLen, &dest->unknown_0024);
327 _unmarshal_uint32 (pData, pDataLen, &dest->num_blocks);
328 _unmarshal_int32 (pData, pDataLen, &dest->unknown_002c);
329 _unmarshal_uint32 (pData, pDataLen, &dest->lang_id);
330 _unmarshal_uuid (pData, pDataLen, dest->system_uuid);
331 _unmarshal_uchar_array(pData, pDataLen, dest->unknown_0044, 16);
332
333 /* error check the data */
334 if (memcmp(dest->signature, "ITSP", 4) != 0)
335 return FALSE;
336 if (dest->version != 1)
337 return FALSE;
338 if (dest->header_len != _CHM_ITSP_V1_LEN)
339 return FALSE;
340
341 return TRUE;
342}
static BOOL _unmarshal_uchar_array(unsigned char **pData, unsigned int *pLenRemain, unsigned char *dest, int count)
Definition: chm_lib.c:122
#define _CHM_ITSP_V1_LEN
Definition: chm_lib.c:288

Referenced by chm_openW().

◆ _unmarshal_lzxc_control_data()

static BOOL _unmarshal_lzxc_control_data ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmLzxcControlData *  dest 
)
static

Definition at line 457 of file chm_lib.c.

460{
461 /* we want at least 0x18 bytes */
462 if (*pDataLen < _CHM_LZXC_MIN_LEN)
463 return FALSE;
464
465 /* unmarshal fields */
466 _unmarshal_uint32 (pData, pDataLen, &dest->size);
467 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
468 _unmarshal_uint32 (pData, pDataLen, &dest->version);
469 _unmarshal_uint32 (pData, pDataLen, &dest->resetInterval);
470 _unmarshal_uint32 (pData, pDataLen, &dest->windowSize);
471 _unmarshal_uint32 (pData, pDataLen, &dest->windowsPerReset);
472
473 if (*pDataLen >= _CHM_LZXC_V2_LEN)
474 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_18);
475 else
476 dest->unknown_18 = 0;
477
478 if (dest->version == 2)
479 {
480 dest->resetInterval *= 0x8000;
481 dest->windowSize *= 0x8000;
482 }
483 if (dest->windowSize == 0 || dest->resetInterval == 0)
484 return FALSE;
485
486 /* for now, only support resetInterval a multiple of windowSize/2 */
487 if (dest->windowSize == 1)
488 return FALSE;
489 if ((dest->resetInterval % (dest->windowSize/2)) != 0)
490 return FALSE;
491
492 /* check structure */
493 if (memcmp(dest->signature, "LZXC", 4) != 0)
494 return FALSE;
495
496 return TRUE;
497}
#define _CHM_LZXC_V2_LEN
Definition: chm_lib.c:445
#define _CHM_LZXC_MIN_LEN
Definition: chm_lib.c:444

Referenced by chm_openW().

◆ _unmarshal_lzxc_reset_table()

static BOOL _unmarshal_lzxc_reset_table ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmLzxcResetTable *  dest 
)
static

Definition at line 419 of file chm_lib.c.

422{
423 /* we only know how to deal with a 0x28 byte structures */
424 if (*pDataLen != _CHM_LZXC_RESETTABLE_V1_LEN)
425 return FALSE;
426
427 /* unmarshal fields */
428 _unmarshal_uint32 (pData, pDataLen, &dest->version);
429 _unmarshal_uint32 (pData, pDataLen, &dest->block_count);
430 _unmarshal_uint32 (pData, pDataLen, &dest->unknown);
431 _unmarshal_uint32 (pData, pDataLen, &dest->table_offset);
432 _unmarshal_uint64 (pData, pDataLen, &dest->uncompressed_len);
433 _unmarshal_uint64 (pData, pDataLen, &dest->compressed_len);
434 _unmarshal_uint64 (pData, pDataLen, &dest->block_len);
435
436 /* check structure */
437 if (dest->version != 2)
438 return FALSE;
439
440 return TRUE;
441}
#define _CHM_LZXC_RESETTABLE_V1_LEN
Definition: chm_lib.c:407

Referenced by chm_openW().

◆ _unmarshal_pmgi_header()

static BOOL _unmarshal_pmgi_header ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmPmgiHeader *  dest 
)
static

Definition at line 387 of file chm_lib.c.

390{
391 /* we only know how to deal with a 0x8 byte structures */
392 if (*pDataLen != _CHM_PMGI_LEN)
393 return FALSE;
394
395 /* unmarshal fields */
396 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
397 _unmarshal_uint32 (pData, pDataLen, &dest->free_space);
398
399 /* check structure */
400 if (memcmp(dest->signature, _chm_pmgi_marker, 4) != 0)
401 return FALSE;
402
403 return TRUE;
404}
static const char _chm_pmgi_marker[4]
Definition: chm_lib.c:379

Referenced by _chm_find_in_PMGI().

◆ _unmarshal_pmgl_header()

static BOOL _unmarshal_pmgl_header ( unsigned char **  pData,
unsigned int *  pDataLen,
struct chmPmglHeader *  dest 
)
static

Definition at line 356 of file chm_lib.c.

359{
360 /* we only know how to deal with a 0x14 byte structures */
361 if (*pDataLen != _CHM_PMGL_LEN)
362 return FALSE;
363
364 /* unmarshal fields */
365 _unmarshal_char_array(pData, pDataLen, dest->signature, 4);
366 _unmarshal_uint32 (pData, pDataLen, &dest->free_space);
367 _unmarshal_uint32 (pData, pDataLen, &dest->unknown_0008);
368 _unmarshal_int32 (pData, pDataLen, &dest->block_prev);
369 _unmarshal_int32 (pData, pDataLen, &dest->block_next);
370
371 /* check structure */
372 if (memcmp(dest->signature, _chm_pmgl_marker, 4) != 0)
373 return FALSE;
374
375 return TRUE;
376}
static const char _chm_pmgl_marker[4]
Definition: chm_lib.c:345

Referenced by _chm_find_in_PMGL(), and chm_enumerate_dir().

◆ _unmarshal_uchar_array()

static BOOL _unmarshal_uchar_array ( unsigned char **  pData,
unsigned int *  pLenRemain,
unsigned char *  dest,
int  count 
)
static

Definition at line 122 of file chm_lib.c.

126{
127 if (count <= 0 || (unsigned int)count > *pLenRemain)
128 return FALSE;
129 memcpy(dest, (*pData), count);
130 *pData += count;
131 *pLenRemain -= count;
132 return TRUE;
133}

Referenced by _unmarshal_itsp_header(), and _unmarshal_uuid().

◆ _unmarshal_uint32()

static BOOL _unmarshal_uint32 ( unsigned char **  pData,
unsigned int *  pLenRemain,
UInt32 *  dest 
)
static

Definition at line 147 of file chm_lib.c.

150{
151 if (4 > *pLenRemain)
152 return FALSE;
153 *dest = (*pData)[0] | (*pData)[1]<<8 | (*pData)[2]<<16 | (*pData)[3]<<24;
154 *pData += 4;
155 *pLenRemain -= 4;
156 return TRUE;
157}

Referenced by _unmarshal_itsf_header(), _unmarshal_itsp_header(), _unmarshal_lzxc_control_data(), _unmarshal_lzxc_reset_table(), _unmarshal_pmgi_header(), and _unmarshal_pmgl_header().

◆ _unmarshal_uint64()

static BOOL _unmarshal_uint64 ( unsigned char **  pData,
unsigned int *  pLenRemain,
UInt64 *  dest 
)
static

Definition at line 179 of file chm_lib.c.

182{
183 UInt64 temp;
184 int i;
185 if (8 > *pLenRemain)
186 return FALSE;
187 temp=0;
188 for(i=8; i>0; i--)
189 {
190 temp <<= 8;
191 temp |= (*pData)[i-1];
192 }
193 *dest = temp;
194 *pData += 8;
195 *pLenRemain -= 8;
196 return TRUE;
197}

Referenced by _chm_get_cmpblock_bounds(), _unmarshal_itsf_header(), and _unmarshal_lzxc_reset_table().

◆ _unmarshal_uuid()

static BOOL _unmarshal_uuid ( unsigned char **  pData,
unsigned int *  pDataLen,
unsigned char *  dest 
)
static

Definition at line 199 of file chm_lib.c.

202{
203 return _unmarshal_uchar_array(pData, pDataLen, dest, 16);
204}

Referenced by _unmarshal_itsf_header(), and _unmarshal_itsp_header().

◆ chm_close()

void chm_close ( struct chmFile *  h)

Definition at line 835 of file chm_lib.c.

836{
837 if (h != NULL)
838 {
839 if (h->fd != CHM_NULL_FD)
840 CHM_CLOSE_FILE(h->fd);
841 h->fd = CHM_NULL_FD;
842
843 h->mutex.DebugInfo->Spare[0] = 0;
844 DeleteCriticalSection(&h->mutex);
845 h->lzx_mutex.DebugInfo->Spare[0] = 0;
846 DeleteCriticalSection(&h->lzx_mutex);
847 h->cache_mutex.DebugInfo->Spare[0] = 0;
848 DeleteCriticalSection(&h->cache_mutex);
849
850 if (h->lzx_state)
851 LZXteardown(h->lzx_state);
852 h->lzx_state = NULL;
853
854 if (h->cache_blocks)
855 {
856 int i;
857 for (i=0; i<h->cache_num_blocks; i++)
858 {
859 HeapFree(GetProcessHeap(), 0, h->cache_blocks[i]);
860 }
861 HeapFree(GetProcessHeap(), 0, h->cache_blocks);
862 h->cache_blocks = NULL;
863 }
864
865 HeapFree(GetProcessHeap(), 0, h->cache_block_indices);
866 h->cache_block_indices = NULL;
867
869 }
870}
#define CHM_CLOSE_FILE(fd)
Definition: chm_lib.c:78
void LZXteardown(struct LZXstate *pState)
Definition: lzx.c:209
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)

Referenced by chm_openW(), ITSProtocol_Start(), ITSS_IStorageImpl_Release(), and release_chm().

◆ chm_dup()

struct chmFile * chm_dup ( struct chmFile *  oldHandle)

Definition at line 803 of file chm_lib.c.

804{
805 struct chmFile *newHandle=NULL;
806
807 newHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(struct chmFile));
808 *newHandle = *oldHandle;
809
810 /* duplicate fd handle */
812 GetCurrentProcess(), &(newHandle->fd),
814 newHandle->lzx_state = NULL;
815 newHandle->cache_blocks = NULL;
816 newHandle->cache_block_indices = NULL;
817 newHandle->cache_num_blocks = 0;
818
819 /* initialize mutexes, if needed */
821 newHandle->mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.mutex");
823 newHandle->lzx_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.lzx_mutex");
825 newHandle->cache_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.cache_mutex");
826
827 /* initialize cache */
830
831 return newHandle;
832}
static void chm_set_param(struct chmFile *h, int paramType, int paramVal)
Definition: chm_lib.c:588
#define CHM_MAX_BLOCKS_CACHED
Definition: chm_lib.c:84
#define CHM_PARAM_MAX_BLOCKS_CACHED
Definition: chm_lib.c:86
#define GetCurrentProcess()
Definition: compat.h:759
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
BOOL WINAPI InitializeCriticalSectionEx(OUT LPCRITICAL_SECTION lpCriticalSection, IN DWORD dwSpinCount, IN DWORD flags)
Definition: sync.c:107
PRTL_CRITICAL_SECTION_DEBUG DebugInfo
Definition: rtltypes.h:1478
Int64 * cache_block_indices
Definition: chm_lib.c:532
Int32 cache_num_blocks
Definition: chm_lib.c:533
HANDLE fd
Definition: chm_lib.c:502
CRITICAL_SECTION cache_mutex
Definition: chm_lib.c:506
UChar ** cache_blocks
Definition: chm_lib.c:531
struct LZXstate * lzx_state
Definition: chm_lib.c:527
CRITICAL_SECTION lzx_mutex
Definition: chm_lib.c:505
CRITICAL_SECTION mutex
Definition: chm_lib.c:504
#define DWORD_PTR
Definition: treelist.c:76
#define RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
Definition: winnt_old.h:1156
#define DUPLICATE_SAME_ACCESS

Referenced by ITSS_IStorageImpl_OpenStorage().

◆ chm_enumerate_dir()

BOOL chm_enumerate_dir ( struct chmFile *  h,
const WCHAR *  prefix,
int  what,
CHM_ENUMERATOR  e,
void *  context 
)

Definition at line 1372 of file chm_lib.c.

1377{
1378 /*
1379 * XXX: do this efficiently (i.e. using the tree index)
1380 */
1381
1382 Int32 curPage;
1383
1384 /* buffer to hold whatever page we're looking at */
1385 UChar *page_buf = HeapAlloc(GetProcessHeap(), 0, h->block_len);
1386 struct chmPmglHeader header;
1387 UChar *end;
1388 UChar *cur;
1389 unsigned int lenRemain;
1390
1391 /* set to TRUE once we've started */
1392 BOOL it_has_begun = FALSE;
1393
1394 /* the current ui */
1395 struct chmUnitInfo ui;
1396 int flag;
1397 UInt64 ui_path_len;
1398
1399 /* the length of the prefix */
1400 WCHAR prefixRectified[CHM_MAX_PATHLEN+1];
1401 int prefixLen;
1402 WCHAR lastPath[CHM_MAX_PATHLEN];
1403 int lastPathLen;
1404
1405 /* starting page */
1406 curPage = h->index_head;
1407
1408 /* initialize pathname state */
1409 lstrcpynW(prefixRectified, prefix, CHM_MAX_PATHLEN);
1410 prefixLen = lstrlenW(prefixRectified);
1411 if (prefixLen != 0)
1412 {
1413 if (prefixRectified[prefixLen-1] != '/')
1414 {
1415 prefixRectified[prefixLen] = '/';
1416 prefixRectified[prefixLen+1] = '\0';
1417 ++prefixLen;
1418 }
1419 }
1420 lastPath[0] = '\0';
1421 lastPathLen = -1;
1422
1423 /* until we have either returned or given up */
1424 while (curPage != -1)
1425 {
1426
1427 /* try to fetch the index page */
1428 if (_chm_fetch_bytes(h,
1429 page_buf,
1430 h->dir_offset + (UInt64)curPage*h->block_len,
1431 h->block_len) != h->block_len)
1432 {
1433 HeapFree(GetProcessHeap(), 0, page_buf);
1434 return FALSE;
1435 }
1436
1437 /* figure out start and end for this page */
1438 cur = page_buf;
1439 lenRemain = _CHM_PMGL_LEN;
1440 if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header))
1441 {
1442 HeapFree(GetProcessHeap(), 0, page_buf);
1443 return FALSE;
1444 }
1445 end = page_buf + h->block_len - (header.free_space);
1446
1447 /* loop over this page */
1448 while (cur < end)
1449 {
1450 if (! _chm_parse_PMGL_entry(&cur, &ui))
1451 {
1452 HeapFree(GetProcessHeap(), 0, page_buf);
1453 return FALSE;
1454 }
1455
1456 /* check if we should start */
1457 if (! it_has_begun)
1458 {
1459 if (ui.length == 0 && wcsnicmp(ui.path, prefixRectified, prefixLen) == 0)
1460 it_has_begun = TRUE;
1461 else
1462 continue;
1463
1464 if (ui.path[prefixLen] == '\0')
1465 continue;
1466 }
1467
1468 /* check if we should stop */
1469 else
1470 {
1471 if (wcsnicmp(ui.path, prefixRectified, prefixLen) != 0)
1472 {
1473 HeapFree(GetProcessHeap(), 0, page_buf);
1474 return TRUE;
1475 }
1476 }
1477
1478 /* check if we should include this path */
1479 if (lastPathLen != -1)
1480 {
1481 if (wcsnicmp(ui.path, lastPath, lastPathLen) == 0)
1482 continue;
1483 }
1484 lstrcpyW(lastPath, ui.path);
1485 lastPathLen = lstrlenW(lastPath);
1486
1487 /* get the length of the path */
1488 ui_path_len = lstrlenW(ui.path)-1;
1489
1490 /* check for DIRS */
1491 if (ui.path[ui_path_len] == '/' && !(what & CHM_ENUMERATE_DIRS))
1492 continue;
1493
1494 /* check for FILES */
1495 if (ui.path[ui_path_len] != '/' && !(what & CHM_ENUMERATE_FILES))
1496 continue;
1497
1498 /* check for NORMAL vs. META */
1499 if (ui.path[0] == '/')
1500 {
1501
1502 /* check for NORMAL vs. SPECIAL */
1503 if (ui.path[1] == '#' || ui.path[1] == '$')
1505 else
1507 }
1508 else
1510 if (! (what & flag))
1511 continue;
1512
1513 /* call the enumerator */
1514 {
1515 int status = (*e)(h, &ui, context);
1516 switch (status)
1517 {
1519 HeapFree(GetProcessHeap(), 0, page_buf);
1520 return FALSE;
1522 break;
1524 HeapFree(GetProcessHeap(), 0, page_buf);
1525 return TRUE;
1526 default:
1527 break;
1528 }
1529 }
1530 }
1531
1532 /* advance to next page */
1533 curPage = header.block_next;
1534 }
1535
1536 HeapFree(GetProcessHeap(), 0, page_buf);
1537 return TRUE;
1538}
LONG Int32
Definition: chm_lib.c:103
static BOOL _chm_parse_PMGL_entry(UChar **pEntry, struct chmUnitInfo *ui)
Definition: chm_lib.c:915
#define CHM_ENUMERATE_NORMAL
Definition: chm_lib.h:94
#define CHM_ENUMERATOR_CONTINUE
Definition: chm_lib.h:101
#define CHM_ENUMERATE_META
Definition: chm_lib.h:95
#define CHM_ENUMERATE_SPECIAL
Definition: chm_lib.h:96
#define CHM_ENUMERATE_DIRS
Definition: chm_lib.h:98
#define CHM_ENUMERATE_FILES
Definition: chm_lib.h:97
#define CHM_ENUMERATOR_SUCCESS
Definition: chm_lib.h:102
#define CHM_ENUMERATOR_FAILURE
Definition: chm_lib.h:100
#define wcsnicmp
Definition: compat.h:14
#define lstrcpyW
Definition: compat.h:749
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
unsigned int BOOL
Definition: ntddk_ex.h:94
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
Definition: http.c:7252
Definition: ps.c:97
Character const *const prefix
Definition: tempnam.cpp:195

Referenced by ITSS_IStorageImpl_EnumElements().

◆ chm_openW()

struct chmFile * chm_openW ( const WCHAR *  filename)

Definition at line 653 of file chm_lib.c.

654{
655 unsigned char sbuffer[256];
656 unsigned int sremain;
657 unsigned char *sbufpos;
658 struct chmFile *newHandle=NULL;
659 struct chmItsfHeader itsfHeader;
660 struct chmItspHeader itspHeader;
661#if 0
662 struct chmUnitInfo uiSpan;
663#endif
664 struct chmUnitInfo uiLzxc;
665 struct chmLzxcControlData ctlData;
666
667 /* allocate handle */
668 newHandle = HeapAlloc(GetProcessHeap(), 0, sizeof(struct chmFile));
669 newHandle->fd = CHM_NULL_FD;
670 newHandle->lzx_state = NULL;
671 newHandle->cache_blocks = NULL;
672 newHandle->cache_block_indices = NULL;
673 newHandle->cache_num_blocks = 0;
674
675 /* open file */
676 if ((newHandle->fd=CreateFileW(filename,
679 NULL,
682 NULL)) == CHM_NULL_FD)
683 {
684 HeapFree(GetProcessHeap(), 0, newHandle);
685 return NULL;
686 }
687
688 /* initialize mutexes, if needed */
690 newHandle->mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.mutex");
692 newHandle->lzx_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.lzx_mutex");
694 newHandle->cache_mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": chmFile.cache_mutex");
695
696 /* read and verify header */
697 sremain = _CHM_ITSF_V3_LEN;
698 sbufpos = sbuffer;
699 if (_chm_fetch_bytes(newHandle, sbuffer, 0, sremain) != sremain ||
700 !_unmarshal_itsf_header(&sbufpos, &sremain, &itsfHeader))
701 {
702 chm_close(newHandle);
703 return NULL;
704 }
705
706 /* stash important values from header */
707 newHandle->dir_offset = itsfHeader.dir_offset;
708 newHandle->dir_len = itsfHeader.dir_len;
709 newHandle->data_offset = itsfHeader.data_offset;
710
711 /* now, read and verify the directory header chunk */
712 sremain = _CHM_ITSP_V1_LEN;
713 sbufpos = sbuffer;
714 if (_chm_fetch_bytes(newHandle, sbuffer,
715 itsfHeader.dir_offset, sremain) != sremain ||
716 !_unmarshal_itsp_header(&sbufpos, &sremain, &itspHeader))
717 {
718 chm_close(newHandle);
719 return NULL;
720 }
721
722 /* grab essential information from ITSP header */
723 newHandle->dir_offset += itspHeader.header_len;
724 newHandle->dir_len -= itspHeader.header_len;
725 newHandle->index_root = itspHeader.index_root;
726 newHandle->index_head = itspHeader.index_head;
727 newHandle->block_len = itspHeader.block_len;
728
729 /* if the index root is -1, this means we don't have any PMGI blocks.
730 * as a result, we must use the sole PMGL block as the index root
731 */
732 if (newHandle->index_root == -1)
733 newHandle->index_root = newHandle->index_head;
734
735 /* initialize cache */
738
739 /* By default, compression is enabled. */
740 newHandle->compression_enabled = 1;
741
742 /* prefetch most commonly needed unit infos */
744 L"::DataSpace/Storage/MSCompressed/Transform/"
745 "{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/"
746 "InstanceData/ResetTable",
747 &newHandle->rt_unit) ||
748 newHandle->rt_unit.space == CHM_COMPRESSED ||
750 L"::DataSpace/Storage/MSCompressed/Content",
751 &newHandle->cn_unit) ||
752 newHandle->cn_unit.space == CHM_COMPRESSED ||
754 L"::DataSpace/Storage/MSCompressed/ControlData",
755 &uiLzxc) ||
756 uiLzxc.space == CHM_COMPRESSED)
757 {
758 newHandle->compression_enabled = 0;
759 }
760
761 /* read reset table info */
762 if (newHandle->compression_enabled)
763 {
765 sbufpos = sbuffer;
766 if (chm_retrieve_object(newHandle, &newHandle->rt_unit, sbuffer,
767 0, sremain) != sremain ||
768 !_unmarshal_lzxc_reset_table(&sbufpos, &sremain,
769 &newHandle->reset_table))
770 {
771 newHandle->compression_enabled = 0;
772 }
773 }
774
775 /* read control data */
776 if (newHandle->compression_enabled)
777 {
778 sremain = (unsigned long)uiLzxc.length;
779 sbufpos = sbuffer;
780 if (chm_retrieve_object(newHandle, &uiLzxc, sbuffer,
781 0, sremain) != sremain ||
782 !_unmarshal_lzxc_control_data(&sbufpos, &sremain,
783 &ctlData))
784 {
785 newHandle->compression_enabled = 0;
786 }
787 else
788 {
789 newHandle->window_size = ctlData.windowSize;
790 newHandle->reset_interval = ctlData.resetInterval;
791/* Jed, Mon Jun 28: Experimentally, it appears that the reset block count */
792/* must be multiplied by this formerly unknown ctrl data field in */
793/* order to decompress some files. */
794 newHandle->reset_blkcount = newHandle->reset_interval / (newHandle->window_size / 2) *
795 ctlData.windowsPerReset;
796 }
797 }
798
799 return newHandle;
800}
LONGINT64 chm_retrieve_object(struct chmFile *h, struct chmUnitInfo *ui, unsigned char *buf, LONGUINT64 addr, LONGINT64 len)
Definition: chm_lib.c:1314
int chm_resolve_object(struct chmFile *h, const WCHAR *objPath, struct chmUnitInfo *ui)
Definition: chm_lib.c:1020
static BOOL _unmarshal_itsp_header(unsigned char **pData, unsigned int *pDataLen, struct chmItspHeader *dest)
Definition: chm_lib.c:308
static BOOL _unmarshal_lzxc_reset_table(unsigned char **pData, unsigned int *pDataLen, struct chmLzxcResetTable *dest)
Definition: chm_lib.c:419
static BOOL _unmarshal_lzxc_control_data(unsigned char **pData, unsigned int *pDataLen, struct chmLzxcControlData *dest)
Definition: chm_lib.c:457
static BOOL _unmarshal_itsf_header(unsigned char **pData, unsigned int *pDataLen, struct chmItsfHeader *dest)
Definition: chm_lib.c:230
void chm_close(struct chmFile *h)
Definition: chm_lib.c:835
#define CHM_COMPRESSED
Definition: chm_lib.h:60
#define CHM_RESOLVE_SUCCESS
Definition: chm_lib.h:82
#define OPEN_EXISTING
Definition: compat.h:775
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define L(x)
Definition: resources.c:13
const char * filename
Definition: ioapi.h:137
if(dx< 0)
Definition: linetemp.h:194
#define long
Definition: qsort.c:33
UInt32 reset_blkcount
Definition: chm_lib.c:524
UInt32 window_size
Definition: chm_lib.c:522
Int32 index_root
Definition: chm_lib.c:511
UInt64 dir_offset
Definition: chm_lib.c:508
struct chmUnitInfo rt_unit
Definition: chm_lib.c:516
struct chmUnitInfo cn_unit
Definition: chm_lib.c:517
int compression_enabled
Definition: chm_lib.c:521
Int32 index_head
Definition: chm_lib.c:512
UInt32 reset_interval
Definition: chm_lib.c:523
UInt64 dir_len
Definition: chm_lib.c:509
UInt64 data_offset
Definition: chm_lib.c:510
UInt32 block_len
Definition: chm_lib.c:513
struct chmLzxcResetTable reset_table
Definition: chm_lib.c:518

Referenced by ITSProtocol_Start(), and ITSS_StgOpenStorage().

◆ chm_resolve_object()

int chm_resolve_object ( struct chmFile *  h,
const WCHAR *  objPath,
struct chmUnitInfo *  ui 
)

Definition at line 1020 of file chm_lib.c.

1023{
1024 /*
1025 * XXX: implement caching scheme for dir pages
1026 */
1027
1028 Int32 curPage;
1029
1030 /* buffer to hold whatever page we're looking at */
1031 UChar *page_buf = HeapAlloc(GetProcessHeap(), 0, h->block_len);
1032
1033 /* starting page */
1034 curPage = h->index_root;
1035
1036 /* until we have either returned or given up */
1037 while (curPage != -1)
1038 {
1039
1040 /* try to fetch the index page */
1041 if (_chm_fetch_bytes(h, page_buf,
1042 h->dir_offset + (UInt64)curPage*h->block_len,
1043 h->block_len) != h->block_len)
1044 {
1045 HeapFree(GetProcessHeap(), 0, page_buf);
1046 return CHM_RESOLVE_FAILURE;
1047 }
1048
1049 /* now, if it is a leaf node: */
1050 if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0)
1051 {
1052 /* scan block */
1053 UChar *pEntry = _chm_find_in_PMGL(page_buf,
1054 h->block_len,
1055 objPath);
1056 if (pEntry == NULL)
1057 {
1058 HeapFree(GetProcessHeap(), 0, page_buf);
1059 return CHM_RESOLVE_FAILURE;
1060 }
1061
1062 /* parse entry and return */
1064 HeapFree(GetProcessHeap(), 0, page_buf);
1065 return CHM_RESOLVE_SUCCESS;
1066 }
1067
1068 /* else, if it is a branch node: */
1069 else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0)
1070 curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath);
1071
1072 /* else, we are confused. give up. */
1073 else
1074 {
1075 HeapFree(GetProcessHeap(), 0, page_buf);
1076 return CHM_RESOLVE_FAILURE;
1077 }
1078 }
1079
1080 /* didn't find anything. fail. */
1081 HeapFree(GetProcessHeap(), 0, page_buf);
1082 return CHM_RESOLVE_FAILURE;
1083}
static Int32 _chm_find_in_PMGI(UChar *page_buf, UInt32 block_len, const WCHAR *objPath)
Definition: chm_lib.c:978
static UChar * _chm_find_in_PMGL(UChar *page_buf, UInt32 block_len, const WCHAR *objPath)
Definition: chm_lib.c:936
#define CHM_RESOLVE_FAILURE
Definition: chm_lib.h:83

Referenced by chm_openW(), ITSProtocol_Start(), and ITSS_IStorageImpl_OpenStream().

◆ chm_retrieve_object()

LONGINT64 chm_retrieve_object ( struct chmFile *  h,
struct chmUnitInfo *  ui,
unsigned char *  buf,
LONGUINT64  addr,
LONGINT64  len 
)

Definition at line 1314 of file chm_lib.c.

1319{
1320 /* must be valid file handle */
1321 if (h == NULL)
1322 return 0;
1323
1324 /* starting address must be in correct range */
1325 if (addr >= ui->length)
1326 return 0;
1327
1328 /* clip length */
1329 if (addr + len > ui->length)
1330 len = ui->length - addr;
1331
1332 /* if the file is uncompressed, it's simple */
1333 if (ui->space == CHM_UNCOMPRESSED)
1334 {
1335 /* read data */
1336 return _chm_fetch_bytes(h,
1337 buf,
1338 h->data_offset + ui->start + addr,
1339 len);
1340 }
1341
1342 /* else if the file is compressed, it's a little trickier */
1343 else /* ui->space == CHM_COMPRESSED */
1344 {
1345 Int64 swath=0, total=0;
1346
1347 /* if compression is not enabled for this file... */
1348 if (! h->compression_enabled)
1349 return total;
1350
1351 do {
1352
1353 /* swill another mouthful */
1354 swath = _chm_decompress_region(h, buf, ui->start + addr, len);
1355
1356 /* if we didn't get any... */
1357 if (swath == 0)
1358 return total;
1359
1360 /* update stats */
1361 total += swath;
1362 len -= swath;
1363 addr += swath;
1364 buf += swath;
1365
1366 } while (len != 0);
1367
1368 return total;
1369 }
1370}
static Int64 _chm_decompress_region(struct chmFile *h, UChar *buf, UInt64 start, Int64 len)
Definition: chm_lib.c:1262
#define CHM_UNCOMPRESSED
Definition: chm_lib.h:59
size_t total
GLenum const GLvoid * addr
Definition: glext.h:9621

Referenced by chm_openW(), ITSProtocol_Read(), and ITSS_IStream_Read().

◆ chm_set_param()

static void chm_set_param ( struct chmFile *  h,
int  paramType,
int  paramVal 
)
static

Definition at line 588 of file chm_lib.c.

591{
592 switch (paramType)
593 {
595 CHM_ACQUIRE_LOCK(h->cache_mutex);
596 if (paramVal != h->cache_num_blocks)
597 {
598 UChar **newBlocks;
599 Int64 *newIndices;
600 int i;
601
602 /* allocate new cached blocks */
603 newBlocks = HeapAlloc(GetProcessHeap(), 0, paramVal * sizeof (UChar *));
604 newIndices = HeapAlloc(GetProcessHeap(), 0, paramVal * sizeof (UInt64));
605 for (i=0; i<paramVal; i++)
606 {
607 newBlocks[i] = NULL;
608 newIndices[i] = 0;
609 }
610
611 /* re-distribute old cached blocks */
612 if (h->cache_blocks)
613 {
614 for (i=0; i<h->cache_num_blocks; i++)
615 {
616 int newSlot = (int)(h->cache_block_indices[i] % paramVal);
617
618 if (h->cache_blocks[i])
619 {
620 /* in case of collision, destroy newcomer */
621 if (newBlocks[newSlot])
622 {
623 HeapFree(GetProcessHeap(), 0, h->cache_blocks[i]);
624 h->cache_blocks[i] = NULL;
625 }
626 else
627 {
628 newBlocks[newSlot] = h->cache_blocks[i];
629 newIndices[newSlot] =
630 h->cache_block_indices[i];
631 }
632 }
633 }
634
635 HeapFree(GetProcessHeap(), 0, h->cache_blocks);
636 HeapFree(GetProcessHeap(), 0, h->cache_block_indices);
637 }
638
639 /* now, set new values */
640 h->cache_blocks = newBlocks;
641 h->cache_block_indices = newIndices;
642 h->cache_num_blocks = paramVal;
643 }
644 CHM_RELEASE_LOCK(h->cache_mutex);
645 break;
646
647 default:
648 break;
649 }
650}

Referenced by chm_dup(), and chm_openW().

Variable Documentation

◆ _chm_pmgi_marker

const char _chm_pmgi_marker[4] = "PMGI"
static

Definition at line 379 of file chm_lib.c.

Referenced by _unmarshal_pmgi_header(), and chm_resolve_object().

◆ _chm_pmgl_marker

const char _chm_pmgl_marker[4] = "PMGL"
static

Definition at line 345 of file chm_lib.c.

Referenced by _unmarshal_pmgl_header(), and chm_resolve_object().