From e717dcc8fab3ba5e4a268371df34070018708274 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 22 Feb 2007 22:51:36 +0100 Subject: [PATCH] hhctrl.ocx: Rewrite reading strings from #STRINGS section. --- dlls/hhctrl.ocx/chm.c | 123 ++++++++++++++++++++++++++++------------------- dlls/hhctrl.ocx/hhctrl.h | 9 ++++ 2 files changed, 82 insertions(+), 50 deletions(-) diff --git a/dlls/hhctrl.ocx/chm.c b/dlls/hhctrl.ocx/chm.c index 2fad67c69c1..9fc98c60387 100644 --- a/dlls/hhctrl.ocx/chm.c +++ b/dlls/hhctrl.ocx/chm.c @@ -2,6 +2,7 @@ * CHM Utility API * * Copyright 2005 James Hawkins + * Copyright 2007 Jacek Caban * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,57 +21,55 @@ #include "hhctrl.h" -/* Reads a string from the #STRINGS section in the CHM file */ -static LPWSTR CHM_ReadString(CHMInfo *pChmInfo, DWORD dwOffset) -{ - LARGE_INTEGER liOffset; - IStorage *pStorage = pChmInfo->pStorage; - IStream *pStream; - DWORD cbRead; - ULONG iPos; - DWORD dwSize; - LPSTR szString; - LPWSTR stringW; - - const int CB_READ_BLOCK = 64; - static const WCHAR stringsW[] = {'#','S','T','R','I','N','G','S',0}; +#include "wine/debug.h" - dwSize = CB_READ_BLOCK; - szString = hhctrl_alloc(dwSize); +WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp); - if (FAILED(IStorage_OpenStream(pStorage, stringsW, NULL, STGM_READ, 0, &pStream))) - return NULL; +#define BLOCK_BITS 12 +#define BLOCK_SIZE (1 << BLOCK_BITS) +#define BLOCK_MASK (BLOCK_SIZE-1) - liOffset.QuadPart = dwOffset; - - if (FAILED(IStream_Seek(pStream, liOffset, STREAM_SEEK_SET, NULL))) - { - IStream_Release(pStream); +/* Reads a string from the #STRINGS section in the CHM file */ +static LPCSTR GetChmString(CHMInfo *chm, DWORD offset) +{ + if(!chm->strings_stream) return NULL; + + if(chm->strings_size <= (offset >> BLOCK_BITS)) { + if(chm->strings) + chm->strings = hhctrl_realloc_zero(chm->strings, + chm->strings_size = ((offset >> BLOCK_BITS)+1)*sizeof(char*)); + else + chm->strings = hhctrl_alloc_zero( + chm->strings_size = ((offset >> BLOCK_BITS)+1)*sizeof(char*)); + } - while (SUCCEEDED(IStream_Read(pStream, szString, CB_READ_BLOCK, &cbRead))) - { - if (!cbRead) - return NULL; + if(!chm->strings[offset >> BLOCK_BITS]) { + LARGE_INTEGER pos; + DWORD read; + HRESULT hres; - for (iPos = 0; iPos < cbRead; iPos++) - { - if (!szString[iPos]) - { - stringW = strdupAtoW(szString); - hhctrl_free(szString); - return stringW; - } + pos.QuadPart = offset & ~BLOCK_MASK; + hres = IStream_Seek(chm->strings_stream, pos, STREAM_SEEK_SET, NULL); + if(FAILED(hres)) { + WARN("Seek failed: %08x\n", hres); + return NULL; } - dwSize *= 2; - szString = hhctrl_realloc(szString, dwSize); - szString += cbRead; + chm->strings[offset >> BLOCK_BITS] = hhctrl_alloc(BLOCK_SIZE); + + hres = IStream_Read(chm->strings_stream, chm->strings[offset >> BLOCK_BITS], + BLOCK_SIZE, &read); + if(FAILED(hres)) { + WARN("Read failed: %08x\n", hres); + hhctrl_free(chm->strings[offset >> BLOCK_BITS]); + chm->strings[offset >> BLOCK_BITS] = NULL; + return NULL; + } } - /* didn't find a string */ - return NULL; + return chm->strings[offset >> BLOCK_BITS] + (offset & BLOCK_MASK); } /* Loads the HH_WINTYPE data from the CHM file @@ -103,16 +102,16 @@ BOOL CHM_LoadWinTypeFromCHM(CHMInfo *pChmInfo, HH_WINTYPEW *pHHWinType) if (FAILED(hr)) goto done; /* convert the #STRINGS offsets to actual strings */ - pHHWinType->pszType = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszType); - pHHWinType->pszCaption = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszCaption); - pHHWinType->pszToc = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszToc); - pHHWinType->pszIndex = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszIndex); - pHHWinType->pszFile = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszFile); - pHHWinType->pszHome = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszHome); - pHHWinType->pszJump1 = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszJump1); - pHHWinType->pszJump2 = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszJump2); - pHHWinType->pszUrlJump1 = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszUrlJump1); - pHHWinType->pszUrlJump2 = CHM_ReadString(pChmInfo, (DWORD)pHHWinType->pszUrlJump2); + pHHWinType->pszType = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszType)); + pHHWinType->pszCaption = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszCaption)); + pHHWinType->pszToc = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszToc)); + pHHWinType->pszIndex = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszIndex)); + pHHWinType->pszFile = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszFile)); + pHHWinType->pszHome = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszHome)); + pHHWinType->pszJump1 = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszJump1)); + pHHWinType->pszJump2 = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszJump2)); + pHHWinType->pszUrlJump1 = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszUrlJump1)); + pHHWinType->pszUrlJump2 = strdupAtoW(GetChmString(pChmInfo, (DWORD)pHHWinType->pszUrlJump2)); /* FIXME: pszCustomTabs is a list of multiple zero-terminated strings so ReadString won't * work in this case @@ -130,6 +129,10 @@ done: /* Opens the CHM file for reading */ BOOL CHM_OpenCHM(CHMInfo *pChmInfo, LPCWSTR szFile) { + HRESULT hres; + + static const WCHAR wszSTRINGS[] = {'#','S','T','R','I','N','G','S',0}; + pChmInfo->szFile = szFile; if (FAILED(CoCreateInstance(&CLSID_ITStorage, NULL, CLSCTX_INPROC_SERVER, @@ -141,6 +144,16 @@ BOOL CHM_OpenCHM(CHMInfo *pChmInfo, LPCWSTR szFile) NULL, 0, &pChmInfo->pStorage))) return FALSE; + hres = IStorage_OpenStream(pChmInfo->pStorage, wszSTRINGS, NULL, STGM_READ, 0, + &pChmInfo->strings_stream); + if(FAILED(hres)) { + WARN("Could not open #STRINGS stream: %08x\n", hres); + return FALSE; + } + + pChmInfo->strings = NULL; + pChmInfo->strings_size = 0; + return TRUE; } @@ -148,4 +161,14 @@ void CHM_CloseCHM(CHMInfo *pCHMInfo) { IITStorage_Release(pCHMInfo->pITStorage); IStorage_Release(pCHMInfo->pStorage); + IStream_Release(pCHMInfo->strings_stream); + + if(pCHMInfo->strings_size) { + int i; + + for(i=0; istrings_size; i++) + hhctrl_free(pCHMInfo->strings[i]); + } + + hhctrl_free(pCHMInfo->strings); } diff --git a/dlls/hhctrl.ocx/hhctrl.h b/dlls/hhctrl.ocx/hhctrl.h index 42576872ea4..355fc02f796 100644 --- a/dlls/hhctrl.ocx/hhctrl.h +++ b/dlls/hhctrl.ocx/hhctrl.h @@ -50,6 +50,10 @@ typedef struct CHMInfo IITStorage *pITStorage; IStorage *pStorage; LPCWSTR szFile; + + IStream *strings_stream; + char **strings; + DWORD strings_size; } CHMInfo; @@ -87,6 +91,11 @@ static inline void *hhctrl_realloc(void *mem, size_t len) return HeapReAlloc(GetProcessHeap(), 0, mem, len); } +static inline void *hhctrl_realloc_zero(void *mem, size_t len) +{ + return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len); +} + static inline BOOL hhctrl_free(void *mem) { return HeapFree(GetProcessHeap(), 0, mem); -- 2.11.4.GIT