Jacek Caban : hhctrl.ocx: Rewrite reading strings from #STRINGS
section.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Feb 23 05:28:20 CST 2007
Module: wine
Branch: master
Commit: e717dcc8fab3ba5e4a268371df34070018708274
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e717dcc8fab3ba5e4a268371df34070018708274
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Feb 22 22:51:36 2007 +0100
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 2fad67c..9fc98c6 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; i<pCHMInfo->strings_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 4257687..355fc02 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);
More information about the wine-cvs
mailing list