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