[1/2] winhlp32: Reorder some functions to avoid forward declarations in hlpfile.c.
Francois Gouget
fgouget at free.fr
Thu Jan 8 07:17:00 CST 2009
---
programs/winhlp32/hlpfile.c | 1456 +++++++++++++++++++++----------------------
1 files changed, 719 insertions(+), 737 deletions(-)
diff --git a/programs/winhlp32/hlpfile.c b/programs/winhlp32/hlpfile.c
index 99043ac..913cdab 100644
--- a/programs/winhlp32/hlpfile.c
+++ b/programs/winhlp32/hlpfile.c
@@ -51,25 +51,315 @@ static inline unsigned GET_UINT(const BYTE* buffer, unsigned i)
static HLPFILE *first_hlpfile = 0;
-static BOOL HLPFILE_DoReadHlpFile(HLPFILE*, LPCSTR);
-static BOOL HLPFILE_ReadFileToBuffer(HLPFILE*, HFILE);
-static BOOL HLPFILE_FindSubFile(HLPFILE*, LPCSTR, BYTE**, BYTE**);
-static BOOL HLPFILE_SystemCommands(HLPFILE*);
-static INT HLPFILE_UncompressedLZ77_Size(const BYTE *ptr, const BYTE *end);
-static BYTE* HLPFILE_UncompressLZ77(const BYTE *ptr, const BYTE *end, BYTE *newptr);
-static BOOL HLPFILE_UncompressLZ77_Phrases(HLPFILE*);
-static BOOL HLPFILE_Uncompress_Phrases40(HLPFILE*);
-static BOOL HLPFILE_Uncompress_Topic(HLPFILE*);
-static BOOL HLPFILE_GetContext(HLPFILE*);
-static BOOL HLPFILE_GetKeywords(HLPFILE*);
-static BOOL HLPFILE_GetMap(HLPFILE*);
-static BOOL HLPFILE_GetTOMap(HLPFILE*);
-static BOOL HLPFILE_AddPage(HLPFILE*, const BYTE*, const BYTE*, unsigned, unsigned);
-static BOOL HLPFILE_SkipParagraph(HLPFILE*, const BYTE*, const BYTE*, unsigned*);
-static void HLPFILE_Uncompress2(HLPFILE*, const BYTE*, const BYTE*, BYTE*, const BYTE*);
-static BOOL HLPFILE_Uncompress3(HLPFILE*, char*, const char*, const BYTE*, const BYTE*);
-static void HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE* dst, unsigned dstsz);
-static BOOL HLPFILE_ReadFont(HLPFILE* hlpfile);
+
+/**************************************************************************
+ * HLPFILE_BPTreeSearch
+ *
+ * Searches for an element in B+ tree
+ *
+ * PARAMS
+ * buf [I] pointer to the embedded file structured as a B+ tree
+ * key [I] pointer to data to find
+ * comp [I] compare function
+ *
+ * RETURNS
+ * Pointer to block identified by key, or NULL if failure.
+ *
+ */
+void* HLPFILE_BPTreeSearch(BYTE* buf, const void* key,
+ HLPFILE_BPTreeCompare comp)
+{
+ unsigned magic;
+ unsigned page_size;
+ unsigned cur_page;
+ unsigned level;
+ BYTE *pages, *ptr, *newptr;
+ int i, entries;
+ int ret;
+
+ magic = GET_USHORT(buf, 9);
+ if (magic != 0x293B)
+ {
+ WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
+ return NULL;
+ }
+ page_size = GET_USHORT(buf, 9+4);
+ cur_page = GET_USHORT(buf, 9+26);
+ level = GET_USHORT(buf, 9+32);
+ pages = buf + 9 + 38;
+ while (--level > 0)
+ {
+ ptr = pages + cur_page*page_size;
+ entries = GET_SHORT(ptr, 2);
+ ptr += 6;
+ for (i = 0; i < entries; i++)
+ {
+ if (comp(ptr, key, 0, (void **)&newptr) > 0) break;
+ ptr = newptr;
+ }
+ cur_page = GET_USHORT(ptr-2, 0);
+ }
+ ptr = pages + cur_page*page_size;
+ entries = GET_SHORT(ptr, 2);
+ ptr += 8;
+ for (i = 0; i < entries; i++)
+ {
+ ret = comp(ptr, key, 1, (void **)&newptr);
+ if (ret == 0) return ptr;
+ if (ret > 0) return NULL;
+ ptr = newptr;
+ }
+ return NULL;
+}
+
+/**************************************************************************
+ * HLPFILE_BPTreeEnum
+ *
+ * Enumerates elements in B+ tree.
+ *
+ * PARAMS
+ * buf [I] pointer to the embedded file structured as a B+ tree
+ * cb [I] compare function
+ * cookie [IO] cookie for cb function
+ */
+void HLPFILE_BPTreeEnum(BYTE* buf, HLPFILE_BPTreeCallback cb, void* cookie)
+{
+ unsigned magic;
+ unsigned page_size;
+ unsigned cur_page;
+ unsigned level;
+ BYTE *pages, *ptr, *newptr;
+ int i, entries;
+
+ magic = GET_USHORT(buf, 9);
+ if (magic != 0x293B)
+ {
+ WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
+ return;
+ }
+ page_size = GET_USHORT(buf, 9+4);
+ cur_page = GET_USHORT(buf, 9+26);
+ level = GET_USHORT(buf, 9+32);
+ pages = buf + 9 + 38;
+ while (--level > 0)
+ {
+ ptr = pages + cur_page*page_size;
+ cur_page = GET_USHORT(ptr, 4);
+ }
+ while (cur_page != 0xFFFF)
+ {
+ ptr = pages + cur_page*page_size;
+ entries = GET_SHORT(ptr, 2);
+ ptr += 8;
+ for (i = 0; i < entries; i++)
+ {
+ cb(ptr, (void **)&newptr, cookie);
+ ptr = newptr;
+ }
+ cur_page = GET_USHORT(pages+cur_page*page_size, 6);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * HLPFILE_UncompressedLZ77_Size
+ */
+static INT HLPFILE_UncompressedLZ77_Size(const BYTE *ptr, const BYTE *end)
+{
+ int i, newsize = 0;
+
+ while (ptr < end)
+ {
+ int mask = *ptr++;
+ for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
+ {
+ if (mask & 1)
+ {
+ int code = GET_USHORT(ptr, 0);
+ int len = 3 + (code >> 12);
+ newsize += len;
+ ptr += 2;
+ }
+ else newsize++, ptr++;
+ }
+ }
+
+ return newsize;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_UncompressLZ77
+ */
+static BYTE *HLPFILE_UncompressLZ77(const BYTE *ptr, const BYTE *end, BYTE *newptr)
+{
+ int i;
+
+ while (ptr < end)
+ {
+ int mask = *ptr++;
+ for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
+ {
+ if (mask & 1)
+ {
+ int code = GET_USHORT(ptr, 0);
+ int len = 3 + (code >> 12);
+ int offset = code & 0xfff;
+ /*
+ * We must copy byte-by-byte here. We cannot use memcpy nor
+ * memmove here. Just example:
+ * a[]={1,2,3,4,5,6,7,8,9,10}
+ * newptr=a+2;
+ * offset=1;
+ * We expect:
+ * {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 11, 12}
+ */
+ for (; len>0; len--, newptr++) *newptr = *(newptr-offset-1);
+ ptr += 2;
+ }
+ else *newptr++ = *ptr++;
+ }
+ }
+
+ return newptr;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_Uncompress2
+ */
+
+static void HLPFILE_Uncompress2(HLPFILE* hlpfile, const BYTE *ptr, const BYTE *end, BYTE *newptr, const BYTE *newend)
+{
+ BYTE *phptr, *phend;
+ UINT code;
+ UINT index;
+
+ while (ptr < end && newptr < newend)
+ {
+ if (!*ptr || *ptr >= 0x10)
+ *newptr++ = *ptr++;
+ else
+ {
+ code = 0x100 * ptr[0] + ptr[1];
+ index = (code - 0x100) / 2;
+
+ phptr = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index];
+ phend = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index + 1];
+
+ if (newptr + (phend - phptr) > newend)
+ {
+ WINE_FIXME("buffer overflow %p > %p for %lu bytes\n",
+ newptr, newend, (SIZE_T)(phend - phptr));
+ return;
+ }
+ memcpy(newptr, phptr, phend - phptr);
+ newptr += phend - phptr;
+ if (code & 1) *newptr++ = ' ';
+
+ ptr += 2;
+ }
+ }
+ if (newptr > newend) WINE_FIXME("buffer overflow %p > %p\n", newptr, newend);
+}
+
+/******************************************************************
+ * HLPFILE_Uncompress3
+ *
+ *
+ */
+static BOOL HLPFILE_Uncompress3(HLPFILE* hlpfile, char* dst, const char* dst_end,
+ const BYTE* src, const BYTE* src_end)
+{
+ unsigned int idx, len;
+
+ for (; src < src_end; src++)
+ {
+ if ((*src & 1) == 0)
+ {
+ idx = *src / 2;
+ if (idx > hlpfile->num_phrases)
+ {
+ WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
+ len = 0;
+ }
+ else
+ {
+ len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
+ if (dst + len <= dst_end)
+ memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
+ }
+ }
+ else if ((*src & 0x03) == 0x01)
+ {
+ idx = (*src + 1) * 64;
+ idx += *++src;
+ if (idx > hlpfile->num_phrases)
+ {
+ WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
+ len = 0;
+ }
+ else
+ {
+ len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
+ if (dst + len <= dst_end)
+ memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
+ }
+ }
+ else if ((*src & 0x07) == 0x03)
+ {
+ len = (*src / 8) + 1;
+ if (dst + len <= dst_end)
+ memcpy(dst, src + 1, len);
+ src += len;
+ }
+ else
+ {
+ len = (*src / 16) + 1;
+ if (dst + len <= dst_end)
+ memset(dst, ((*src & 0x0F) == 0x07) ? ' ' : 0, len);
+ }
+ dst += len;
+ }
+
+ if (dst > dst_end) WINE_ERR("buffer overflow (%p > %p)\n", dst, dst_end);
+ return TRUE;
+}
+
+/******************************************************************
+ * HLPFILE_UncompressRLE
+ *
+ *
+ */
+static void HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE* dst, unsigned dstsz)
+{
+ BYTE ch;
+ BYTE* sdst = dst + dstsz;
+
+ while (src < end)
+ {
+ ch = *src++;
+ if (ch & 0x80)
+ {
+ ch &= 0x7F;
+ if (dst + ch <= sdst)
+ memcpy(dst, src, ch);
+ src += ch;
+ }
+ else
+ {
+ if (dst + ch <= sdst)
+ memset(dst, (char)*src, ch);
+ src++;
+ }
+ dst += ch;
+ }
+ if (dst != sdst)
+ WINE_WARN("Buffer X-flow: d(%lu) instead of d(%u)\n",
+ (SIZE_T)(dst - (sdst - dstsz)), dstsz);
+}
+
/******************************************************************
* HLPFILE_PageByOffset
@@ -102,6 +392,25 @@ HLPFILE_PAGE *HLPFILE_PageByOffset(HLPFILE* hlpfile, LONG offset, ULONG* relativ
return found;
}
+/***********************************************************************
+ *
+ * HLPFILE_Contents
+ */
+HLPFILE_PAGE* HLPFILE_Contents(HLPFILE *hlpfile, ULONG* relative)
+{
+ HLPFILE_PAGE* page = NULL;
+
+ if (!hlpfile) return NULL;
+
+ page = HLPFILE_PageByOffset(hlpfile, hlpfile->contents_start, relative);
+ if (!page)
+ {
+ page = hlpfile->first_page;
+ *relative = 0;
+ }
+ return page;
+}
+
/**************************************************************************
* comp_PageByHash
*
@@ -173,23 +482,50 @@ HLPFILE_PAGE *HLPFILE_PageByMap(HLPFILE* hlpfile, LONG lMap, ULONG* relative)
return NULL;
}
-/***********************************************************************
+/**************************************************************************
+ * comp_FindSubFile
+ *
+ * HLPFILE_BPTreeCompare function for HLPFILE directory.
*
- * HLPFILE_Contents
*/
-HLPFILE_PAGE* HLPFILE_Contents(HLPFILE *hlpfile, ULONG* relative)
+static int comp_FindSubFile(void *p, const void *key,
+ int leaf, void** next)
{
- HLPFILE_PAGE* page = NULL;
+ *next = (char *)p+strlen(p)+(leaf?5:3);
+ WINE_TRACE("Comparing '%s' with '%s'\n", (char *)p, (char *)key);
+ return strcmp(p, key);
+}
- if (!hlpfile) return NULL;
+/***********************************************************************
+ *
+ * HLPFILE_FindSubFile
+ */
+static BOOL HLPFILE_FindSubFile(HLPFILE* hlpfile, LPCSTR name, BYTE **subbuf, BYTE **subend)
+{
+ BYTE *ptr;
- page = HLPFILE_PageByOffset(hlpfile, hlpfile->contents_start, relative);
- if (!page)
+ WINE_TRACE("looking for file '%s'\n", name);
+ ptr = HLPFILE_BPTreeSearch(hlpfile->file_buffer + GET_UINT(hlpfile->file_buffer, 4),
+ name, comp_FindSubFile);
+ if (!ptr) return FALSE;
+ *subbuf = hlpfile->file_buffer + GET_UINT(ptr, strlen(name)+1);
+ if (*subbuf >= hlpfile->file_buffer + hlpfile->file_buffer_size)
{
- page = hlpfile->first_page;
- *relative = 0;
+ WINE_ERR("internal file %s does not fit\n", name);
+ return FALSE;
}
- return page;
+ *subend = *subbuf + GET_UINT(*subbuf, 0);
+ if (*subend > hlpfile->file_buffer + hlpfile->file_buffer_size)
+ {
+ WINE_ERR("internal file %s does not fit\n", name);
+ return FALSE;
+ }
+ if (GET_UINT(*subbuf, 0) < GET_UINT(*subbuf, 4) + 9)
+ {
+ WINE_ERR("invalid size provided for internal file %s\n", name);
+ return FALSE;
+ }
+ return TRUE;
}
/***********************************************************************
@@ -215,251 +551,6 @@ LONG HLPFILE_Hash(LPCSTR lpszContext)
return lHash;
}
-/***********************************************************************
- *
- * HLPFILE_ReadHlpFile
- */
-HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath)
-{
- HLPFILE* hlpfile;
-
- for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)
- {
- if (!strcmp(lpszPath, hlpfile->lpszPath))
- {
- hlpfile->wRefCount++;
- return hlpfile;
- }
- }
-
- hlpfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(HLPFILE) + lstrlen(lpszPath) + 1);
- if (!hlpfile) return 0;
-
- hlpfile->lpszPath = (char*)hlpfile + sizeof(HLPFILE);
- hlpfile->contents_start = 0xFFFFFFFF;
- hlpfile->next = first_hlpfile;
- hlpfile->wRefCount = 1;
-
- strcpy(hlpfile->lpszPath, lpszPath);
-
- first_hlpfile = hlpfile;
- if (hlpfile->next) hlpfile->next->prev = hlpfile;
-
- if (!HLPFILE_DoReadHlpFile(hlpfile, lpszPath))
- {
- HLPFILE_FreeHlpFile(hlpfile);
- hlpfile = 0;
- }
-
- return hlpfile;
-}
-
-/***********************************************************************
- *
- * HLPFILE_DoReadHlpFile
- */
-static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
-{
- BOOL ret;
- HFILE hFile;
- OFSTRUCT ofs;
- BYTE* buf;
- DWORD ref = 0x0C;
- unsigned index, old_index, offset, len, offs, topicoffset;
-
- hFile = OpenFile(lpszPath, &ofs, OF_READ);
- if (hFile == HFILE_ERROR) return FALSE;
-
- ret = HLPFILE_ReadFileToBuffer(hlpfile, hFile);
- _lclose(hFile);
- if (!ret) return FALSE;
-
- if (!HLPFILE_SystemCommands(hlpfile)) return FALSE;
-
- if (hlpfile->version <= 16 && !HLPFILE_GetTOMap(hlpfile)) return FALSE;
-
- /* load phrases support */
- if (!HLPFILE_UncompressLZ77_Phrases(hlpfile))
- HLPFILE_Uncompress_Phrases40(hlpfile);
-
- if (!HLPFILE_Uncompress_Topic(hlpfile)) return FALSE;
- if (!HLPFILE_ReadFont(hlpfile)) return FALSE;
-
- buf = hlpfile->topic_map[0];
- old_index = -1;
- offs = 0;
- do
- {
- BYTE* end;
-
- if (hlpfile->version <= 16)
- {
- index = (ref - 0x0C) / hlpfile->dsize;
- offset = (ref - 0x0C) % hlpfile->dsize;
- }
- else
- {
- index = (ref - 0x0C) >> 14;
- offset = (ref - 0x0C) & 0x3FFF;
- }
-
- if (hlpfile->version <= 16 && index != old_index && old_index != -1)
- {
- /* we jumped to the next block, adjust pointers */
- ref -= 12;
- offset -= 12;
- }
-
- WINE_TRACE("ref=%08x => [%u/%u]\n", ref, index, offset);
-
- if (index >= hlpfile->topic_maplen) {WINE_WARN("maplen\n"); break;}
- buf = hlpfile->topic_map[index] + offset;
- if (buf + 0x15 >= hlpfile->topic_end) {WINE_WARN("extra\n"); break;}
- end = min(buf + GET_UINT(buf, 0), hlpfile->topic_end);
- if (index != old_index) {offs = 0; old_index = index;}
-
- switch (buf[0x14])
- {
- case 0x02:
- if (hlpfile->version <= 16)
- topicoffset = ref + index * 12;
- else
- topicoffset = index * 0x8000 + offs;
- if (!HLPFILE_AddPage(hlpfile, buf, end, ref, topicoffset)) return FALSE;
- break;
-
- case 0x01:
- case 0x20:
- case 0x23:
- if (!HLPFILE_SkipParagraph(hlpfile, buf, end, &len)) return FALSE;
- offs += len;
- break;
-
- default:
- WINE_ERR("buf[0x14] = %x\n", buf[0x14]);
- }
-
- if (hlpfile->version <= 16)
- {
- ref += GET_UINT(buf, 0xc);
- if (GET_UINT(buf, 0xc) == 0)
- break;
- }
- else
- ref = GET_UINT(buf, 0xc);
- } while (ref != 0xffffffff);
-
- HLPFILE_GetKeywords(hlpfile);
- HLPFILE_GetMap(hlpfile);
- if (hlpfile->version <= 16) return TRUE;
- return HLPFILE_GetContext(hlpfile);
-}
-
-/***********************************************************************
- *
- * HLPFILE_AddPage
- */
-static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned ref, unsigned offset)
-{
- HLPFILE_PAGE* page;
- const BYTE* title;
- UINT titlesize, blocksize, datalen;
- char* ptr;
- HLPFILE_MACRO*macro;
-
- blocksize = GET_UINT(buf, 0);
- datalen = GET_UINT(buf, 0x10);
- title = buf + datalen;
- if (title > end) {WINE_WARN("page2\n"); return FALSE;};
-
- titlesize = GET_UINT(buf, 4);
- page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize + 1);
- if (!page) return FALSE;
- page->lpszTitle = (char*)page + sizeof(HLPFILE_PAGE);
-
- if (titlesize > blocksize - datalen)
- {
- /* need to decompress */
- if (hlpfile->hasPhrases)
- HLPFILE_Uncompress2(hlpfile, title, end, (BYTE*)page->lpszTitle, (BYTE*)page->lpszTitle + titlesize);
- else if (hlpfile->hasPhrases40)
- HLPFILE_Uncompress3(hlpfile, page->lpszTitle, page->lpszTitle + titlesize, title, end);
- else
- {
- WINE_FIXME("Text size is too long, splitting\n");
- titlesize = blocksize - datalen;
- memcpy(page->lpszTitle, title, titlesize);
- }
- }
- else
- memcpy(page->lpszTitle, title, titlesize);
-
- page->lpszTitle[titlesize] = '\0';
-
- if (hlpfile->first_page)
- {
- hlpfile->last_page->next = page;
- page->prev = hlpfile->last_page;
- hlpfile->last_page = page;
- }
- else
- {
- hlpfile->first_page = page;
- hlpfile->last_page = page;
- page->prev = NULL;
- }
-
- page->file = hlpfile;
- page->next = NULL;
- page->first_macro = NULL;
- page->first_link = NULL;
- page->wNumber = GET_UINT(buf, 0x21);
- page->offset = offset;
- page->reference = ref;
-
- page->browse_bwd = GET_UINT(buf, 0x19);
- page->browse_fwd = GET_UINT(buf, 0x1D);
-
- if (hlpfile->version <= 16)
- {
- if (page->browse_bwd == 0xFFFF || page->browse_bwd == 0xFFFFFFFF)
- page->browse_bwd = 0xFFFFFFFF;
- else
- page->browse_bwd = hlpfile->TOMap[page->browse_bwd];
-
- if (page->browse_fwd == 0xFFFF || page->browse_fwd == 0xFFFFFFFF)
- page->browse_fwd = 0xFFFFFFFF;
- else
- page->browse_fwd = hlpfile->TOMap[page->browse_fwd];
- }
-
- WINE_TRACE("Added page[%d]: title='%s' %08x << %08x >> %08x\n",
- page->wNumber, page->lpszTitle,
- page->browse_bwd, page->offset, page->browse_fwd);
-
- /* now load macros */
- ptr = page->lpszTitle + strlen(page->lpszTitle) + 1;
- while (ptr < page->lpszTitle + titlesize)
- {
- unsigned len = strlen(ptr);
- char* macro_str;
-
- WINE_TRACE("macro: %s\n", ptr);
- macro = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_MACRO) + len + 1);
- macro->lpszMacro = macro_str = (char*)(macro + 1);
- memcpy(macro_str, ptr, len + 1);
- /* FIXME: shall we really link macro in reverse order ??
- * may produce strange results when played at page opening
- */
- macro->next = page->first_macro;
- page->first_macro = macro;
- ptr += len + 1;
- }
-
- return TRUE;
-}
-
static long fetch_long(const BYTE** ptr)
{
long ret;
@@ -529,28 +620,6 @@ static unsigned short fetch_ushort(const BYTE** ptr)
return ret;
}
-/***********************************************************************
- *
- * HLPFILE_SkipParagraph
- */
-static BOOL HLPFILE_SkipParagraph(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned* len)
-{
- const BYTE *tmp;
-
- if (!hlpfile->first_page) {WINE_WARN("no page\n"); return FALSE;};
- if (buf + 0x19 > end) {WINE_WARN("header too small\n"); return FALSE;};
-
- tmp = buf + 0x15;
- if (buf[0x14] == 0x20 || buf[0x14] == 0x23)
- {
- fetch_long(&tmp);
- *len = fetch_ushort(&tmp);
- }
- else *len = end-buf-15;
-
- return TRUE;
-}
-
/******************************************************************
* HLPFILE_DecompressGfx
*
@@ -1791,52 +1860,6 @@ static BOOL HLPFILE_ReadFileToBuffer(HLPFILE* hlpfile, HFILE hFile)
return TRUE;
}
-/**************************************************************************
- * comp_FindSubFile
- *
- * HLPFILE_BPTreeCompare function for HLPFILE directory.
- *
- */
-static int comp_FindSubFile(void *p, const void *key,
- int leaf, void** next)
-{
- *next = (char *)p+strlen(p)+(leaf?5:3);
- WINE_TRACE("Comparing '%s' with '%s'\n", (char *)p, (char *)key);
- return strcmp(p, key);
-}
-
-/***********************************************************************
- *
- * HLPFILE_FindSubFile
- */
-static BOOL HLPFILE_FindSubFile(HLPFILE* hlpfile, LPCSTR name, BYTE **subbuf, BYTE **subend)
-{
- BYTE *ptr;
-
- WINE_TRACE("looking for file '%s'\n", name);
- ptr = HLPFILE_BPTreeSearch(hlpfile->file_buffer + GET_UINT(hlpfile->file_buffer, 4),
- name, comp_FindSubFile);
- if (!ptr) return FALSE;
- *subbuf = hlpfile->file_buffer + GET_UINT(ptr, strlen(name)+1);
- if (*subbuf >= hlpfile->file_buffer + hlpfile->file_buffer_size)
- {
- WINE_ERR("internal file %s does not fit\n", name);
- return FALSE;
- }
- *subend = *subbuf + GET_UINT(*subbuf, 0);
- if (*subend > hlpfile->file_buffer + hlpfile->file_buffer_size)
- {
- WINE_ERR("internal file %s does not fit\n", name);
- return FALSE;
- }
- if (GET_UINT(*subbuf, 0) < GET_UINT(*subbuf, 4) + 9)
- {
- WINE_ERR("invalid size provided for internal file %s\n", name);
- return FALSE;
- }
- return TRUE;
-}
-
/***********************************************************************
*
* HLPFILE_SystemCommands
@@ -2009,66 +2032,181 @@ static BOOL HLPFILE_SystemCommands(HLPFILE* hlpfile)
/***********************************************************************
*
- * HLPFILE_UncompressedLZ77_Size
+ * HLPFILE_GetContext
*/
-static INT HLPFILE_UncompressedLZ77_Size(const BYTE *ptr, const BYTE *end)
+static BOOL HLPFILE_GetContext(HLPFILE *hlpfile)
{
- int i, newsize = 0;
+ BYTE *cbuf, *cend;
+ unsigned clen;
- while (ptr < end)
+ if (!HLPFILE_FindSubFile(hlpfile, "|CONTEXT", &cbuf, &cend))
+ {WINE_WARN("context0\n"); return FALSE;}
+
+ clen = cend - cbuf;
+ hlpfile->Context = HeapAlloc(GetProcessHeap(), 0, clen);
+ if (!hlpfile->Context) return FALSE;
+ memcpy(hlpfile->Context, cbuf, clen);
+
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_GetKeywords
+ */
+static BOOL HLPFILE_GetKeywords(HLPFILE *hlpfile)
+{
+ BYTE *cbuf, *cend;
+ unsigned clen;
+
+ if (!HLPFILE_FindSubFile(hlpfile, "|KWBTREE", &cbuf, &cend)) return FALSE;
+ clen = cend - cbuf;
+ hlpfile->kwbtree = HeapAlloc(GetProcessHeap(), 0, clen);
+ if (!hlpfile->kwbtree) return FALSE;
+ memcpy(hlpfile->kwbtree, cbuf, clen);
+
+ if (!HLPFILE_FindSubFile(hlpfile, "|KWDATA", &cbuf, &cend))
{
- int mask = *ptr++;
- for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
- {
- if (mask & 1)
- {
- int code = GET_USHORT(ptr, 0);
- int len = 3 + (code >> 12);
- newsize += len;
- ptr += 2;
- }
- else newsize++, ptr++;
- }
+ WINE_ERR("corrupted help file: kwbtree present but kwdata absent\n");
+ HeapFree(GetProcessHeap(), 0, hlpfile->kwbtree);
+ return FALSE;
}
+ clen = cend - cbuf;
+ hlpfile->kwdata = HeapAlloc(GetProcessHeap(), 0, clen);
+ if (!hlpfile->kwdata)
+ {
+ HeapFree(GetProcessHeap(), 0, hlpfile->kwdata);
+ return FALSE;
+ }
+ memcpy(hlpfile->kwdata, cbuf, clen);
- return newsize;
+ return TRUE;
}
/***********************************************************************
*
- * HLPFILE_UncompressLZ77
+ * HLPFILE_GetMap
*/
-static BYTE *HLPFILE_UncompressLZ77(const BYTE *ptr, const BYTE *end, BYTE *newptr)
+static BOOL HLPFILE_GetMap(HLPFILE *hlpfile)
{
- int i;
+ BYTE *cbuf, *cend;
+ unsigned entries, i;
- while (ptr < end)
+ if (!HLPFILE_FindSubFile(hlpfile, "|CTXOMAP", &cbuf, &cend))
+ {WINE_WARN("no map section\n"); return FALSE;}
+
+ entries = GET_USHORT(cbuf, 9);
+ hlpfile->Map = HeapAlloc(GetProcessHeap(), 0, entries * sizeof(HLPFILE_MAP));
+ if (!hlpfile->Map) return FALSE;
+ hlpfile->wMapLen = entries;
+ for (i = 0; i < entries; i++)
{
- int mask = *ptr++;
- for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
- {
- if (mask & 1)
- {
- int code = GET_USHORT(ptr, 0);
- int len = 3 + (code >> 12);
- int offset = code & 0xfff;
- /*
- * We must copy byte-by-byte here. We cannot use memcpy nor
- * memmove here. Just example:
- * a[]={1,2,3,4,5,6,7,8,9,10}
- * newptr=a+2;
- * offset=1;
- * We expect:
- * {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 11, 12}
- */
- for (; len>0; len--, newptr++) *newptr = *(newptr-offset-1);
- ptr += 2;
- }
- else *newptr++ = *ptr++;
- }
+ hlpfile->Map[i].lMap = GET_UINT(cbuf+11,i*8);
+ hlpfile->Map[i].offset = GET_UINT(cbuf+11,i*8+4);
}
+ return TRUE;
+}
- return newptr;
+/***********************************************************************
+ *
+ * HLPFILE_GetTOMap
+ */
+static BOOL HLPFILE_GetTOMap(HLPFILE *hlpfile)
+{
+ BYTE *cbuf, *cend;
+ unsigned clen;
+
+ if (!HLPFILE_FindSubFile(hlpfile, "|TOMAP", &cbuf, &cend))
+ {WINE_WARN("no tomap section\n"); return FALSE;}
+
+ clen = cend - cbuf - 9;
+ hlpfile->TOMap = HeapAlloc(GetProcessHeap(), 0, clen);
+ if (!hlpfile->TOMap) return FALSE;
+ memcpy(hlpfile->TOMap, cbuf+9, clen);
+ hlpfile->wTOMapLen = clen/4;
+ return TRUE;
+}
+
+/***********************************************************************
+ *
+ * DeleteMacro
+ */
+static void HLPFILE_DeleteMacro(HLPFILE_MACRO* macro)
+{
+ HLPFILE_MACRO* next;
+
+ while (macro)
+ {
+ next = macro->next;
+ HeapFree(GetProcessHeap(), 0, macro);
+ macro = next;
+ }
+}
+
+/***********************************************************************
+ *
+ * DeletePage
+ */
+static void HLPFILE_DeletePage(HLPFILE_PAGE* page)
+{
+ HLPFILE_PAGE* next;
+
+ while (page)
+ {
+ next = page->next;
+ HLPFILE_DeleteMacro(page->first_macro);
+ HeapFree(GetProcessHeap(), 0, page);
+ page = next;
+ }
+}
+
+/***********************************************************************
+ *
+ * HLPFILE_FreeHlpFile
+ */
+void HLPFILE_FreeHlpFile(HLPFILE* hlpfile)
+{
+ unsigned i;
+
+ if (!hlpfile || --hlpfile->wRefCount > 0) return;
+
+ if (hlpfile->next) hlpfile->next->prev = hlpfile->prev;
+ if (hlpfile->prev) hlpfile->prev->next = hlpfile->next;
+ else first_hlpfile = hlpfile->next;
+
+ if (hlpfile->numFonts)
+ {
+ for (i = 0; i < hlpfile->numFonts; i++)
+ {
+ DeleteObject(hlpfile->fonts[i].hFont);
+ }
+ HeapFree(GetProcessHeap(), 0, hlpfile->fonts);
+ }
+
+ if (hlpfile->numBmps)
+ {
+ for (i = 0; i < hlpfile->numBmps; i++)
+ {
+ DeleteObject(hlpfile->bmps[i]);
+ }
+ HeapFree(GetProcessHeap(), 0, hlpfile->bmps);
+ }
+
+ HLPFILE_DeletePage(hlpfile->first_page);
+ HLPFILE_DeleteMacro(hlpfile->first_macro);
+
+ DestroyIcon(hlpfile->hIcon);
+ if (hlpfile->numWindows) HeapFree(GetProcessHeap(), 0, hlpfile->windows);
+ HeapFree(GetProcessHeap(), 0, hlpfile->Context);
+ HeapFree(GetProcessHeap(), 0, hlpfile->Map);
+ HeapFree(GetProcessHeap(), 0, hlpfile->lpszTitle);
+ HeapFree(GetProcessHeap(), 0, hlpfile->lpszCopyright);
+ HeapFree(GetProcessHeap(), 0, hlpfile->file_buffer);
+ HeapFree(GetProcessHeap(), 0, hlpfile->phrases_offsets);
+ HeapFree(GetProcessHeap(), 0, hlpfile->phrases_buffer);
+ HeapFree(GetProcessHeap(), 0, hlpfile->topic_map);
+ HeapFree(GetProcessHeap(), 0, hlpfile->help_on_file);
+ HeapFree(GetProcessHeap(), 0, hlpfile);
}
/***********************************************************************
@@ -2259,423 +2397,267 @@ static BOOL HLPFILE_Uncompress_Topic(HLPFILE* hlpfile)
/***********************************************************************
*
- * HLPFILE_Uncompress2
- */
-
-static void HLPFILE_Uncompress2(HLPFILE* hlpfile, const BYTE *ptr, const BYTE *end, BYTE *newptr, const BYTE *newend)
-{
- BYTE *phptr, *phend;
- UINT code;
- UINT index;
-
- while (ptr < end && newptr < newend)
- {
- if (!*ptr || *ptr >= 0x10)
- *newptr++ = *ptr++;
- else
- {
- code = 0x100 * ptr[0] + ptr[1];
- index = (code - 0x100) / 2;
-
- phptr = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index];
- phend = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index + 1];
-
- if (newptr + (phend - phptr) > newend)
- {
- WINE_FIXME("buffer overflow %p > %p for %lu bytes\n",
- newptr, newend, (SIZE_T)(phend - phptr));
- return;
- }
- memcpy(newptr, phptr, phend - phptr);
- newptr += phend - phptr;
- if (code & 1) *newptr++ = ' ';
-
- ptr += 2;
- }
- }
- if (newptr > newend) WINE_FIXME("buffer overflow %p > %p\n", newptr, newend);
-}
-
-/******************************************************************
- * HLPFILE_Uncompress3
- *
- *
+ * HLPFILE_AddPage
*/
-static BOOL HLPFILE_Uncompress3(HLPFILE* hlpfile, char* dst, const char* dst_end,
- const BYTE* src, const BYTE* src_end)
+static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned ref, unsigned offset)
{
- unsigned int idx, len;
-
- for (; src < src_end; src++)
- {
- if ((*src & 1) == 0)
- {
- idx = *src / 2;
- if (idx > hlpfile->num_phrases)
- {
- WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
- len = 0;
- }
- else
- {
- len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
- if (dst + len <= dst_end)
- memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
- }
- }
- else if ((*src & 0x03) == 0x01)
- {
- idx = (*src + 1) * 64;
- idx += *++src;
- if (idx > hlpfile->num_phrases)
- {
- WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
- len = 0;
- }
- else
- {
- len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
- if (dst + len <= dst_end)
- memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
- }
- }
- else if ((*src & 0x07) == 0x03)
- {
- len = (*src / 8) + 1;
- if (dst + len <= dst_end)
- memcpy(dst, src + 1, len);
- src += len;
- }
- else
- {
- len = (*src / 16) + 1;
- if (dst + len <= dst_end)
- memset(dst, ((*src & 0x0F) == 0x07) ? ' ' : 0, len);
- }
- dst += len;
- }
+ HLPFILE_PAGE* page;
+ const BYTE* title;
+ UINT titlesize, blocksize, datalen;
+ char* ptr;
+ HLPFILE_MACRO*macro;
- if (dst > dst_end) WINE_ERR("buffer overflow (%p > %p)\n", dst, dst_end);
- return TRUE;
-}
+ blocksize = GET_UINT(buf, 0);
+ datalen = GET_UINT(buf, 0x10);
+ title = buf + datalen;
+ if (title > end) {WINE_WARN("page2\n"); return FALSE;};
-/******************************************************************
- * HLPFILE_UncompressRLE
- *
- *
- */
-static void HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE* dst, unsigned dstsz)
-{
- BYTE ch;
- BYTE* sdst = dst + dstsz;
+ titlesize = GET_UINT(buf, 4);
+ page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize + 1);
+ if (!page) return FALSE;
+ page->lpszTitle = (char*)page + sizeof(HLPFILE_PAGE);
- while (src < end)
+ if (titlesize > blocksize - datalen)
{
- ch = *src++;
- if (ch & 0x80)
- {
- ch &= 0x7F;
- if (dst + ch <= sdst)
- memcpy(dst, src, ch);
- src += ch;
- }
+ /* need to decompress */
+ if (hlpfile->hasPhrases)
+ HLPFILE_Uncompress2(hlpfile, title, end, (BYTE*)page->lpszTitle, (BYTE*)page->lpszTitle + titlesize);
+ else if (hlpfile->hasPhrases40)
+ HLPFILE_Uncompress3(hlpfile, page->lpszTitle, page->lpszTitle + titlesize, title, end);
else
{
- if (dst + ch <= sdst)
- memset(dst, (char)*src, ch);
- src++;
+ WINE_FIXME("Text size is too long, splitting\n");
+ titlesize = blocksize - datalen;
+ memcpy(page->lpszTitle, title, titlesize);
}
- dst += ch;
}
- if (dst != sdst)
- WINE_WARN("Buffer X-flow: d(%lu) instead of d(%u)\n",
- (SIZE_T)(dst - (sdst - dstsz)), dstsz);
-}
+ else
+ memcpy(page->lpszTitle, title, titlesize);
-/**************************************************************************
- * HLPFILE_BPTreeSearch
- *
- * Searches for an element in B+ tree
- *
- * PARAMS
- * buf [I] pointer to the embedded file structured as a B+ tree
- * key [I] pointer to data to find
- * comp [I] compare function
- *
- * RETURNS
- * Pointer to block identified by key, or NULL if failure.
- *
- */
-void* HLPFILE_BPTreeSearch(BYTE* buf, const void* key,
- HLPFILE_BPTreeCompare comp)
-{
- unsigned magic;
- unsigned page_size;
- unsigned cur_page;
- unsigned level;
- BYTE *pages, *ptr, *newptr;
- int i, entries;
- int ret;
+ page->lpszTitle[titlesize] = '\0';
- magic = GET_USHORT(buf, 9);
- if (magic != 0x293B)
- {
- WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
- return NULL;
- }
- page_size = GET_USHORT(buf, 9+4);
- cur_page = GET_USHORT(buf, 9+26);
- level = GET_USHORT(buf, 9+32);
- pages = buf + 9 + 38;
- while (--level > 0)
+ if (hlpfile->first_page)
{
- ptr = pages + cur_page*page_size;
- entries = GET_SHORT(ptr, 2);
- ptr += 6;
- for (i = 0; i < entries; i++)
- {
- if (comp(ptr, key, 0, (void **)&newptr) > 0) break;
- ptr = newptr;
- }
- cur_page = GET_USHORT(ptr-2, 0);
+ hlpfile->last_page->next = page;
+ page->prev = hlpfile->last_page;
+ hlpfile->last_page = page;
}
- ptr = pages + cur_page*page_size;
- entries = GET_SHORT(ptr, 2);
- ptr += 8;
- for (i = 0; i < entries; i++)
+ else
{
- ret = comp(ptr, key, 1, (void **)&newptr);
- if (ret == 0) return ptr;
- if (ret > 0) return NULL;
- ptr = newptr;
+ hlpfile->first_page = page;
+ hlpfile->last_page = page;
+ page->prev = NULL;
}
- return NULL;
-}
-/**************************************************************************
- * HLPFILE_BPTreeEnum
- *
- * Enumerates elements in B+ tree.
- *
- * PARAMS
- * buf [I] pointer to the embedded file structured as a B+ tree
- * cb [I] compare function
- * cookie [IO] cookie for cb function
- */
-void HLPFILE_BPTreeEnum(BYTE* buf, HLPFILE_BPTreeCallback cb, void* cookie)
-{
- unsigned magic;
- unsigned page_size;
- unsigned cur_page;
- unsigned level;
- BYTE *pages, *ptr, *newptr;
- int i, entries;
+ page->file = hlpfile;
+ page->next = NULL;
+ page->first_macro = NULL;
+ page->first_link = NULL;
+ page->wNumber = GET_UINT(buf, 0x21);
+ page->offset = offset;
+ page->reference = ref;
- magic = GET_USHORT(buf, 9);
- if (magic != 0x293B)
- {
- WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
- return;
- }
- page_size = GET_USHORT(buf, 9+4);
- cur_page = GET_USHORT(buf, 9+26);
- level = GET_USHORT(buf, 9+32);
- pages = buf + 9 + 38;
- while (--level > 0)
- {
- ptr = pages + cur_page*page_size;
- cur_page = GET_USHORT(ptr, 4);
- }
- while (cur_page != 0xFFFF)
+ page->browse_bwd = GET_UINT(buf, 0x19);
+ page->browse_fwd = GET_UINT(buf, 0x1D);
+
+ if (hlpfile->version <= 16)
{
- ptr = pages + cur_page*page_size;
- entries = GET_SHORT(ptr, 2);
- ptr += 8;
- for (i = 0; i < entries; i++)
- {
- cb(ptr, (void **)&newptr, cookie);
- ptr = newptr;
- }
- cur_page = GET_USHORT(pages+cur_page*page_size, 6);
- }
-}
+ if (page->browse_bwd == 0xFFFF || page->browse_bwd == 0xFFFFFFFF)
+ page->browse_bwd = 0xFFFFFFFF;
+ else
+ page->browse_bwd = hlpfile->TOMap[page->browse_bwd];
+ if (page->browse_fwd == 0xFFFF || page->browse_fwd == 0xFFFFFFFF)
+ page->browse_fwd = 0xFFFFFFFF;
+ else
+ page->browse_fwd = hlpfile->TOMap[page->browse_fwd];
+ }
-/***********************************************************************
- *
- * HLPFILE_GetContext
- */
-static BOOL HLPFILE_GetContext(HLPFILE *hlpfile)
-{
- BYTE *cbuf, *cend;
- unsigned clen;
+ WINE_TRACE("Added page[%d]: title='%s' %08x << %08x >> %08x\n",
+ page->wNumber, page->lpszTitle,
+ page->browse_bwd, page->offset, page->browse_fwd);
- if (!HLPFILE_FindSubFile(hlpfile, "|CONTEXT", &cbuf, &cend))
- {WINE_WARN("context0\n"); return FALSE;}
+ /* now load macros */
+ ptr = page->lpszTitle + strlen(page->lpszTitle) + 1;
+ while (ptr < page->lpszTitle + titlesize)
+ {
+ unsigned len = strlen(ptr);
+ char* macro_str;
- clen = cend - cbuf;
- hlpfile->Context = HeapAlloc(GetProcessHeap(), 0, clen);
- if (!hlpfile->Context) return FALSE;
- memcpy(hlpfile->Context, cbuf, clen);
+ WINE_TRACE("macro: %s\n", ptr);
+ macro = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_MACRO) + len + 1);
+ macro->lpszMacro = macro_str = (char*)(macro + 1);
+ memcpy(macro_str, ptr, len + 1);
+ /* FIXME: shall we really link macro in reverse order ??
+ * may produce strange results when played at page opening
+ */
+ macro->next = page->first_macro;
+ page->first_macro = macro;
+ ptr += len + 1;
+ }
return TRUE;
}
/***********************************************************************
*
- * HLPFILE_GetKeywords
+ * HLPFILE_SkipParagraph
*/
-static BOOL HLPFILE_GetKeywords(HLPFILE *hlpfile)
+static BOOL HLPFILE_SkipParagraph(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned* len)
{
- BYTE *cbuf, *cend;
- unsigned clen;
+ const BYTE *tmp;
- if (!HLPFILE_FindSubFile(hlpfile, "|KWBTREE", &cbuf, &cend)) return FALSE;
- clen = cend - cbuf;
- hlpfile->kwbtree = HeapAlloc(GetProcessHeap(), 0, clen);
- if (!hlpfile->kwbtree) return FALSE;
- memcpy(hlpfile->kwbtree, cbuf, clen);
+ if (!hlpfile->first_page) {WINE_WARN("no page\n"); return FALSE;};
+ if (buf + 0x19 > end) {WINE_WARN("header too small\n"); return FALSE;};
- if (!HLPFILE_FindSubFile(hlpfile, "|KWDATA", &cbuf, &cend))
- {
- WINE_ERR("corrupted help file: kwbtree present but kwdata absent\n");
- HeapFree(GetProcessHeap(), 0, hlpfile->kwbtree);
- return FALSE;
- }
- clen = cend - cbuf;
- hlpfile->kwdata = HeapAlloc(GetProcessHeap(), 0, clen);
- if (!hlpfile->kwdata)
+ tmp = buf + 0x15;
+ if (buf[0x14] == 0x20 || buf[0x14] == 0x23)
{
- HeapFree(GetProcessHeap(), 0, hlpfile->kwdata);
- return FALSE;
+ fetch_long(&tmp);
+ *len = fetch_ushort(&tmp);
}
- memcpy(hlpfile->kwdata, cbuf, clen);
+ else *len = end-buf-15;
return TRUE;
}
/***********************************************************************
*
- * HLPFILE_GetMap
+ * HLPFILE_DoReadHlpFile
*/
-static BOOL HLPFILE_GetMap(HLPFILE *hlpfile)
+static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
{
- BYTE *cbuf, *cend;
- unsigned entries, i;
+ BOOL ret;
+ HFILE hFile;
+ OFSTRUCT ofs;
+ BYTE* buf;
+ DWORD ref = 0x0C;
+ unsigned index, old_index, offset, len, offs, topicoffset;
- if (!HLPFILE_FindSubFile(hlpfile, "|CTXOMAP", &cbuf, &cend))
- {WINE_WARN("no map section\n"); return FALSE;}
+ hFile = OpenFile(lpszPath, &ofs, OF_READ);
+ if (hFile == HFILE_ERROR) return FALSE;
- entries = GET_USHORT(cbuf, 9);
- hlpfile->Map = HeapAlloc(GetProcessHeap(), 0, entries * sizeof(HLPFILE_MAP));
- if (!hlpfile->Map) return FALSE;
- hlpfile->wMapLen = entries;
- for (i = 0; i < entries; i++)
- {
- hlpfile->Map[i].lMap = GET_UINT(cbuf+11,i*8);
- hlpfile->Map[i].offset = GET_UINT(cbuf+11,i*8+4);
- }
- return TRUE;
-}
+ ret = HLPFILE_ReadFileToBuffer(hlpfile, hFile);
+ _lclose(hFile);
+ if (!ret) return FALSE;
-/***********************************************************************
- *
- * HLPFILE_GetTOMap
- */
-static BOOL HLPFILE_GetTOMap(HLPFILE *hlpfile)
-{
- BYTE *cbuf, *cend;
- unsigned clen;
+ if (!HLPFILE_SystemCommands(hlpfile)) return FALSE;
- if (!HLPFILE_FindSubFile(hlpfile, "|TOMAP", &cbuf, &cend))
- {WINE_WARN("no tomap section\n"); return FALSE;}
+ if (hlpfile->version <= 16 && !HLPFILE_GetTOMap(hlpfile)) return FALSE;
- clen = cend - cbuf - 9;
- hlpfile->TOMap = HeapAlloc(GetProcessHeap(), 0, clen);
- if (!hlpfile->TOMap) return FALSE;
- memcpy(hlpfile->TOMap, cbuf+9, clen);
- hlpfile->wTOMapLen = clen/4;
- return TRUE;
-}
+ /* load phrases support */
+ if (!HLPFILE_UncompressLZ77_Phrases(hlpfile))
+ HLPFILE_Uncompress_Phrases40(hlpfile);
-/***********************************************************************
- *
- * DeleteMacro
- */
-static void HLPFILE_DeleteMacro(HLPFILE_MACRO* macro)
-{
- HLPFILE_MACRO* next;
+ if (!HLPFILE_Uncompress_Topic(hlpfile)) return FALSE;
+ if (!HLPFILE_ReadFont(hlpfile)) return FALSE;
- while (macro)
+ buf = hlpfile->topic_map[0];
+ old_index = -1;
+ offs = 0;
+ do
{
- next = macro->next;
- HeapFree(GetProcessHeap(), 0, macro);
- macro = next;
- }
-}
+ BYTE* end;
-/***********************************************************************
- *
- * DeletePage
- */
-static void HLPFILE_DeletePage(HLPFILE_PAGE* page)
-{
- HLPFILE_PAGE* next;
+ if (hlpfile->version <= 16)
+ {
+ index = (ref - 0x0C) / hlpfile->dsize;
+ offset = (ref - 0x0C) % hlpfile->dsize;
+ }
+ else
+ {
+ index = (ref - 0x0C) >> 14;
+ offset = (ref - 0x0C) & 0x3FFF;
+ }
- while (page)
- {
- next = page->next;
- HLPFILE_DeleteMacro(page->first_macro);
- HeapFree(GetProcessHeap(), 0, page);
- page = next;
- }
+ if (hlpfile->version <= 16 && index != old_index && old_index != -1)
+ {
+ /* we jumped to the next block, adjust pointers */
+ ref -= 12;
+ offset -= 12;
+ }
+
+ WINE_TRACE("ref=%08x => [%u/%u]\n", ref, index, offset);
+
+ if (index >= hlpfile->topic_maplen) {WINE_WARN("maplen\n"); break;}
+ buf = hlpfile->topic_map[index] + offset;
+ if (buf + 0x15 >= hlpfile->topic_end) {WINE_WARN("extra\n"); break;}
+ end = min(buf + GET_UINT(buf, 0), hlpfile->topic_end);
+ if (index != old_index) {offs = 0; old_index = index;}
+
+ switch (buf[0x14])
+ {
+ case 0x02:
+ if (hlpfile->version <= 16)
+ topicoffset = ref + index * 12;
+ else
+ topicoffset = index * 0x8000 + offs;
+ if (!HLPFILE_AddPage(hlpfile, buf, end, ref, topicoffset)) return FALSE;
+ break;
+
+ case 0x01:
+ case 0x20:
+ case 0x23:
+ if (!HLPFILE_SkipParagraph(hlpfile, buf, end, &len)) return FALSE;
+ offs += len;
+ break;
+
+ default:
+ WINE_ERR("buf[0x14] = %x\n", buf[0x14]);
+ }
+
+ if (hlpfile->version <= 16)
+ {
+ ref += GET_UINT(buf, 0xc);
+ if (GET_UINT(buf, 0xc) == 0)
+ break;
+ }
+ else
+ ref = GET_UINT(buf, 0xc);
+ } while (ref != 0xffffffff);
+
+ HLPFILE_GetKeywords(hlpfile);
+ HLPFILE_GetMap(hlpfile);
+ if (hlpfile->version <= 16) return TRUE;
+ return HLPFILE_GetContext(hlpfile);
}
/***********************************************************************
*
- * HLPFILE_FreeHlpFile
+ * HLPFILE_ReadHlpFile
*/
-void HLPFILE_FreeHlpFile(HLPFILE* hlpfile)
+HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath)
{
- unsigned i;
-
- if (!hlpfile || --hlpfile->wRefCount > 0) return;
-
- if (hlpfile->next) hlpfile->next->prev = hlpfile->prev;
- if (hlpfile->prev) hlpfile->prev->next = hlpfile->next;
- else first_hlpfile = hlpfile->next;
+ HLPFILE* hlpfile;
- if (hlpfile->numFonts)
+ for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)
{
- for (i = 0; i < hlpfile->numFonts; i++)
+ if (!strcmp(lpszPath, hlpfile->lpszPath))
{
- DeleteObject(hlpfile->fonts[i].hFont);
+ hlpfile->wRefCount++;
+ return hlpfile;
}
- HeapFree(GetProcessHeap(), 0, hlpfile->fonts);
}
- if (hlpfile->numBmps)
+ hlpfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(HLPFILE) + lstrlen(lpszPath) + 1);
+ if (!hlpfile) return 0;
+
+ hlpfile->lpszPath = (char*)hlpfile + sizeof(HLPFILE);
+ hlpfile->contents_start = 0xFFFFFFFF;
+ hlpfile->next = first_hlpfile;
+ hlpfile->wRefCount = 1;
+
+ strcpy(hlpfile->lpszPath, lpszPath);
+
+ first_hlpfile = hlpfile;
+ if (hlpfile->next) hlpfile->next->prev = hlpfile;
+
+ if (!HLPFILE_DoReadHlpFile(hlpfile, lpszPath))
{
- for (i = 0; i < hlpfile->numBmps; i++)
- {
- DeleteObject(hlpfile->bmps[i]);
- }
- HeapFree(GetProcessHeap(), 0, hlpfile->bmps);
+ HLPFILE_FreeHlpFile(hlpfile);
+ hlpfile = 0;
}
- HLPFILE_DeletePage(hlpfile->first_page);
- HLPFILE_DeleteMacro(hlpfile->first_macro);
-
- DestroyIcon(hlpfile->hIcon);
- if (hlpfile->numWindows) HeapFree(GetProcessHeap(), 0, hlpfile->windows);
- HeapFree(GetProcessHeap(), 0, hlpfile->Context);
- HeapFree(GetProcessHeap(), 0, hlpfile->Map);
- HeapFree(GetProcessHeap(), 0, hlpfile->lpszTitle);
- HeapFree(GetProcessHeap(), 0, hlpfile->lpszCopyright);
- HeapFree(GetProcessHeap(), 0, hlpfile->file_buffer);
- HeapFree(GetProcessHeap(), 0, hlpfile->phrases_offsets);
- HeapFree(GetProcessHeap(), 0, hlpfile->phrases_buffer);
- HeapFree(GetProcessHeap(), 0, hlpfile->topic_map);
- HeapFree(GetProcessHeap(), 0, hlpfile->help_on_file);
- HeapFree(GetProcessHeap(), 0, hlpfile);
+ return hlpfile;
}
--
1.5.6.5
More information about the wine-patches
mailing list