ReactOS 0.4.15-dev-7906-g1b85a5f
hlpfile.c
Go to the documentation of this file.
1/*
2 * Help Viewer
3 *
4 * Copyright 1996 Ulrich Schmid
5 * 2002, 2008 Eric Pouech
6 * 2007 Kirill K. Smirnov
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23#include <stdarg.h>
24#include <stdio.h>
25#include <string.h>
26
27#include "windef.h"
28#include "winbase.h"
29#include "wingdi.h"
30#include "winuser.h"
31#include "winhelp.h"
32
33#include "wine/debug.h"
34
36
37static inline unsigned short GET_USHORT(const BYTE* buffer, unsigned i)
38{
39 return (BYTE)buffer[i] + 0x100 * (BYTE)buffer[i + 1];
40}
41
42static inline short GET_SHORT(const BYTE* buffer, unsigned i)
43{
44 return (BYTE)buffer[i] + 0x100 * (signed char)buffer[i+1];
45}
46
47static inline unsigned GET_UINT(const BYTE* buffer, unsigned i)
48{
49 return GET_USHORT(buffer, i) + 0x10000 * GET_USHORT(buffer, i + 2);
50}
51
53
54
55/**************************************************************************
56 * HLPFILE_BPTreeSearch
57 *
58 * Searches for an element in B+ tree
59 *
60 * PARAMS
61 * buf [I] pointer to the embedded file structured as a B+ tree
62 * key [I] pointer to data to find
63 * comp [I] compare function
64 *
65 * RETURNS
66 * Pointer to block identified by key, or NULL if failure.
67 *
68 */
69static void* HLPFILE_BPTreeSearch(BYTE* buf, const void* key,
71{
72 unsigned magic;
73 unsigned page_size;
74 unsigned cur_page;
75 unsigned level;
76 BYTE *pages, *ptr, *newptr;
77 int i, entries;
78 int ret;
79
80 magic = GET_USHORT(buf, 9);
81 if (magic != 0x293B)
82 {
83 WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
84 return NULL;
85 }
86 page_size = GET_USHORT(buf, 9+4);
87 cur_page = GET_USHORT(buf, 9+26);
88 level = GET_USHORT(buf, 9+32);
89 pages = buf + 9 + 38;
90 while (--level > 0)
91 {
92 ptr = pages + cur_page*page_size;
93 entries = GET_SHORT(ptr, 2);
94 ptr += 6;
95 for (i = 0; i < entries; i++)
96 {
97 if (comp(ptr, key, 0, (void **)&newptr) > 0) break;
98 ptr = newptr;
99 }
100 cur_page = GET_USHORT(ptr-2, 0);
101 }
102 ptr = pages + cur_page*page_size;
103 entries = GET_SHORT(ptr, 2);
104 ptr += 8;
105 for (i = 0; i < entries; i++)
106 {
107 ret = comp(ptr, key, 1, (void **)&newptr);
108 if (ret == 0) return ptr;
109 if (ret > 0) return NULL;
110 ptr = newptr;
111 }
112 return NULL;
113}
114
115/**************************************************************************
116 * HLPFILE_BPTreeEnum
117 *
118 * Enumerates elements in B+ tree.
119 *
120 * PARAMS
121 * buf [I] pointer to the embedded file structured as a B+ tree
122 * cb [I] compare function
123 * cookie [IO] cookie for cb function
124 */
126{
127 unsigned magic;
128 unsigned page_size;
129 unsigned cur_page;
130 unsigned level;
131 BYTE *pages, *ptr, *newptr;
132 int i, entries;
133
134 magic = GET_USHORT(buf, 9);
135 if (magic != 0x293B)
136 {
137 WINE_ERR("Invalid magic in B+ tree: 0x%x\n", magic);
138 return;
139 }
140 page_size = GET_USHORT(buf, 9+4);
141 cur_page = GET_USHORT(buf, 9+26);
142 level = GET_USHORT(buf, 9+32);
143 pages = buf + 9 + 38;
144 while (--level > 0)
145 {
146 ptr = pages + cur_page*page_size;
147 cur_page = GET_USHORT(ptr, 4);
148 }
149 while (cur_page != 0xFFFF)
150 {
151 ptr = pages + cur_page*page_size;
152 entries = GET_SHORT(ptr, 2);
153 ptr += 8;
154 for (i = 0; i < entries; i++)
155 {
156 cb(ptr, (void **)&newptr, cookie);
157 ptr = newptr;
158 }
159 cur_page = GET_USHORT(pages+cur_page*page_size, 6);
160 }
161}
162
163
164/***********************************************************************
165 *
166 * HLPFILE_UncompressedLZ77_Size
167 */
169{
170 int i, newsize = 0;
171
172 while (ptr < end)
173 {
174 int mask = *ptr++;
175 for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
176 {
177 if (mask & 1)
178 {
179 int code = GET_USHORT(ptr, 0);
180 int len = 3 + (code >> 12);
181 newsize += len;
182 ptr += 2;
183 }
184 else newsize++, ptr++;
185 }
186 }
187
188 return newsize;
189}
190
191/***********************************************************************
192 *
193 * HLPFILE_UncompressLZ77
194 */
195static BYTE *HLPFILE_UncompressLZ77(const BYTE *ptr, const BYTE *end, BYTE *newptr)
196{
197 int i;
198
199 while (ptr < end)
200 {
201 int mask = *ptr++;
202 for (i = 0; i < 8 && ptr < end; i++, mask >>= 1)
203 {
204 if (mask & 1)
205 {
206 int code = GET_USHORT(ptr, 0);
207 int len = 3 + (code >> 12);
208 int offset = code & 0xfff;
209 /*
210 * We must copy byte-by-byte here. We cannot use memcpy nor
211 * memmove here. Just example:
212 * a[]={1,2,3,4,5,6,7,8,9,10}
213 * newptr=a+2;
214 * offset=1;
215 * We expect:
216 * {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 11, 12}
217 */
218 for (; len>0; len--, newptr++) *newptr = *(newptr-offset-1);
219 ptr += 2;
220 }
221 else *newptr++ = *ptr++;
222 }
223 }
224
225 return newptr;
226}
227
228/***********************************************************************
229 *
230 * HLPFILE_Uncompress2
231 */
232
233static void HLPFILE_Uncompress2(HLPFILE* hlpfile, const BYTE *ptr, const BYTE *end, BYTE *newptr, const BYTE *newend)
234{
235 BYTE *phptr, *phend;
236 UINT code;
237 UINT index;
238
239 while (ptr < end && newptr < newend)
240 {
241 if (!*ptr || *ptr >= 0x10)
242 *newptr++ = *ptr++;
243 else
244 {
245 code = 0x100 * ptr[0] + ptr[1];
246 index = (code - 0x100) / 2;
247
248 phptr = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index];
249 phend = (BYTE*)hlpfile->phrases_buffer + hlpfile->phrases_offsets[index + 1];
250
251 if (newptr + (phend - phptr) > newend)
252 {
253 WINE_FIXME("buffer overflow %p > %p for %lu bytes\n",
254 newptr, newend, (SIZE_T)(phend - phptr));
255 return;
256 }
257 memcpy(newptr, phptr, phend - phptr);
258 newptr += phend - phptr;
259 if (code & 1) *newptr++ = ' ';
260
261 ptr += 2;
262 }
263 }
264 if (newptr > newend) WINE_FIXME("buffer overflow %p > %p\n", newptr, newend);
265}
266
267/******************************************************************
268 * HLPFILE_Uncompress3
269 *
270 *
271 */
272static BOOL HLPFILE_Uncompress3(HLPFILE* hlpfile, char* dst, const char* dst_end,
273 const BYTE* src, const BYTE* src_end)
274{
275 unsigned int idx, len;
276
277 for (; src < src_end; src++)
278 {
279 if ((*src & 1) == 0)
280 {
281 idx = *src / 2;
282 if (idx > hlpfile->num_phrases)
283 {
284 WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
285 len = 0;
286 }
287 else
288 {
289 len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
290 if (dst + len <= dst_end)
291 memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
292 }
293 }
294 else if ((*src & 0x03) == 0x01)
295 {
296 idx = (*src + 1) * 64;
297 idx += *++src;
298 if (idx > hlpfile->num_phrases)
299 {
300 WINE_ERR("index in phrases %d/%d\n", idx, hlpfile->num_phrases);
301 len = 0;
302 }
303 else
304 {
305 len = hlpfile->phrases_offsets[idx + 1] - hlpfile->phrases_offsets[idx];
306 if (dst + len <= dst_end)
307 memcpy(dst, &hlpfile->phrases_buffer[hlpfile->phrases_offsets[idx]], len);
308 }
309 }
310 else if ((*src & 0x07) == 0x03)
311 {
312 len = (*src / 8) + 1;
313 if (dst + len <= dst_end)
314 memcpy(dst, src + 1, len);
315 src += len;
316 }
317 else
318 {
319 len = (*src / 16) + 1;
320 if (dst + len <= dst_end)
321 memset(dst, ((*src & 0x0F) == 0x07) ? ' ' : 0, len);
322 }
323 dst += len;
324 }
325
326 if (dst > dst_end) WINE_ERR("buffer overflow (%p > %p)\n", dst, dst_end);
327 return TRUE;
328}
329
330/******************************************************************
331 * HLPFILE_UncompressRLE
332 *
333 *
334 */
335static void HLPFILE_UncompressRLE(const BYTE* src, const BYTE* end, BYTE* dst, unsigned dstsz)
336{
337 BYTE ch;
338 BYTE* sdst = dst + dstsz;
339
340 while (src < end)
341 {
342 ch = *src++;
343 if (ch & 0x80)
344 {
345 ch &= 0x7F;
346 if (dst + ch <= sdst)
347 memcpy(dst, src, ch);
348 src += ch;
349 }
350 else
351 {
352 if (dst + ch <= sdst)
353 memset(dst, (char)*src, ch);
354 src++;
355 }
356 dst += ch;
357 }
358 if (dst != sdst)
359 WINE_WARN("Buffer X-flow: d(%lu) instead of d(%u)\n",
360 (SIZE_T)(dst - (sdst - dstsz)), dstsz);
361}
362
363
364/******************************************************************
365 * HLPFILE_PageByOffset
366 *
367 *
368 */
370{
372 HLPFILE_PAGE* found;
373
374 if (!hlpfile) return 0;
375
376 WINE_TRACE("<%s>[%x]\n", debugstr_a(hlpfile->lpszPath), offset);
377
378 if (offset == 0xFFFFFFFF) return NULL;
379 page = NULL;
380
381 for (found = NULL, page = hlpfile->first_page; page; page = page->next)
382 {
383 if (page->offset <= offset && (!found || found->offset < page->offset))
384 {
385 *relative = offset - page->offset;
386 found = page;
387 }
388 }
389 if (!found)
390 WINE_ERR("Page of offset %u not found in file %s\n",
391 offset, debugstr_a(hlpfile->lpszPath));
392 return found;
393}
394
395/***********************************************************************
396 *
397 * HLPFILE_Contents
398 */
399static HLPFILE_PAGE* HLPFILE_Contents(HLPFILE *hlpfile, ULONG* relative)
400{
402
403 if (!hlpfile) return NULL;
404
405 page = HLPFILE_PageByOffset(hlpfile, hlpfile->contents_start, relative);
406 if (!page)
407 {
408 page = hlpfile->first_page;
409 *relative = 0;
410 }
411 return page;
412}
413
414/**************************************************************************
415 * comp_PageByHash
416 *
417 * HLPFILE_BPTreeCompare function for '|CONTEXT' B+ tree file
418 *
419 */
420static int comp_PageByHash(void *p, const void *key,
421 int leaf, void** next)
422{
423 LONG lKey = (LONG_PTR)key;
424 LONG lTest = (INT)GET_UINT(p, 0);
425
426 *next = (char *)p+(leaf?8:6);
427 WINE_TRACE("Comparing '%d' with '%d'\n", lKey, lTest);
428 if (lTest < lKey) return -1;
429 if (lTest > lKey) return 1;
430 return 0;
431}
432
433/***********************************************************************
434 *
435 * HLPFILE_PageByHash
436 */
438{
439 BYTE *ptr;
440
441 if (!hlpfile) return NULL;
442 if (!lHash) return HLPFILE_Contents(hlpfile, relative);
443
444 WINE_TRACE("<%s>[%x]\n", debugstr_a(hlpfile->lpszPath), lHash);
445
446 /* For win 3.0 files hash values are really page numbers */
447 if (hlpfile->version <= 16)
448 {
449 if (lHash >= hlpfile->wTOMapLen) return NULL;
450 return HLPFILE_PageByOffset(hlpfile, hlpfile->TOMap[lHash], relative);
451 }
452
454 if (!ptr)
455 {
456 WINE_ERR("Page of hash %x not found in file %s\n", lHash, debugstr_a(hlpfile->lpszPath));
457 return NULL;
458 }
459
460 return HLPFILE_PageByOffset(hlpfile, GET_UINT(ptr, 4), relative);
461}
462
463/***********************************************************************
464 *
465 * HLPFILE_PageByMap
466 */
468{
469 unsigned int i;
470
471 if (!hlpfile) return 0;
472
473 WINE_TRACE("<%s>[%x]\n", debugstr_a(hlpfile->lpszPath), lMap);
474
475 for (i = 0; i < hlpfile->wMapLen; i++)
476 {
477 if (hlpfile->Map[i].lMap == lMap)
478 return HLPFILE_PageByOffset(hlpfile, hlpfile->Map[i].offset, relative);
479 }
480
481 WINE_ERR("Page of Map %x not found in file %s\n", lMap, debugstr_a(hlpfile->lpszPath));
482 return NULL;
483}
484
485/**************************************************************************
486 * comp_FindSubFile
487 *
488 * HLPFILE_BPTreeCompare function for HLPFILE directory.
489 *
490 */
491static int comp_FindSubFile(void *p, const void *key,
492 int leaf, void** next)
493{
494 *next = (char *)p+strlen(p)+(leaf?5:3);
495 WINE_TRACE("Comparing %s with %s\n", debugstr_a((char *)p), debugstr_a((const char *)key));
496 return strcmp(p, key);
497}
498
499/***********************************************************************
500 *
501 * HLPFILE_FindSubFile
502 */
503static BOOL HLPFILE_FindSubFile(HLPFILE* hlpfile, LPCSTR name, BYTE **subbuf, BYTE **subend)
504{
505 BYTE *ptr;
506
507 WINE_TRACE("looking for file %s\n", debugstr_a(name));
508 ptr = HLPFILE_BPTreeSearch(hlpfile->file_buffer + GET_UINT(hlpfile->file_buffer, 4),
510 if (!ptr)
511 { /* Subfiles with bitmap images are usually prefixed with '|', but sometimes not.
512 Unfortunately, there is no consensus among different pieces of unofficial
513 documentation. So remove leading '|' and try again. */
514 CHAR c = *name++;
515 if (c == '|')
516 {
517 WINE_TRACE("not found. try %s\n", debugstr_a(name));
518 ptr = HLPFILE_BPTreeSearch(hlpfile->file_buffer + GET_UINT(hlpfile->file_buffer, 4),
520 }
521 }
522 if (!ptr) return FALSE;
523 *subbuf = hlpfile->file_buffer + GET_UINT(ptr, strlen(name)+1);
524 if (*subbuf >= hlpfile->file_buffer + hlpfile->file_buffer_size)
525 {
526 WINE_ERR("internal file %s does not fit\n", debugstr_a(name));
527 return FALSE;
528 }
529 *subend = *subbuf + GET_UINT(*subbuf, 0);
530 if (*subend > hlpfile->file_buffer + hlpfile->file_buffer_size)
531 {
532 WINE_ERR("internal file %s does not fit\n", debugstr_a(name));
533 return FALSE;
534 }
535 if (GET_UINT(*subbuf, 0) < GET_UINT(*subbuf, 4) + 9)
536 {
537 WINE_ERR("invalid size provided for internal file %s\n", debugstr_a(name));
538 return FALSE;
539 }
540 return TRUE;
541}
542
543/***********************************************************************
544 *
545 * HLPFILE_Hash
546 */
548{
549 LONG lHash = 0;
550 CHAR c;
551
552 while ((c = *lpszContext++))
553 {
554 CHAR x = 0;
555 if (c >= 'A' && c <= 'Z') x = c - 'A' + 17;
556 if (c >= 'a' && c <= 'z') x = c - 'a' + 17;
557 if (c >= '1' && c <= '9') x = c - '0';
558 if (c == '0') x = 10;
559 if (c == '.') x = 12;
560 if (c == '_') x = 13;
561 if (x) lHash = lHash * 43 + x;
562 }
563 return lHash;
564}
565
566static LONG fetch_long(const BYTE** ptr)
567{
568 LONG ret;
569
570 if (*(*ptr) & 1)
571 {
572 ret = (*(const ULONG*)(*ptr) - 0x80000000) / 2;
573 (*ptr) += 4;
574 }
575 else
576 {
577 ret = (*(const USHORT*)(*ptr) - 0x8000) / 2;
578 (*ptr) += 2;
579 }
580
581 return ret;
582}
583
584static ULONG fetch_ulong(const BYTE** ptr)
585{
586 ULONG ret;
587
588 if (*(*ptr) & 1)
589 {
590 ret = *(const ULONG*)(*ptr) / 2;
591 (*ptr) += 4;
592 }
593 else
594 {
595 ret = *(const USHORT*)(*ptr) / 2;
596 (*ptr) += 2;
597 }
598 return ret;
599}
600
601static short fetch_short(const BYTE** ptr)
602{
603 short ret;
604
605 if (*(*ptr) & 1)
606 {
607 ret = (*(const unsigned short*)(*ptr) - 0x8000) / 2;
608 (*ptr) += 2;
609 }
610 else
611 {
612 ret = (*(const unsigned char*)(*ptr) - 0x80) / 2;
613 (*ptr)++;
614 }
615 return ret;
616}
617
618static unsigned short fetch_ushort(const BYTE** ptr)
619{
620 unsigned short ret;
621
622 if (*(*ptr) & 1)
623 {
624 ret = *(const unsigned short*)(*ptr) / 2;
625 (*ptr) += 2;
626 }
627 else
628 {
629 ret = *(const unsigned char*)(*ptr) / 2;
630 (*ptr)++;
631 }
632 return ret;
633}
634
635/******************************************************************
636 * HLPFILE_DecompressGfx
637 *
638 * Decompress the data part of a bitmap or a metafile
639 */
640static const BYTE* HLPFILE_DecompressGfx(const BYTE* src, unsigned csz, unsigned sz, BYTE packing,
641 BYTE** alloc)
642{
643 const BYTE* dst;
644 BYTE* tmp;
645 unsigned sz77;
646
647 WINE_TRACE("Unpacking (%d) from %u bytes to %u bytes\n", packing, csz, sz);
648
649 switch (packing)
650 {
651 case 0: /* uncompressed */
652 if (sz != csz)
653 WINE_WARN("Bogus gfx sizes (uncompressed): %u / %u\n", sz, csz);
654 dst = src;
655 *alloc = NULL;
656 break;
657 case 1: /* RunLen */
658 dst = *alloc = HeapAlloc(GetProcessHeap(), 0, sz);
659 if (!dst) return NULL;
660 HLPFILE_UncompressRLE(src, src + csz, *alloc, sz);
661 break;
662 case 2: /* LZ77 */
664 dst = *alloc = HeapAlloc(GetProcessHeap(), 0, sz77);
665 if (!dst) return NULL;
667 if (sz77 != sz)
668 WINE_WARN("Bogus gfx sizes (LZ77): %u / %u\n", sz77, sz);
669 break;
670 case 3: /* LZ77 then RLE */
672 tmp = HeapAlloc(GetProcessHeap(), 0, sz77);
673 if (!tmp) return FALSE;
674 HLPFILE_UncompressLZ77(src, src + csz, tmp);
675 dst = *alloc = HeapAlloc(GetProcessHeap(), 0, sz);
676 if (!dst)
677 {
678 HeapFree(GetProcessHeap(), 0, tmp);
679 return FALSE;
680 }
681 HLPFILE_UncompressRLE(tmp, tmp + sz77, *alloc, sz);
682 HeapFree(GetProcessHeap(), 0, tmp);
683 break;
684 default:
685 WINE_FIXME("Unsupported packing %u\n", packing);
686 return NULL;
687 }
688 return dst;
689}
690
691static BOOL HLPFILE_RtfAddRawString(struct RtfData* rd, const char* str, size_t sz)
692{
693 if (rd->ptr + sz >= rd->data + rd->allocated)
694 {
695 char* new = HeapReAlloc(GetProcessHeap(), 0, rd->data, rd->allocated *= 2);
696 if (!new) return FALSE;
697 rd->ptr = new + (rd->ptr - rd->data);
698 rd->data = new;
699 }
700 memcpy(rd->ptr, str, sz);
701 rd->ptr += sz;
702
703 return TRUE;
704}
705
706static BOOL HLPFILE_RtfAddControl(struct RtfData* rd, const char* str)
707{
708 WINE_TRACE("%s\n", debugstr_a(str));
709 if (*str == '\\' || *str == '{') rd->in_text = FALSE;
710 else if (*str == '}') rd->in_text = TRUE;
712}
713
714static BOOL HLPFILE_RtfAddText(struct RtfData* rd, const char* str)
715{
716 const char* p;
717 const char* last;
718 const char* replace;
719 unsigned rlen;
720
721 if (!rd->in_text)
722 {
723 if (!HLPFILE_RtfAddRawString(rd, " ", 1)) return FALSE;
724 rd->in_text = TRUE;
725 }
726 for (last = p = str; *p; p++)
727 {
728 if (*p & 0x80) /* escape non-ASCII chars */
729 {
730 static char xx[8];
731 rlen = sprintf(xx, "\\'%x", *(const BYTE*)p);
732 replace = xx;
733 }
734 else switch (*p)
735 {
736 case '{': rlen = 2; replace = "\\{"; break;
737 case '}': rlen = 2; replace = "\\}"; break;
738 case '\\': rlen = 2; replace = "\\\\"; break;
739 default: continue;
740 }
741 if ((p != last && !HLPFILE_RtfAddRawString(rd, last, p - last)) ||
742 !HLPFILE_RtfAddRawString(rd, replace, rlen)) return FALSE;
743 last = p + 1;
744 }
746}
747
748/******************************************************************
749 * RtfAddHexBytes
750 *
751 */
752static BOOL HLPFILE_RtfAddHexBytes(struct RtfData* rd, const void* _ptr, unsigned sz)
753{
754 char tmp[512];
755 unsigned i, step;
756 const BYTE* ptr = _ptr;
757 static const char* _2hex = "0123456789abcdef";
758
759 if (!rd->in_text)
760 {
761 if (!HLPFILE_RtfAddRawString(rd, " ", 1)) return FALSE;
762 rd->in_text = TRUE;
763 }
764 for (; sz; sz -= step)
765 {
766 step = min(256, sz);
767 for (i = 0; i < step; i++)
768 {
769 tmp[2 * i + 0] = _2hex[*ptr >> 4];
770 tmp[2 * i + 1] = _2hex[*ptr++ & 0xF];
771 }
772 if (!HLPFILE_RtfAddRawString(rd, tmp, 2 * step)) return FALSE;
773 }
774 return TRUE;
775}
776
777static HLPFILE_LINK* HLPFILE_AllocLink(struct RtfData* rd, int cookie,
778 const char* str, unsigned len, LONG hash,
779 BOOL clrChange, BOOL bHotSpot, unsigned wnd);
780
781/******************************************************************
782 * HLPFILE_AddHotSpotLinks
783 *
784 */
786 const BYTE* start, ULONG hs_size, ULONG hs_offset)
787{
788 unsigned i, hs_num;
789 ULONG hs_macro;
790 const char* str;
791
792 if (hs_size == 0 || hs_offset == 0) return;
793
794 start += hs_offset;
795 /* always 1 ?? */
796 hs_num = GET_USHORT(start, 1);
797 hs_macro = GET_UINT(start, 3);
798
799 str = (const char*)start + 7 + 15 * hs_num + hs_macro;
800 /* FIXME: should use hs_size to prevent out of bounds reads */
801 for (i = 0; i < hs_num; i++)
802 {
803 HLPFILE_HOTSPOTLINK* hslink;
804
805 WINE_TRACE("%02x-%02x%02x {%s,%s}\n",
806 start[7 + 15 * i + 0], start[7 + 15 * i + 1], start[7 + 15 * i + 2],
808 /* str points to two null terminated strings:
809 * hotspot name, then link name
810 */
811 str += strlen(str) + 1; /* skip hotspot name */
812
813 hslink = NULL;
814 switch (start[7 + 15 * i + 0])
815 /* The next two chars always look like 0x04 0x00 ???
816 * What are they for ?
817 */
818 {
819 case 0xC8:
820 hslink = (HLPFILE_HOTSPOTLINK*)
821 HLPFILE_AllocLink(rd, hlp_link_macro, str, -1, 0, FALSE, TRUE, -1);
822 break;
823
824 case 0xE6:
825 case 0xE7:
826 hslink = (HLPFILE_HOTSPOTLINK*)
827 HLPFILE_AllocLink(rd, (start[7 + 15 * i + 0] & 1) ? hlp_link_link : hlp_link_popup,
828 file->lpszPath, -1, HLPFILE_Hash(str),
829 FALSE, TRUE, -1);
830 break;
831
832 case 0xEE:
833 case 0xEF:
834 {
835 const char* win = strchr(str, '>');
836 int wnd = -1;
837 char* tgt = NULL;
838
839 if (win)
840 {
841 for (wnd = file->numWindows - 1; wnd >= 0; wnd--)
842 {
843 if (!strcmp(win + 1, file->windows[wnd].name)) break;
844 }
845 if (wnd == -1)
846 WINE_WARN("Couldn't find window info for %s\n", debugstr_a(win));
847 if ((tgt = HeapAlloc(GetProcessHeap(), 0, win - str + 1)))
848 {
849 memcpy(tgt, str, win - str);
850 tgt[win - str] = '\0';
851 }
852 }
853 hslink = (HLPFILE_HOTSPOTLINK*)
854 HLPFILE_AllocLink(rd, (start[7 + 15 * i + 0] & 1) ? hlp_link_link : hlp_link_popup,
855 file->lpszPath, -1, HLPFILE_Hash(tgt ? tgt : str), FALSE, TRUE, wnd);
856 HeapFree(GetProcessHeap(), 0, tgt);
857 break;
858 }
859 default:
860 WINE_FIXME("unknown hotsport target 0x%x\n", start[7 + 15 * i + 0]);
861 }
862 if (hslink)
863 {
864 hslink->x = GET_USHORT(start, 7 + 15 * i + 3);
865 hslink->y = GET_USHORT(start, 7 + 15 * i + 5);
866 hslink->width = GET_USHORT(start, 7 + 15 * i + 7);
867 hslink->height = GET_USHORT(start, 7 + 15 * i + 9);
868 /* target = GET_UINT(start, 7 + 15 * i + 11); */
869 }
870 str += strlen(str) + 1;
871 }
872}
873
874/******************************************************************
875 * HLPFILE_RtfAddTransparentBitmap
876 *
877 * We'll transform a transparent bitmap into an metafile that
878 * we then transform into RTF
879 */
881 const void* pict, unsigned nc)
882{
883 HDC hdc, hdcMask, hdcMem, hdcEMF;
884 HBITMAP hbm, hbmMask, hbmOldMask, hbmOldMem;
885 HENHMETAFILE hEMF;
886 BOOL ret = FALSE;
887 void* data;
888 UINT sz;
889
890 hbm = CreateDIBitmap(hdc = GetDC(0), &bi->bmiHeader,
891 CBM_INIT, pict, bi, DIB_RGB_COLORS);
892
894 hbmOldMem = SelectObject(hdcMem, hbm);
895
896 /* create the mask bitmap from the main bitmap */
897 hdcMask = CreateCompatibleDC(hdc);
898 hbmMask = CreateBitmap(bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, 1, 1, NULL);
899 hbmOldMask = SelectObject(hdcMask, hbmMask);
901 RGB(bi->bmiColors[nc - 1].rgbRed,
902 bi->bmiColors[nc - 1].rgbGreen,
903 bi->bmiColors[nc - 1].rgbBlue));
904 BitBlt(hdcMask, 0, 0, bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, hdcMem, 0, 0, SRCCOPY);
905
906 /* sets to RGB(0,0,0) the transparent bits in main bitmap */
907 SetBkColor(hdcMem, RGB(0,0,0));
908 SetTextColor(hdcMem, RGB(255,255,255));
909 BitBlt(hdcMem, 0, 0, bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, hdcMask, 0, 0, SRCAND);
910
911 SelectObject(hdcMask, hbmOldMask);
912 DeleteDC(hdcMask);
913
914 SelectObject(hdcMem, hbmOldMem);
916
917 /* we create the bitmap on the fly */
918 hdcEMF = CreateEnhMetaFileW(NULL, NULL, NULL, NULL);
919 hdcMem = CreateCompatibleDC(hdcEMF);
920
921 /* sets to RGB(0,0,0) the transparent bits in final bitmap */
922 hbmOldMem = SelectObject(hdcMem, hbmMask);
923 SetBkColor(hdcEMF, RGB(255, 255, 255));
924 SetTextColor(hdcEMF, RGB(0, 0, 0));
925 BitBlt(hdcEMF, 0, 0, bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, hdcMem, 0, 0, SRCAND);
926
927 /* and copy the remaining bits of main bitmap */
929 BitBlt(hdcEMF, 0, 0, bi->bmiHeader.biWidth, bi->bmiHeader.biHeight, hdcMem, 0, 0, SRCPAINT);
930 SelectObject(hdcMem, hbmOldMem);
932
933 /* do the cleanup */
934 ReleaseDC(0, hdc);
935 DeleteObject(hbmMask);
937
938 hEMF = CloseEnhMetaFile(hdcEMF);
939
940 /* generate rtf stream */
941 sz = GetEnhMetaFileBits(hEMF, 0, NULL);
942 if (sz && (data = HeapAlloc(GetProcessHeap(), 0, sz)))
943 {
944 if (sz == GetEnhMetaFileBits(hEMF, sz, data))
945 {
946 ret = HLPFILE_RtfAddControl(rd, "{\\pict\\emfblip") &&
949 }
951 }
952 DeleteEnhMetaFile(hEMF);
953
954 return ret;
955}
956
957/******************************************************************
958 * HLPFILE_RtfAddBitmap
959 *
960 */
961static BOOL HLPFILE_RtfAddBitmap(struct RtfData* rd, HLPFILE* file, const BYTE* beg, BYTE type, BYTE pack)
962{
963 const BYTE* ptr;
964 const BYTE* pict_beg;
965 BYTE* alloc = NULL;
966 BITMAPINFO* bi;
967 ULONG off, csz;
968 unsigned nc = 0;
969 BOOL clrImportant = FALSE;
970 BOOL ret = FALSE;
971 char tmp[256];
972 unsigned hs_size, hs_offset;
973
974 bi = HeapAlloc(GetProcessHeap(), 0, sizeof(*bi));
975 if (!bi) return FALSE;
976
977 ptr = beg + 2; /* for type and pack */
978
979 bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
987 clrImportant = fetch_ulong(&ptr);
988 bi->bmiHeader.biClrImportant = (clrImportant > 1) ? clrImportant : 0;
990 if (bi->bmiHeader.biBitCount > 32) WINE_FIXME("Unknown bit count %u\n", bi->bmiHeader.biBitCount);
991 if (bi->bmiHeader.biPlanes != 1) WINE_FIXME("Unsupported planes %u\n", bi->bmiHeader.biPlanes);
992 bi->bmiHeader.biSizeImage = (((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8) * bi->bmiHeader.biHeight;
993 WINE_TRACE("planes=%d bc=%d size=(%d,%d)\n",
996
997 csz = fetch_ulong(&ptr);
998 hs_size = fetch_ulong(&ptr);
999
1000 off = GET_UINT(ptr, 0); ptr += 4;
1001 hs_offset = GET_UINT(ptr, 0); ptr += 4;
1002 HLPFILE_AddHotSpotLinks(rd, file, beg, hs_size, hs_offset);
1003
1004 /* now read palette info */
1005 if (type == 0x06)
1006 {
1007 unsigned i;
1008
1009 nc = bi->bmiHeader.biClrUsed;
1010 /* not quite right, especially for bitfields type of compression */
1011 if (!nc && bi->bmiHeader.biBitCount <= 8)
1012 nc = 1 << bi->bmiHeader.biBitCount;
1013
1014 bi = HeapReAlloc(GetProcessHeap(), 0, bi, sizeof(*bi) + nc * sizeof(RGBQUAD));
1015 if (!bi) return FALSE;
1016 for (i = 0; i < nc; i++)
1017 {
1018 bi->bmiColors[i].rgbBlue = ptr[0];
1019 bi->bmiColors[i].rgbGreen = ptr[1];
1020 bi->bmiColors[i].rgbRed = ptr[2];
1021 bi->bmiColors[i].rgbReserved = 0;
1022 ptr += 4;
1023 }
1024 }
1025 pict_beg = HLPFILE_DecompressGfx(beg + off, csz, bi->bmiHeader.biSizeImage, pack, &alloc);
1026
1027 if (clrImportant == 1 && nc > 0)
1028 {
1029 ret = HLPFILE_RtfAddTransparentBitmap(rd, bi, pict_beg, nc);
1030 goto done;
1031 }
1032 if (!HLPFILE_RtfAddControl(rd, "{\\pict")) goto done;
1033 if (type == 0x06)
1034 {
1035 sprintf(tmp, "\\dibitmap0\\picw%d\\pich%d",
1037 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1038 if (!HLPFILE_RtfAddHexBytes(rd, bi, sizeof(*bi) + nc * sizeof(RGBQUAD))) goto done;
1039 }
1040 else
1041 {
1042 sprintf(tmp, "\\wbitmap0\\wbmbitspixel%d\\wbmplanes%d\\picw%d\\pich%d",
1045 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1046 }
1047 if (!HLPFILE_RtfAddHexBytes(rd, pict_beg, bi->bmiHeader.biSizeImage)) goto done;
1048 if (!HLPFILE_RtfAddControl(rd, "}")) goto done;
1049
1050 ret = TRUE;
1051done:
1052 HeapFree(GetProcessHeap(), 0, bi);
1054
1055 return ret;
1056}
1057
1058/******************************************************************
1059 * HLPFILE_RtfAddMetaFile
1060 *
1061 */
1062static BOOL HLPFILE_RtfAddMetaFile(struct RtfData* rd, HLPFILE* file, const BYTE* beg, BYTE pack)
1063{
1064 ULONG size, csize, off, hs_offset, hs_size;
1065 const BYTE* ptr;
1066 const BYTE* bits;
1067 BYTE* alloc = NULL;
1068 char tmp[256];
1069 unsigned mm;
1070 BOOL ret;
1071
1072 WINE_TRACE("Loading metafile\n");
1073
1074 ptr = beg + 2; /* for type and pack */
1075
1076 mm = fetch_ushort(&ptr); /* mapping mode */
1077 sprintf(tmp, "{\\pict\\wmetafile%u\\picw%u\\pich%u",
1078 mm, GET_USHORT(ptr, 0), GET_USHORT(ptr, 2));
1079 if (!HLPFILE_RtfAddControl(rd, tmp)) return FALSE;
1080 ptr += 4;
1081
1082 size = fetch_ulong(&ptr); /* decompressed size */
1083 csize = fetch_ulong(&ptr); /* compressed size */
1084 hs_size = fetch_ulong(&ptr); /* hotspot size */
1085 off = GET_UINT(ptr, 0);
1086 hs_offset = GET_UINT(ptr, 4);
1087 ptr += 8;
1088
1089 HLPFILE_AddHotSpotLinks(rd, file, beg, hs_size, hs_offset);
1090
1091 WINE_TRACE("sz=%u csz=%u offs=%u/%u,%u/%u\n",
1092 size, csize, off, (ULONG)(ptr - beg), hs_size, hs_offset);
1093
1094 bits = HLPFILE_DecompressGfx(beg + off, csize, size, pack, &alloc);
1095 if (!bits) return FALSE;
1096
1099
1101
1102 return ret;
1103}
1104
1105/******************************************************************
1106 * HLPFILE_RtfAddGfxByAddr
1107 *
1108 */
1110 const BYTE* ref, ULONG size)
1111{
1112 unsigned i, numpict;
1113
1114 numpict = GET_USHORT(ref, 2);
1115 WINE_TRACE("Got picture magic=%04x #=%d\n", GET_USHORT(ref, 0), numpict);
1116
1117 for (i = 0; i < numpict; i++)
1118 {
1119 const BYTE* beg;
1120 const BYTE* ptr;
1121 BYTE type, pack;
1122
1123 WINE_TRACE("Offset[%d] = %x\n", i, GET_UINT(ref, (1 + i) * 4));
1124 beg = ptr = ref + GET_UINT(ref, (1 + i) * 4);
1125
1126 type = *ptr++;
1127 pack = *ptr++;
1128
1129 switch (type)
1130 {
1131 case 5: /* device dependent bmp */
1132 case 6: /* device independent bmp */
1133 HLPFILE_RtfAddBitmap(rd, hlpfile, beg, type, pack);
1134 break;
1135 case 8:
1136 HLPFILE_RtfAddMetaFile(rd, hlpfile, beg, pack);
1137 break;
1138 default: WINE_FIXME("Unknown type %u\n", type); return FALSE;
1139 }
1140
1141 /* FIXME: hotspots */
1142
1143 /* FIXME: implement support for multiple picture format */
1144 if (numpict != 1) WINE_FIXME("Supporting only one bitmap format per logical bitmap (for now). Using first format\n");
1145 break;
1146 }
1147 return TRUE;
1148}
1149
1150/******************************************************************
1151 * HLPFILE_RtfAddGfxByIndex
1152 *
1153 *
1154 */
1156 unsigned index)
1157{
1158 char tmp[16];
1159 BYTE *ref, *end;
1160
1161 WINE_TRACE("Loading picture #%d\n", index);
1162
1163 sprintf(tmp, "|bm%u", index);
1164
1165 if (!HLPFILE_FindSubFile(hlpfile, tmp, &ref, &end)) {WINE_WARN("no sub file\n"); return FALSE;}
1166
1167 ref += 9;
1168 return HLPFILE_RtfAddGfxByAddr(rd, hlpfile, ref, end - ref);
1169}
1170
1171/******************************************************************
1172 * HLPFILE_AllocLink
1173 *
1174 *
1175 */
1177 const char* str, unsigned len, LONG hash,
1178 BOOL clrChange, BOOL bHotSpot, unsigned wnd)
1179{
1181 char* link_str;
1182 unsigned asz = bHotSpot ? sizeof(HLPFILE_HOTSPOTLINK) : sizeof(HLPFILE_LINK);
1183
1184 /* FIXME: should build a string table for the attributes.link.lpszPath
1185 * they are reallocated for each link
1186 */
1187 if (len == -1) len = strlen(str);
1188 link = HeapAlloc(GetProcessHeap(), 0, asz + len + 1);
1189 if (!link) return NULL;
1190
1191 link->cookie = cookie;
1192 link->string = link_str = (char*)link + asz;
1193 memcpy(link_str, str, len);
1194 link_str[len] = '\0';
1195 link->hash = hash;
1196 link->bClrChange = clrChange;
1197 link->bHotSpot = bHotSpot;
1198 link->window = wnd;
1199 link->next = rd->first_link;
1200 rd->first_link = link;
1201 link->cpMin = rd->char_pos;
1202 rd->force_color = clrChange;
1203 if (rd->current_link) WINE_FIXME("Pending link\n");
1204 if (bHotSpot)
1205 link->cpMax = rd->char_pos;
1206 else
1207 rd->current_link = link;
1208
1209 WINE_TRACE("Link[%d] to %s@%08x:%d\n",
1210 link->cookie, debugstr_a(link->string), link->hash, link->window);
1211 return link;
1212}
1213
1214static unsigned HLPFILE_HalfPointsScale(HLPFILE_PAGE* page, unsigned pts)
1215{
1216 return pts * page->file->scale - page->file->rounderr;
1217}
1218
1219/***********************************************************************
1220 *
1221 * HLPFILE_BrowseParagraph
1222 */
1224 BYTE *buf, BYTE* end, unsigned* parlen)
1225{
1226 UINT textsize;
1227 const BYTE *format, *format_end;
1228 char *text, *text_base, *text_end;
1229 LONG size, blocksize, datalen;
1230 unsigned short bits;
1231 unsigned ncol = 1;
1232 short nc, lastcol, table_width;
1233 char tmp[256];
1234 BOOL ret = FALSE;
1235
1236 if (buf + 0x19 > end) {WINE_WARN("header too small\n"); return FALSE;};
1237
1238 *parlen = 0;
1239 blocksize = GET_UINT(buf, 0);
1240 size = GET_UINT(buf, 0x4);
1241 datalen = GET_UINT(buf, 0x10);
1242 text = text_base = HeapAlloc(GetProcessHeap(), 0, size);
1243 if (!text) return FALSE;
1244 if (size > blocksize - datalen)
1245 {
1246 /* need to decompress */
1247 if (page->file->hasPhrases)
1249 else if (page->file->hasPhrases40)
1251 else
1252 {
1253 WINE_FIXME("Text size is too long, splitting\n");
1254 size = blocksize - datalen;
1255 memcpy(text, buf + datalen, size);
1256 }
1257 }
1258 else
1259 memcpy(text, buf + datalen, size);
1260
1261 text_end = text + size;
1262
1263 format = buf + 0x15;
1264 format_end = buf + GET_UINT(buf, 0x10);
1265
1266 WINE_TRACE("Record type (buf[0x14]) = 0x%x\n", buf[0x14]);
1267
1268 if (buf[0x14] == HLP_DISPLAY || buf[0x14] == HLP_TABLE)
1269 {
1271 *parlen = fetch_ushort(&format);
1272 }
1273
1274 if (buf[0x14] == HLP_TABLE)
1275 {
1276 unsigned char type;
1277
1278 ncol = *format++;
1279
1280 if (!HLPFILE_RtfAddControl(rd, "\\trowd")) goto done;
1281 type = *format++;
1282 if (type == 0 || type == 2)
1283 {
1284 table_width = GET_SHORT(format, 0);
1285 format += 2;
1286 if (!HLPFILE_RtfAddControl(rd, "\\trqc")) goto done;
1287 }
1288 else
1289 table_width = 32767;
1290 WINE_TRACE("New table: cols=%d type=%x width=%d\n",
1291 ncol, type, table_width);
1292 if (ncol > 1)
1293 {
1294 int pos;
1295 sprintf(tmp, "\\trgaph%d\\trleft%d",
1296 MulDiv(HLPFILE_HalfPointsScale(page, GET_SHORT(format, 6)), table_width, 32767),
1297 MulDiv(HLPFILE_HalfPointsScale(page, GET_SHORT(format, 2) - GET_SHORT(format, 6)), table_width, 32767) - 1);
1298 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1299 pos = GET_SHORT(format, 6) / 2;
1300 for (nc = 0; nc < ncol; nc++)
1301 {
1302 WINE_TRACE("column(%d/%d) gap=%d width=%d\n",
1303 nc, ncol, GET_SHORT(format, nc*4),
1304 GET_SHORT(format, nc*4+2));
1305 pos += GET_SHORT(format, nc * 4) + GET_SHORT(format, nc * 4 + 2);
1306 sprintf(tmp, "\\cellx%d",
1307 MulDiv(HLPFILE_HalfPointsScale(page, pos), table_width, 32767));
1308 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1309 }
1310 }
1311 else
1312 {
1313 WINE_TRACE("column(0/%d) gap=%d width=%d\n",
1314 ncol, GET_SHORT(format, 0), GET_SHORT(format, 2));
1315 sprintf(tmp, "\\trleft%d\\cellx%d ",
1316 MulDiv(HLPFILE_HalfPointsScale(page, GET_SHORT(format, 2)), table_width, 32767) - 1,
1317 MulDiv(HLPFILE_HalfPointsScale(page, GET_SHORT(format, 0)), table_width, 32767));
1318 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1319 }
1320 format += ncol * 4;
1321 }
1322
1323 lastcol = -1;
1324 for (nc = 0; nc < ncol; )
1325 {
1326 WINE_TRACE("looking for format at offset %lu in column %d\n", (SIZE_T)(format - (buf + 0x15)), nc);
1327 if (!HLPFILE_RtfAddControl(rd, "\\pard")) goto done;
1328 if (buf[0x14] == HLP_TABLE)
1329 {
1330 nc = lastcol = GET_SHORT(format, 0);
1331 if (nc == -1) /* last column */
1332 {
1333 if (!HLPFILE_RtfAddControl(rd, "\\row")) goto done;
1334 rd->char_pos += 2;
1335 break;
1336 }
1337 format += 5;
1338 if (!HLPFILE_RtfAddControl(rd, "\\intbl")) goto done;
1339 }
1340 else nc++;
1341 if (buf[0x14] == HLP_DISPLAY30)
1342 format += 6;
1343 else
1344 format += 4;
1345 bits = GET_USHORT(format, 0); format += 2;
1346 if (bits & 0x0001) fetch_long(&format);
1347 if (bits & 0x0002)
1348 {
1350 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1351 }
1352 if (bits & 0x0004)
1353 {
1355 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1356 }
1357 if (bits & 0x0008)
1358 {
1360 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1361 }
1362 if (bits & 0x0010)
1363 {
1365 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1366 }
1367 if (bits & 0x0020)
1368 {
1370 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1371 }
1372 if (bits & 0x0040)
1373 {
1375 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1376 }
1377 if (bits & 0x0100)
1378 {
1379 BYTE brdr = *format++;
1380 short w;
1381
1382 if ((brdr & 0x01) && !HLPFILE_RtfAddControl(rd, "\\box")) goto done;
1383 if ((brdr & 0x02) && !HLPFILE_RtfAddControl(rd, "\\brdrt")) goto done;
1384 if ((brdr & 0x04) && !HLPFILE_RtfAddControl(rd, "\\brdrl")) goto done;
1385 if ((brdr & 0x08) && !HLPFILE_RtfAddControl(rd, "\\brdrb")) goto done;
1386 if ((brdr & 0x10) && !HLPFILE_RtfAddControl(rd, "\\brdrr")) goto done;
1387 if ((brdr & 0x20) && !HLPFILE_RtfAddControl(rd, "\\brdrth")) goto done;
1388 if (!(brdr & 0x20) && !HLPFILE_RtfAddControl(rd, "\\brdrs")) goto done;
1389 if ((brdr & 0x40) && !HLPFILE_RtfAddControl(rd, "\\brdrdb")) goto done;
1390 /* 0x80: unknown */
1391
1392 w = GET_SHORT(format, 0); format += 2;
1393 if (w)
1394 {
1395 sprintf(tmp, "\\brdrw%d", HLPFILE_HalfPointsScale(page, w));
1396 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1397 }
1398 }
1399 if (bits & 0x0200)
1400 {
1401 int i, ntab = fetch_short(&format);
1402 unsigned tab, ts;
1403 const char* kind;
1404
1405 for (i = 0; i < ntab; i++)
1406 {
1407 tab = fetch_ushort(&format);
1408 ts = (tab & 0x4000) ? fetch_ushort(&format) : 0 /* left */;
1409 switch (ts)
1410 {
1411 default: WINE_FIXME("Unknown tab style %x\n", ts);
1412 /* fall through */
1413 case 0: kind = ""; break;
1414 case 1: kind = "\\tqr"; break;
1415 case 2: kind = "\\tqc"; break;
1416 }
1417 /* FIXME: do kind */
1418 sprintf(tmp, "%s\\tx%d",
1419 kind, HLPFILE_HalfPointsScale(page, tab & 0x3FFF));
1420 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1421 }
1422 }
1423 switch (bits & 0xc00)
1424 {
1425 default: WINE_FIXME("Unsupported alignment 0xC00\n"); break;
1426 case 0: if (!HLPFILE_RtfAddControl(rd, "\\ql")) goto done; break;
1427 case 0x400: if (!HLPFILE_RtfAddControl(rd, "\\qr")) goto done; break;
1428 case 0x800: if (!HLPFILE_RtfAddControl(rd, "\\qc")) goto done; break;
1429 }
1430
1431 /* 0x1000 doesn't need space */
1432 if ((bits & 0x1000) && !HLPFILE_RtfAddControl(rd, "\\keep")) goto done;
1433 if ((bits & 0xE080) != 0)
1434 WINE_FIXME("Unsupported bits %04x, potential trouble ahead\n", bits);
1435
1436 while (text < text_end && format < format_end)
1437 {
1438 WINE_TRACE("Got text: %s (%p/%p - %p/%p)\n", debugstr_a(text), text, text_end, format, format_end);
1439 textsize = strlen(text);
1440 if (textsize)
1441 {
1442 if (rd->force_color)
1443 {
1444 if ((rd->current_link->cookie == hlp_link_popup) ?
1445 !HLPFILE_RtfAddControl(rd, "{\\uld\\cf1") :
1446 !HLPFILE_RtfAddControl(rd, "{\\ul\\cf1")) goto done;
1447 }
1448 if (!HLPFILE_RtfAddText(rd, text)) goto done;
1449 if (rd->force_color && !HLPFILE_RtfAddControl(rd, "}")) goto done;
1450 rd->char_pos += textsize;
1451 }
1452 /* else: null text, keep on storing attributes */
1453 text += textsize + 1;
1454
1455 WINE_TRACE("format=0x%02x\n", *format);
1456 if (*format == 0xff)
1457 {
1458 format++;
1459 break;
1460 }
1461
1462 switch (*format)
1463 {
1464 case 0x20:
1465 WINE_FIXME("NIY20\n");
1466 format += 5;
1467 break;
1468
1469 case 0x21:
1470 WINE_FIXME("NIY21\n");
1471 format += 3;
1472 break;
1473
1474 case 0x80:
1475 {
1476 unsigned font = GET_USHORT(format, 1);
1477 unsigned fs;
1478
1479 WINE_TRACE("Changing font to %d\n", font);
1480 format += 3;
1481 /* Font size in hlpfile is given in the same units as
1482 rtf control word \fs uses (half-points). */
1483 switch (rd->font_scale)
1484 {
1485 case 0: fs = page->file->fonts[font].LogFont.lfHeight - 4; break;
1486 default:
1487 case 1: fs = page->file->fonts[font].LogFont.lfHeight; break;
1488 case 2: fs = page->file->fonts[font].LogFont.lfHeight + 4; break;
1489 }
1490 /* FIXME: colors are missing, at a minimum; also, the bold attribute loses information */
1491
1492 sprintf(tmp, "\\f%u\\cf%u\\fs%u%s%s%s%s",
1493 font, font + 2, fs,
1494 page->file->fonts[font].LogFont.lfWeight > 400 ? "\\b" : "\\b0",
1495 page->file->fonts[font].LogFont.lfItalic ? "\\i" : "\\i0",
1496 page->file->fonts[font].LogFont.lfUnderline ? "\\ul" : "\\ul0",
1497 page->file->fonts[font].LogFont.lfStrikeOut ? "\\strike" : "\\strike0");
1498 if (!HLPFILE_RtfAddControl(rd, tmp)) goto done;
1499 }
1500 break;
1501
1502 case 0x81:
1503 if (!HLPFILE_RtfAddControl(rd, "\\line")) goto done;
1504 format += 1;
1505 rd->char_pos++;
1506 break;
1507
1508 case 0x82:
1509 if (buf[0x14] == HLP_TABLE)
1510 {
1511 if (format[1] != 0xFF)
1512 {
1513 if (!HLPFILE_RtfAddControl(rd, "\\par\\intbl")) goto done;
1514 }
1515 else if (GET_SHORT(format, 2) == -1)
1516 {
1517 if (!HLPFILE_RtfAddControl(rd, "\\cell\\intbl\\row")) goto done;
1518 rd->char_pos += 2;
1519 }
1520 else if (GET_SHORT(format, 2) == lastcol)
1521 {
1522 if (!HLPFILE_RtfAddControl(rd, "\\par\\pard")) goto done;
1523 }
1524 else
1525 {
1526 if (!HLPFILE_RtfAddControl(rd, "\\cell\\pard")) goto done;
1527 }
1528 }
1529 else if (!HLPFILE_RtfAddControl(rd, "\\par")) goto done;
1530 format += 1;
1531 rd->char_pos++;
1532 break;
1533
1534 case 0x83:
1535 if (!HLPFILE_RtfAddControl(rd, "\\tab")) goto done;
1536 format += 1;
1537 rd->char_pos++;
1538 break;
1539
1540#if 0
1541 case 0x84:
1542 format += 3;
1543 break;
1544#endif
1545
1546 case 0x86:
1547 case 0x87:
1548 case 0x88:
1549 {
1550 BYTE type = format[1];
1551
1552 /* FIXME: we don't use 'BYTE pos = (*format - 0x86);' for the image position */
1553 format += 2;
1555
1556 switch (type)
1557 {
1558 case 0x22:
1559 fetch_ushort(&format); /* hot spot */
1560 /* fall through */
1561 case 0x03:
1562 switch (GET_SHORT(format, 0))
1563 {
1564 case 0:
1566 rd->char_pos++;
1567 break;
1568 case 1:
1569 WINE_FIXME("does it work ??? %x<%u>#%u\n",
1570 GET_SHORT(format, 0),
1571 size, GET_SHORT(format, 2));
1572 HLPFILE_RtfAddGfxByAddr(rd, page->file, format + 2, size - 4);
1573 rd->char_pos++;
1574 break;
1575 default:
1576 WINE_FIXME("??? %u\n", GET_SHORT(format, 0));
1577 break;
1578 }
1579 break;
1580 case 0x05:
1581 WINE_FIXME("Got an embedded element %s\n", debugstr_a((char *)format + 6));
1582 break;
1583 default:
1584 WINE_FIXME("Got a type %d picture\n", type);
1585 break;
1586 }
1587 format += size;
1588 }
1589 break;
1590
1591 case 0x89:
1592 format += 1;
1593 if (!rd->current_link)
1594 WINE_FIXME("No existing link\n");
1595 rd->current_link->cpMax = rd->char_pos;
1596 rd->current_link = NULL;
1597 rd->force_color = FALSE;
1598 break;
1599
1600 case 0x8B:
1601 if (!HLPFILE_RtfAddControl(rd, "\\~")) goto done;
1602 format += 1;
1603 rd->char_pos++;
1604 break;
1605
1606 case 0x8C:
1607 if (!HLPFILE_RtfAddControl(rd, "\\_")) goto done;
1608 /* FIXME: it could be that hyphen is also in input stream !! */
1609 format += 1;
1610 rd->char_pos++;
1611 break;
1612
1613#if 0
1614 case 0xA9:
1615 format += 2;
1616 break;
1617#endif
1618
1619 case 0xC8:
1620 case 0xCC:
1621 WINE_TRACE("macro => %s\n", debugstr_a((char *)format + 3));
1622 HLPFILE_AllocLink(rd, hlp_link_macro, (const char*)format + 3,
1623 GET_USHORT(format, 1), 0, !(*format & 4), FALSE, -1);
1624 format += 3 + GET_USHORT(format, 1);
1625 break;
1626
1627 case 0xE0:
1628 case 0xE1:
1629 WINE_WARN("jump topic 1 => %u\n", GET_UINT(format, 1));
1630 HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup,
1631 page->file->lpszPath, -1, GET_UINT(format, 1), TRUE, FALSE, -1);
1632
1633
1634 format += 5;
1635 break;
1636
1637 case 0xE2:
1638 case 0xE3:
1639 case 0xE6:
1640 case 0xE7:
1641 WINE_WARN("jump topic 1 => %u\n", GET_UINT(format, 1));
1642 HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup,
1643 page->file->lpszPath, -1, GET_UINT(format, 1),
1644 !(*format & 4), FALSE, -1);
1645 format += 5;
1646 break;
1647
1648 case 0xEA:
1649 case 0xEB:
1650 case 0xEE:
1651 case 0xEF:
1652 {
1653 const char* ptr = (const char*) format + 8;
1654 BYTE type = format[3];
1655 int wnd = -1;
1656
1657 switch (type)
1658 {
1659 case 1:
1660 wnd = *ptr;
1661 /* fall through */
1662 case 0:
1663 ptr = page->file->lpszPath;
1664 break;
1665 case 6:
1666 for (wnd = page->file->numWindows - 1; wnd >= 0; wnd--)
1667 {
1668 if (!strcmp(ptr, page->file->windows[wnd].name)) break;
1669 }
1670 if (wnd == -1)
1671 WINE_WARN("Couldn't find window info for %s\n", debugstr_a(ptr));
1672 ptr += strlen(ptr) + 1;
1673 /* fall through */
1674 case 4:
1675 break;
1676 default:
1677 WINE_WARN("Unknown link type %d\n", type);
1678 break;
1679 }
1680 HLPFILE_AllocLink(rd, (*format & 1) ? hlp_link_link : hlp_link_popup,
1681 ptr, -1, GET_UINT(format, 4), !(*format & 4), FALSE, wnd);
1682 }
1683 format += 3 + GET_USHORT(format, 1);
1684 break;
1685
1686 default:
1687 WINE_WARN("format %02x\n", *format);
1688 format++;
1689 }
1690 }
1691 }
1692 ret = TRUE;
1693done:
1694
1695 HeapFree(GetProcessHeap(), 0, text_base);
1696 return ret;
1697}
1698
1699/******************************************************************
1700 * HLPFILE_BrowsePage
1701 *
1702 */
1704 unsigned font_scale, unsigned relative)
1705{
1706 HLPFILE *hlpfile = page->file;
1707 BYTE *buf, *end;
1708 DWORD ref = page->reference;
1709 unsigned index, old_index = -1, offset, count = 0, offs = 0;
1710 unsigned cpg, parlen;
1711 char tmp[1024];
1712 const char* ck = NULL;
1713
1714 rd->in_text = TRUE;
1715 rd->data = rd->ptr = HeapAlloc(GetProcessHeap(), 0, rd->allocated = 32768);
1716 rd->char_pos = 0;
1717 rd->first_link = rd->current_link = NULL;
1718 rd->force_color = FALSE;
1719 rd->font_scale = font_scale;
1720 rd->relative = relative;
1721 rd->char_pos_rel = 0;
1722
1723 switch (hlpfile->charset)
1724 {
1725 case DEFAULT_CHARSET:
1726 case ANSI_CHARSET: cpg = 1252; break;
1727 case SHIFTJIS_CHARSET: cpg = 932; break;
1728 case HANGEUL_CHARSET: cpg = 949; break;
1729 case GB2312_CHARSET: cpg = 936; break;
1730 case CHINESEBIG5_CHARSET: cpg = 950; break;
1731 case GREEK_CHARSET: cpg = 1253; break;
1732 case TURKISH_CHARSET: cpg = 1254; break;
1733 case HEBREW_CHARSET: cpg = 1255; break;
1734 case ARABIC_CHARSET: cpg = 1256; break;
1735 case BALTIC_CHARSET: cpg = 1257; break;
1736 case VIETNAMESE_CHARSET: cpg = 1258; break;
1737 case RUSSIAN_CHARSET: cpg = 1251; break;
1738 case EE_CHARSET: cpg = 1250; break;
1739 case THAI_CHARSET: cpg = 874; break;
1740 case JOHAB_CHARSET: cpg = 1361; break;
1741 case MAC_CHARSET: ck = "mac"; break;
1742 default:
1743 WINE_FIXME("Unsupported charset %u\n", hlpfile->charset);
1744 cpg = 1252;
1745 }
1746 if (ck)
1747 {
1748 sprintf(tmp, "{\\rtf1\\%s\\deff0", ck);
1749 if (!HLPFILE_RtfAddControl(rd, tmp)) return FALSE;
1750 }
1751 else
1752 {
1753 sprintf(tmp, "{\\rtf1\\ansi\\ansicpg%d\\deff0", cpg);
1754 if (!HLPFILE_RtfAddControl(rd, tmp)) return FALSE;
1755 }
1756
1757 /* generate font table */
1758 if (!HLPFILE_RtfAddControl(rd, "{\\fonttbl")) return FALSE;
1759 for (index = 0; index < hlpfile->numFonts; index++)
1760 {
1761 const char* family;
1762 switch (hlpfile->fonts[index].LogFont.lfPitchAndFamily & 0xF0)
1763 {
1764 case FF_MODERN: family = "modern"; break;
1765 case FF_ROMAN: family = "roman"; break;
1766 case FF_SWISS: family = "swiss"; break;
1767 case FF_SCRIPT: family = "script"; break;
1768 case FF_DECORATIVE: family = "decor"; break;
1769 default: family = "nil"; break;
1770 }
1771 sprintf(tmp, "{\\f%d\\f%s\\fprq%d\\fcharset%d %s;}",
1772 index, family,
1773 hlpfile->fonts[index].LogFont.lfPitchAndFamily & 0x0F,
1774 hlpfile->fonts[index].LogFont.lfCharSet,
1775 hlpfile->fonts[index].LogFont.lfFaceName);
1776 if (!HLPFILE_RtfAddControl(rd, tmp)) return FALSE;
1777 }
1778 if (!HLPFILE_RtfAddControl(rd, "}")) return FALSE;
1779 /* generate color table */
1780 if (!HLPFILE_RtfAddControl(rd, "{\\colortbl ;\\red0\\green128\\blue0;")) return FALSE;
1781 for (index = 0; index < hlpfile->numFonts; index++)
1782 {
1783 sprintf(tmp, "\\red%d\\green%d\\blue%d;",
1784 GetRValue(hlpfile->fonts[index].color),
1785 GetGValue(hlpfile->fonts[index].color),
1786 GetBValue(hlpfile->fonts[index].color));
1787 if (!HLPFILE_RtfAddControl(rd, tmp)) return FALSE;
1788 }
1789 if (!HLPFILE_RtfAddControl(rd, "}")) return FALSE;
1790
1791 do
1792 {
1793 if (hlpfile->version <= 16)
1794 {
1795 index = (ref - 0x0C) / hlpfile->dsize;
1796 offset = (ref - 0x0C) % hlpfile->dsize;
1797 }
1798 else
1799 {
1800 index = (ref - 0x0C) >> 14;
1801 offset = (ref - 0x0C) & 0x3FFF;
1802 }
1803
1804 if (hlpfile->version <= 16 && index != old_index && old_index != -1)
1805 {
1806 /* we jumped to the next block, adjust pointers */
1807 ref -= 12;
1808 offset -= 12;
1809 }
1810
1811 if (index >= hlpfile->topic_maplen) {WINE_WARN("maplen\n"); break;}
1812 buf = hlpfile->topic_map[index] + offset;
1813 if (buf + 0x15 >= hlpfile->topic_end) {WINE_WARN("extra\n"); break;}
1814 end = min(buf + GET_UINT(buf, 0), hlpfile->topic_end);
1815 if (index != old_index) {offs = 0; old_index = index;}
1816
1817 switch (buf[0x14])
1818 {
1819 case HLP_TOPICHDR:
1820 if (count++) goto done;
1821 break;
1822 case HLP_DISPLAY30:
1823 case HLP_DISPLAY:
1824 case HLP_TABLE:
1825 if (!HLPFILE_BrowseParagraph(page, rd, buf, end, &parlen)) return FALSE;
1826 if (relative > index * 0x8000 + offs)
1827 rd->char_pos_rel = rd->char_pos;
1828 offs += parlen;
1829 break;
1830 default:
1831 WINE_ERR("buf[0x14] = %x\n", buf[0x14]);
1832 }
1833 if (hlpfile->version <= 16)
1834 {
1835 ref += GET_UINT(buf, 0xc);
1836 if (GET_UINT(buf, 0xc) == 0)
1837 break;
1838 }
1839 else
1840 ref = GET_UINT(buf, 0xc);
1841 } while (ref != 0xffffffff);
1842done:
1843 page->first_link = rd->first_link;
1844 return HLPFILE_RtfAddControl(rd, "}");
1845}
1846
1847/******************************************************************
1848 * HLPFILE_ReadFont
1849 *
1850 *
1851 */
1853{
1854 BYTE *ref, *end;
1855 unsigned i, len, idx;
1856 unsigned face_num, dscr_num, face_offset, dscr_offset;
1857 BYTE flag, family;
1858
1859 if (!HLPFILE_FindSubFile(hlpfile, "|FONT", &ref, &end))
1860 {
1861 WINE_WARN("no subfile FONT\n");
1862 hlpfile->numFonts = 0;
1863 hlpfile->fonts = NULL;
1864 return FALSE;
1865 }
1866
1867 ref += 9;
1868
1869 face_num = GET_USHORT(ref, 0);
1870 dscr_num = GET_USHORT(ref, 2);
1871 face_offset = GET_USHORT(ref, 4);
1872 dscr_offset = GET_USHORT(ref, 6);
1873
1874 WINE_TRACE("Got NumFacenames=%u@%u NumDesc=%u@%u\n",
1875 face_num, face_offset, dscr_num, dscr_offset);
1876
1877 hlpfile->numFonts = dscr_num;
1878 hlpfile->fonts = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_FONT) * dscr_num);
1879
1880 len = (dscr_offset - face_offset) / face_num;
1881
1882 /* mvb font */
1883 if (face_offset >= 16)
1884 {
1885 hlpfile->scale = 1;
1886 hlpfile->rounderr = 0;
1887 WINE_FIXME("mvb font: not implemented\n");
1888 return FALSE;
1889 }
1890 /* new font */
1891 if (face_offset >= 12)
1892 {
1893 hlpfile->scale = 1;
1894 hlpfile->rounderr = 0;
1895 WINE_FIXME("new font: not implemented\n");
1896 return FALSE;
1897 }
1898 /* old font */
1899 hlpfile->scale = 10;
1900 hlpfile->rounderr = 5;
1901/* EPP for (i = face_offset; i < dscr_offset; i += len) */
1902/* EPP WINE_FIXME("[%d]: %*s\n", i / len, len, ref + i); */
1903 for (i = 0; i < dscr_num; i++)
1904 {
1905 flag = ref[dscr_offset + i * 11 + 0];
1906 family = ref[dscr_offset + i * 11 + 2];
1907
1908 hlpfile->fonts[i].LogFont.lfHeight = ref[dscr_offset + i * 11 + 1];
1909 hlpfile->fonts[i].LogFont.lfWidth = 0;
1910 hlpfile->fonts[i].LogFont.lfEscapement = 0;
1911 hlpfile->fonts[i].LogFont.lfOrientation = 0;
1912 hlpfile->fonts[i].LogFont.lfWeight = (flag & 1) ? 700 : 400;
1913 hlpfile->fonts[i].LogFont.lfItalic = (flag & 2) != 0;
1914 hlpfile->fonts[i].LogFont.lfUnderline = (flag & 4) != 0;
1915 hlpfile->fonts[i].LogFont.lfStrikeOut = (flag & 8) != 0;
1916 hlpfile->fonts[i].LogFont.lfCharSet = hlpfile->charset;
1921
1922 switch (family)
1923 {
1924 case 0x01: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_MODERN; break;
1925 case 0x02: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_ROMAN; break;
1926 case 0x03: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_SWISS; break;
1927 case 0x04: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_SCRIPT; break;
1928 case 0x05: hlpfile->fonts[i].LogFont.lfPitchAndFamily |= FF_DECORATIVE; break;
1929 default: WINE_FIXME("Unknown family %u\n", family);
1930 }
1931 idx = GET_USHORT(ref, dscr_offset + i * 11 + 3);
1932
1933 if (idx < face_num)
1934 {
1935 memcpy(hlpfile->fonts[i].LogFont.lfFaceName, ref + face_offset + idx * len, min(len, LF_FACESIZE - 1));
1936 hlpfile->fonts[i].LogFont.lfFaceName[min(len, LF_FACESIZE - 1)] = '\0';
1937 }
1938 else
1939 {
1940 WINE_FIXME("Too high face ref (%u/%u)\n", idx, face_num);
1941 strcpy(hlpfile->fonts[i].LogFont.lfFaceName, "Helv");
1942 }
1943 hlpfile->fonts[i].hFont = 0;
1944 hlpfile->fonts[i].color = RGB(ref[dscr_offset + i * 11 + 5],
1945 ref[dscr_offset + i * 11 + 6],
1946 ref[dscr_offset + i * 11 + 7]);
1947#define X(b,s) ((flag & (1 << b)) ? "-"s: "")
1948 WINE_TRACE("Font[%d]: flags=%02x%s%s%s%s%s%s pSize=%u family=%u face=%s[%u] color=%08x\n",
1949 i, flag,
1950 X(0, "bold"),
1951 X(1, "italic"),
1952 X(2, "underline"),
1953 X(3, "strikeOut"),
1954 X(4, "dblUnderline"),
1955 X(5, "smallCaps"),
1956 ref[dscr_offset + i * 11 + 1],
1957 family,
1958 debugstr_a(hlpfile->fonts[i].LogFont.lfFaceName), idx,
1959 GET_UINT(ref, dscr_offset + i * 11 + 5) & 0x00FFFFFF);
1960 }
1961 return TRUE;
1962}
1963
1964/***********************************************************************
1965 *
1966 * HLPFILE_ReadFileToBuffer
1967 */
1969{
1970 BYTE header[16], dummy[1];
1971
1972 if (_hread(hFile, header, 16) != 16) {WINE_WARN("header\n"); return FALSE;};
1973
1974 /* sanity checks */
1975 if (GET_UINT(header, 0) != 0x00035F3F)
1976 {WINE_WARN("wrong header\n"); return FALSE;};
1977
1978 hlpfile->file_buffer_size = GET_UINT(header, 12);
1979 hlpfile->file_buffer = HeapAlloc(GetProcessHeap(), 0, hlpfile->file_buffer_size + 1);
1980 if (!hlpfile->file_buffer) return FALSE;
1981
1982 memcpy(hlpfile->file_buffer, header, 16);
1983 if (_hread(hFile, hlpfile->file_buffer + 16, hlpfile->file_buffer_size - 16) !=hlpfile->file_buffer_size - 16)
1984 {WINE_WARN("filesize1\n"); return FALSE;};
1985
1986 if (_hread(hFile, dummy, 1) != 0) WINE_WARN("filesize2\n");
1987
1988 hlpfile->file_buffer[hlpfile->file_buffer_size] = '\0'; /* FIXME: was '0', sounds backwards to me */
1989
1990 return TRUE;
1991}
1992
1993/***********************************************************************
1994 *
1995 * HLPFILE_SystemCommands
1996 */
1998{
1999 BYTE *buf, *ptr, *end;
2000 HLPFILE_MACRO *macro, **m;
2001 LPSTR p;
2002 unsigned short magic, minor, major, flags;
2003
2004 hlpfile->lpszTitle = NULL;
2005
2006 if (!HLPFILE_FindSubFile(hlpfile, "|SYSTEM", &buf, &end)) return FALSE;
2007
2008 magic = GET_USHORT(buf + 9, 0);
2009 minor = GET_USHORT(buf + 9, 2);
2010 major = GET_USHORT(buf + 9, 4);
2011 /* gen date on 4 bytes */
2012 flags = GET_USHORT(buf + 9, 10);
2013 WINE_TRACE("Got system header: magic=%04x version=%d.%d flags=%04x\n",
2014 magic, major, minor, flags);
2015 if (magic != 0x036C || major != 1)
2016 {WINE_WARN("Wrong system header\n"); return FALSE;}
2017 if (minor <= 16)
2018 {
2019 hlpfile->tbsize = 0x800;
2020 hlpfile->compressed = FALSE;
2021 }
2022 else if (flags == 0)
2023 {
2024 hlpfile->tbsize = 0x1000;
2025 hlpfile->compressed = FALSE;
2026 }
2027 else if (flags == 4)
2028 {
2029 hlpfile->tbsize = 0x1000;
2030 hlpfile->compressed = TRUE;
2031 }
2032 else
2033 {
2034 hlpfile->tbsize = 0x800;
2035 hlpfile->compressed = TRUE;
2036 }
2037
2038 if (hlpfile->compressed)
2039 hlpfile->dsize = 0x4000;
2040 else
2041 hlpfile->dsize = hlpfile->tbsize - 0x0C;
2042
2043 hlpfile->version = minor;
2044 hlpfile->flags = flags;
2045 hlpfile->charset = DEFAULT_CHARSET;
2046
2047 if (hlpfile->version <= 16)
2048 {
2049 char *str = (char*)buf + 0x15;
2050
2051 hlpfile->lpszTitle = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
2052 if (!hlpfile->lpszTitle) return FALSE;
2053 strcpy(hlpfile->lpszTitle, str);
2054 WINE_TRACE("Title: %s\n", debugstr_a(hlpfile->lpszTitle));
2055 /* Nothing more to parse */
2056 return TRUE;
2057 }
2058 for (ptr = buf + 0x15; ptr + 4 <= end; ptr += GET_USHORT(ptr, 2) + 4)
2059 {
2060 char *str = (char*) ptr + 4;
2061 switch (GET_USHORT(ptr, 0))
2062 {
2063 case 1:
2064 if (hlpfile->lpszTitle) {WINE_WARN("title\n"); break;}
2065 hlpfile->lpszTitle = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
2066 if (!hlpfile->lpszTitle) return FALSE;
2067 strcpy(hlpfile->lpszTitle, str);
2068 WINE_TRACE("Title: %s\n", debugstr_a(hlpfile->lpszTitle));
2069 break;
2070
2071 case 2:
2072 if (hlpfile->lpszCopyright) {WINE_WARN("copyright\n"); break;}
2073 hlpfile->lpszCopyright = HeapAlloc(GetProcessHeap(), 0, strlen(str) + 1);
2074 if (!hlpfile->lpszCopyright) return FALSE;
2075 strcpy(hlpfile->lpszCopyright, str);
2076 WINE_TRACE("Copyright: %s\n", debugstr_a(hlpfile->lpszCopyright));
2077 break;
2078
2079 case 3:
2080 if (GET_USHORT(ptr, 2) != 4) {WINE_WARN("system3\n");break;}
2081 hlpfile->contents_start = GET_UINT(ptr, 4);
2082 WINE_TRACE("Setting contents start at %08lx\n", hlpfile->contents_start);
2083 break;
2084
2085 case 4:
2086 macro = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_MACRO) + strlen(str) + 1);
2087 if (!macro) break;
2088 p = (char*)macro + sizeof(HLPFILE_MACRO);
2089 strcpy(p, str);
2090 macro->lpszMacro = p;
2091 macro->next = 0;
2092 for (m = &hlpfile->first_macro; *m; m = &(*m)->next);
2093 *m = macro;
2094 break;
2095
2096 case 5:
2097 if (GET_USHORT(ptr, 4 + 4) != 1)
2098 WINE_FIXME("More than one icon, picking up first\n");
2099 /* 0x16 is sizeof(CURSORICONDIR), see user32/user_private.h */
2100 hlpfile->hIcon = CreateIconFromResourceEx(ptr + 4 + 0x16,
2101 GET_USHORT(ptr, 2) - 0x16, TRUE,
2102 0x30000, 0, 0, 0);
2103 break;
2104
2105 case 6:
2106 if (GET_USHORT(ptr, 2) != 90) {WINE_WARN("system6\n");break;}
2107
2108 if (hlpfile->windows)
2109 hlpfile->windows = HeapReAlloc(GetProcessHeap(), 0, hlpfile->windows,
2110 sizeof(HLPFILE_WINDOWINFO) * ++hlpfile->numWindows);
2111 else
2112 hlpfile->windows = HeapAlloc(GetProcessHeap(), 0,
2113 sizeof(HLPFILE_WINDOWINFO) * ++hlpfile->numWindows);
2114
2115 if (hlpfile->windows)
2116 {
2117 HLPFILE_WINDOWINFO* wi = &hlpfile->windows[hlpfile->numWindows - 1];
2118
2119 flags = GET_USHORT(ptr, 4);
2120 if (flags & 0x0001) strcpy(wi->type, &str[2]);
2121 else wi->type[0] = '\0';
2122 if (flags & 0x0002) strcpy(wi->name, &str[12]);
2123 else wi->name[0] = '\0';
2124 if (flags & 0x0004) strcpy(wi->caption, &str[21]);
2125 else lstrcpynA(wi->caption, hlpfile->lpszTitle, sizeof(wi->caption));
2126 wi->origin.x = (flags & 0x0008) ? GET_USHORT(ptr, 76) : CW_USEDEFAULT;
2127 wi->origin.y = (flags & 0x0010) ? GET_USHORT(ptr, 78) : CW_USEDEFAULT;
2128 wi->size.cx = (flags & 0x0020) ? GET_USHORT(ptr, 80) : CW_USEDEFAULT;
2129 wi->size.cy = (flags & 0x0040) ? GET_USHORT(ptr, 82) : CW_USEDEFAULT;
2130 wi->style = (flags & 0x0080) ? GET_USHORT(ptr, 84) : SW_SHOW;
2132 wi->sr_color = (flags & 0x0100) ? GET_UINT(ptr, 86) : 0xFFFFFF;
2133 wi->nsr_color = (flags & 0x0200) ? GET_UINT(ptr, 90) : 0xFFFFFF;
2134 WINE_TRACE("System-Window: flags=%c%c%c%c%c%c%c%c type=%s name=%s caption=%s (%d,%d)x(%d,%d)\n",
2135 flags & 0x0001 ? 'T' : 't',
2136 flags & 0x0002 ? 'N' : 'n',
2137 flags & 0x0004 ? 'C' : 'c',
2138 flags & 0x0008 ? 'X' : 'x',
2139 flags & 0x0010 ? 'Y' : 'y',
2140 flags & 0x0020 ? 'W' : 'w',
2141 flags & 0x0040 ? 'H' : 'h',
2142 flags & 0x0080 ? 'S' : 's',
2143 debugstr_a(wi->type), debugstr_a(wi->name), debugstr_a(wi->caption), wi->origin.x, wi->origin.y,
2144 wi->size.cx, wi->size.cy);
2145 }
2146 break;
2147 case 8:
2148 WINE_WARN("Citation: %s\n", debugstr_a((char *)ptr + 4));
2149 break;
2150 case 11:
2151 hlpfile->charset = ptr[4];
2152 WINE_TRACE("Charset: %d\n", hlpfile->charset);
2153 break;
2154 default:
2155 WINE_WARN("Unsupported SystemRecord[%d]\n", GET_USHORT(ptr, 0));
2156 }
2157 }
2158 if (!hlpfile->lpszTitle)
2160 return TRUE;
2161}
2162
2163/***********************************************************************
2164 *
2165 * HLPFILE_GetContext
2166 */
2168{
2169 BYTE *cbuf, *cend;
2170 unsigned clen;
2171
2172 if (!HLPFILE_FindSubFile(hlpfile, "|CONTEXT", &cbuf, &cend))
2173 {WINE_WARN("context0\n"); return FALSE;}
2174
2175 clen = cend - cbuf;
2176 hlpfile->Context = HeapAlloc(GetProcessHeap(), 0, clen);
2177 if (!hlpfile->Context) return FALSE;
2178 memcpy(hlpfile->Context, cbuf, clen);
2179
2180 return TRUE;
2181}
2182
2183/***********************************************************************
2184 *
2185 * HLPFILE_GetKeywords
2186 */
2188{
2189 BYTE *cbuf, *cend;
2190 unsigned clen;
2191
2192 if (!HLPFILE_FindSubFile(hlpfile, "|KWBTREE", &cbuf, &cend)) return FALSE;
2193 clen = cend - cbuf;
2194 hlpfile->kwbtree = HeapAlloc(GetProcessHeap(), 0, clen);
2195 if (!hlpfile->kwbtree) return FALSE;
2196 memcpy(hlpfile->kwbtree, cbuf, clen);
2197
2198 if (!HLPFILE_FindSubFile(hlpfile, "|KWDATA", &cbuf, &cend))
2199 {
2200 WINE_ERR("corrupted help file: kwbtree present but kwdata absent\n");
2201 HeapFree(GetProcessHeap(), 0, hlpfile->kwbtree);
2202 return FALSE;
2203 }
2204 clen = cend - cbuf;
2205 hlpfile->kwdata = HeapAlloc(GetProcessHeap(), 0, clen);
2206 if (!hlpfile->kwdata)
2207 {
2208 HeapFree(GetProcessHeap(), 0, hlpfile->kwdata);
2209 return FALSE;
2210 }
2211 memcpy(hlpfile->kwdata, cbuf, clen);
2212
2213 return TRUE;
2214}
2215
2216/***********************************************************************
2217 *
2218 * HLPFILE_GetMap
2219 */
2221{
2222 BYTE *cbuf, *cend;
2223 unsigned entries, i;
2224
2225 if (!HLPFILE_FindSubFile(hlpfile, "|CTXOMAP", &cbuf, &cend))
2226 {WINE_WARN("no map section\n"); return FALSE;}
2227
2228 entries = GET_USHORT(cbuf, 9);
2229 hlpfile->Map = HeapAlloc(GetProcessHeap(), 0, entries * sizeof(HLPFILE_MAP));
2230 if (!hlpfile->Map) return FALSE;
2231 hlpfile->wMapLen = entries;
2232 for (i = 0; i < entries; i++)
2233 {
2234 hlpfile->Map[i].lMap = GET_UINT(cbuf+11,i*8);
2235 hlpfile->Map[i].offset = GET_UINT(cbuf+11,i*8+4);
2236 }
2237 return TRUE;
2238}
2239
2240/***********************************************************************
2241 *
2242 * HLPFILE_GetTOMap
2243 */
2245{
2246 BYTE *cbuf, *cend;
2247 unsigned clen;
2248
2249 if (!HLPFILE_FindSubFile(hlpfile, "|TOMAP", &cbuf, &cend))
2250 {WINE_WARN("no tomap section\n"); return FALSE;}
2251
2252 clen = cend - cbuf - 9;
2253 hlpfile->TOMap = HeapAlloc(GetProcessHeap(), 0, clen);
2254 if (!hlpfile->TOMap) return FALSE;
2255 memcpy(hlpfile->TOMap, cbuf+9, clen);
2256 hlpfile->wTOMapLen = clen/4;
2257 return TRUE;
2258}
2259
2260/***********************************************************************
2261 *
2262 * DeleteMacro
2263 */
2265{
2267
2268 while (macro)
2269 {
2270 next = macro->next;
2271 HeapFree(GetProcessHeap(), 0, macro);
2272 macro = next;
2273 }
2274}
2275
2276/***********************************************************************
2277 *
2278 * DeletePage
2279 */
2281{
2283
2284 while (page)
2285 {
2286 next = page->next;
2287 HLPFILE_DeleteMacro(page->first_macro);
2289 page = next;
2290 }
2291}
2292
2293/***********************************************************************
2294 *
2295 * HLPFILE_FreeHlpFile
2296 */
2298{
2299 unsigned i;
2300
2301 if (!hlpfile || --hlpfile->wRefCount > 0) return;
2302
2303 if (hlpfile->next) hlpfile->next->prev = hlpfile->prev;
2304 if (hlpfile->prev) hlpfile->prev->next = hlpfile->next;
2305 else first_hlpfile = hlpfile->next;
2306
2307 if (hlpfile->numFonts)
2308 {
2309 for (i = 0; i < hlpfile->numFonts; i++)
2310 {
2311 DeleteObject(hlpfile->fonts[i].hFont);
2312 }
2313 HeapFree(GetProcessHeap(), 0, hlpfile->fonts);
2314 }
2315
2316 if (hlpfile->numBmps)
2317 {
2318 for (i = 0; i < hlpfile->numBmps; i++)
2319 {
2320 DeleteObject(hlpfile->bmps[i]);
2321 }
2322 HeapFree(GetProcessHeap(), 0, hlpfile->bmps);
2323 }
2324
2327
2328 DestroyIcon(hlpfile->hIcon);
2329 if (hlpfile->numWindows) HeapFree(GetProcessHeap(), 0, hlpfile->windows);
2330 HeapFree(GetProcessHeap(), 0, hlpfile->Context);
2331 HeapFree(GetProcessHeap(), 0, hlpfile->Map);
2332 HeapFree(GetProcessHeap(), 0, hlpfile->lpszTitle);
2333 HeapFree(GetProcessHeap(), 0, hlpfile->lpszCopyright);
2334 HeapFree(GetProcessHeap(), 0, hlpfile->file_buffer);
2335 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_offsets);
2336 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_buffer);
2337 HeapFree(GetProcessHeap(), 0, hlpfile->topic_map);
2338 HeapFree(GetProcessHeap(), 0, hlpfile->help_on_file);
2339 HeapFree(GetProcessHeap(), 0, hlpfile);
2340}
2341
2342/***********************************************************************
2343 *
2344 * HLPFILE_UncompressLZ77_Phrases
2345 */
2347{
2348 UINT i, num, dec_size, head_size;
2349 BYTE *buf, *end;
2350
2351 if (!HLPFILE_FindSubFile(hlpfile, "|Phrases", &buf, &end)) return FALSE;
2352
2353 if (hlpfile->version <= 16)
2354 head_size = 13;
2355 else
2356 head_size = 17;
2357
2358 num = hlpfile->num_phrases = GET_USHORT(buf, 9);
2359 if (buf + 2 * num + 0x13 >= end) {WINE_WARN("1a\n"); return FALSE;};
2360
2361 if (hlpfile->version <= 16)
2362 dec_size = end - buf - 15 - 2 * num;
2363 else
2364 dec_size = HLPFILE_UncompressedLZ77_Size(buf + 0x13 + 2 * num, end);
2365
2366 hlpfile->phrases_offsets = HeapAlloc(GetProcessHeap(), 0, sizeof(unsigned) * (num + 1));
2367 hlpfile->phrases_buffer = HeapAlloc(GetProcessHeap(), 0, dec_size);
2368 if (!hlpfile->phrases_offsets || !hlpfile->phrases_buffer)
2369 {
2370 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_offsets);
2371 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_buffer);
2372 return FALSE;
2373 }
2374
2375 for (i = 0; i <= num; i++)
2376 hlpfile->phrases_offsets[i] = GET_USHORT(buf, head_size + 2 * i) - 2 * num - 2;
2377
2378 if (hlpfile->version <= 16)
2379 memcpy(hlpfile->phrases_buffer, buf + 15 + 2*num, dec_size);
2380 else
2381 HLPFILE_UncompressLZ77(buf + 0x13 + 2 * num, end, (BYTE*)hlpfile->phrases_buffer);
2382
2383 hlpfile->hasPhrases = TRUE;
2384 return TRUE;
2385}
2386
2387/***********************************************************************
2388 *
2389 * HLPFILE_Uncompress_Phrases40
2390 */
2392{
2393 UINT num;
2394 INT dec_size, cpr_size;
2395 BYTE *buf_idx, *end_idx;
2396 BYTE *buf_phs, *end_phs;
2397 ULONG* ptr, mask = 0;
2398 unsigned int i;
2399 unsigned short bc, n;
2400
2401 if (!HLPFILE_FindSubFile(hlpfile, "|PhrIndex", &buf_idx, &end_idx) ||
2402 !HLPFILE_FindSubFile(hlpfile, "|PhrImage", &buf_phs, &end_phs)) return FALSE;
2403
2404 ptr = (ULONG*)(buf_idx + 9 + 28);
2405 bc = GET_USHORT(buf_idx, 9 + 24) & 0x0F;
2406 num = hlpfile->num_phrases = GET_USHORT(buf_idx, 9 + 4);
2407
2408 WINE_TRACE("Index: Magic=%08x #entries=%u CpsdSize=%u PhrImgSize=%u\n"
2409 "\tPhrImgCprsdSize=%u 0=%u bc=%x ukn=%x\n",
2410 GET_UINT(buf_idx, 9 + 0),
2411 GET_UINT(buf_idx, 9 + 4),
2412 GET_UINT(buf_idx, 9 + 8),
2413 GET_UINT(buf_idx, 9 + 12),
2414 GET_UINT(buf_idx, 9 + 16),
2415 GET_UINT(buf_idx, 9 + 20),
2416 GET_USHORT(buf_idx, 9 + 24),
2417 GET_USHORT(buf_idx, 9 + 26));
2418
2419 dec_size = GET_UINT(buf_idx, 9 + 12);
2420 cpr_size = GET_UINT(buf_idx, 9 + 16);
2421
2422 if (dec_size != cpr_size &&
2423 dec_size != HLPFILE_UncompressedLZ77_Size(buf_phs + 9, end_phs))
2424 {
2425 WINE_WARN("size mismatch %u %u\n",
2426 dec_size, HLPFILE_UncompressedLZ77_Size(buf_phs + 9, end_phs));
2427 dec_size = max(dec_size, HLPFILE_UncompressedLZ77_Size(buf_phs + 9, end_phs));
2428 }
2429
2430 hlpfile->phrases_offsets = HeapAlloc(GetProcessHeap(), 0, sizeof(unsigned) * (num + 1));
2431 hlpfile->phrases_buffer = HeapAlloc(GetProcessHeap(), 0, dec_size);
2432 if (!hlpfile->phrases_offsets || !hlpfile->phrases_buffer)
2433 {
2434 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_offsets);
2435 HeapFree(GetProcessHeap(), 0, hlpfile->phrases_buffer);
2436 return FALSE;
2437 }
2438
2439#define getbit() ((mask <<= 1) ? (*ptr & mask) != 0: (*++ptr & (mask=1)) != 0)
2440
2441 hlpfile->phrases_offsets[0] = 0;
2442 ptr--; /* as we'll first increment ptr because mask is 0 on first getbit() call */
2443 for (i = 0; i < num; i++)
2444 {
2445 for (n = 1; getbit(); n += 1 << bc);
2446 if (getbit()) n++;
2447 if (bc > 1 && getbit()) n += 2;
2448 if (bc > 2 && getbit()) n += 4;
2449 if (bc > 3 && getbit()) n += 8;
2450 if (bc > 4 && getbit()) n += 16;
2451 hlpfile->phrases_offsets[i + 1] = hlpfile->phrases_offsets[i] + n;
2452 }
2453#undef getbit
2454
2455 if (dec_size == cpr_size)
2456 memcpy(hlpfile->phrases_buffer, buf_phs + 9, dec_size);
2457 else
2458 HLPFILE_UncompressLZ77(buf_phs + 9, end_phs, (BYTE*)hlpfile->phrases_buffer);
2459
2460 hlpfile->hasPhrases40 = TRUE;
2461 return TRUE;
2462}
2463
2464/***********************************************************************
2465 *
2466 * HLPFILE_Uncompress_Topic
2467 */
2469{
2470 BYTE *buf, *ptr, *end, *newptr;
2471 unsigned int i, newsize = 0;
2472 unsigned int topic_size;
2473
2474 if (!HLPFILE_FindSubFile(hlpfile, "|TOPIC", &buf, &end))
2475 {WINE_WARN("topic0\n"); return FALSE;}
2476
2477 buf += 9; /* Skip file header */
2478 topic_size = end - buf;
2479 if (hlpfile->compressed)
2480 {
2481 hlpfile->topic_maplen = (topic_size - 1) / hlpfile->tbsize + 1;
2482
2483 for (i = 0; i < hlpfile->topic_maplen; i++)
2484 {
2485 ptr = buf + i * hlpfile->tbsize;
2486
2487 /* I don't know why, it's necessary for printman.hlp */
2488 if (ptr + 0x44 > end) ptr = end - 0x44;
2489
2490 newsize += HLPFILE_UncompressedLZ77_Size(ptr + 0xc, min(end, ptr + hlpfile->tbsize));
2491 }
2492
2493 hlpfile->topic_map = HeapAlloc(GetProcessHeap(), 0,
2494 hlpfile->topic_maplen * sizeof(hlpfile->topic_map[0]) + newsize);
2495 if (!hlpfile->topic_map) return FALSE;
2496 newptr = (BYTE*)(hlpfile->topic_map + hlpfile->topic_maplen);
2497 hlpfile->topic_end = newptr + newsize;
2498
2499 for (i = 0; i < hlpfile->topic_maplen; i++)
2500 {
2501 ptr = buf + i * hlpfile->tbsize;
2502 if (ptr + 0x44 > end) ptr = end - 0x44;
2503
2504 hlpfile->topic_map[i] = newptr;
2505 newptr = HLPFILE_UncompressLZ77(ptr + 0xc, min(end, ptr + hlpfile->tbsize), newptr);
2506 }
2507 }
2508 else
2509 {
2510 /* basically, we need to copy the TopicBlockSize byte pages
2511 * (removing the first 0x0C) in one single area in memory
2512 */
2513 hlpfile->topic_maplen = (topic_size - 1) / hlpfile->tbsize + 1;
2514 hlpfile->topic_map = HeapAlloc(GetProcessHeap(), 0,
2515 hlpfile->topic_maplen * (sizeof(hlpfile->topic_map[0]) + hlpfile->dsize));
2516 if (!hlpfile->topic_map) return FALSE;
2517 newptr = (BYTE*)(hlpfile->topic_map + hlpfile->topic_maplen);
2518 hlpfile->topic_end = newptr + topic_size;
2519
2520 for (i = 0; i < hlpfile->topic_maplen; i++)
2521 {
2522 hlpfile->topic_map[i] = newptr + i * hlpfile->dsize;
2523 memcpy(hlpfile->topic_map[i], buf + i * hlpfile->tbsize + 0x0C, hlpfile->dsize);
2524 }
2525 }
2526 return TRUE;
2527}
2528
2529/***********************************************************************
2530 *
2531 * HLPFILE_AddPage
2532 */
2533static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned ref, unsigned offset)
2534{
2536 const BYTE* title;
2537 UINT titlesize, blocksize, datalen;
2538 char* ptr;
2539 HLPFILE_MACRO*macro;
2540
2541 blocksize = GET_UINT(buf, 0);
2542 datalen = GET_UINT(buf, 0x10);
2543 title = buf + datalen;
2544 if (title > end) {WINE_WARN("page2\n"); return FALSE;};
2545
2546 titlesize = GET_UINT(buf, 4);
2547 page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize + 1);
2548 if (!page) return FALSE;
2549 page->lpszTitle = (char*)page + sizeof(HLPFILE_PAGE);
2550
2551 if (titlesize > blocksize - datalen)
2552 {
2553 /* need to decompress */
2554 if (hlpfile->hasPhrases)
2555 HLPFILE_Uncompress2(hlpfile, title, end, (BYTE*)page->lpszTitle, (BYTE*)page->lpszTitle + titlesize);
2556 else if (hlpfile->hasPhrases40)
2557 HLPFILE_Uncompress3(hlpfile, page->lpszTitle, page->lpszTitle + titlesize, title, end);
2558 else
2559 {
2560 WINE_FIXME("Text size is too long, splitting\n");
2561 titlesize = blocksize - datalen;
2562 memcpy(page->lpszTitle, title, titlesize);
2563 }
2564 }
2565 else
2566 memcpy(page->lpszTitle, title, titlesize);
2567
2568 page->lpszTitle[titlesize] = '\0';
2569
2570 if (hlpfile->first_page)
2571 {
2572 hlpfile->last_page->next = page;
2573 page->prev = hlpfile->last_page;
2574 hlpfile->last_page = page;
2575 }
2576 else
2577 {
2578 hlpfile->first_page = page;
2579 hlpfile->last_page = page;
2580 page->prev = NULL;
2581 }
2582
2583 page->file = hlpfile;
2584 page->next = NULL;
2585 page->first_macro = NULL;
2586 page->first_link = NULL;
2587 page->wNumber = GET_UINT(buf, 0x21);
2588 page->offset = offset;
2589 page->reference = ref;
2590
2591 page->browse_bwd = GET_UINT(buf, 0x19);
2592 page->browse_fwd = GET_UINT(buf, 0x1D);
2593
2594 if (hlpfile->version <= 16)
2595 {
2596 if (page->browse_bwd == 0xFFFF || page->browse_bwd == 0xFFFFFFFF)
2597 page->browse_bwd = 0xFFFFFFFF;
2598 else
2599 page->browse_bwd = hlpfile->TOMap[page->browse_bwd];
2600
2601 if (page->browse_fwd == 0xFFFF || page->browse_fwd == 0xFFFFFFFF)
2602 page->browse_fwd = 0xFFFFFFFF;
2603 else
2604 page->browse_fwd = hlpfile->TOMap[page->browse_fwd];
2605 }
2606
2607 WINE_TRACE("Added page[%d]: title=%s %08x << %08x >> %08x\n",
2608 page->wNumber, debugstr_a(page->lpszTitle),
2609 page->browse_bwd, page->offset, page->browse_fwd);
2610
2611 /* now load macros */
2612 ptr = page->lpszTitle + strlen(page->lpszTitle) + 1;
2613 while (ptr < page->lpszTitle + titlesize)
2614 {
2615 unsigned len = strlen(ptr);
2616 char* macro_str;
2617
2618 WINE_TRACE("macro: %s\n", debugstr_a(ptr));
2619 macro = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_MACRO) + len + 1);
2620 macro->lpszMacro = macro_str = (char*)(macro + 1);
2621 memcpy(macro_str, ptr, len + 1);
2622 /* FIXME: shall we really link macro in reverse order ??
2623 * may produce strange results when played at page opening
2624 */
2625 macro->next = page->first_macro;
2626 page->first_macro = macro;
2627 ptr += len + 1;
2628 }
2629
2630 return TRUE;
2631}
2632
2633/***********************************************************************
2634 *
2635 * HLPFILE_SkipParagraph
2636 */
2637static BOOL HLPFILE_SkipParagraph(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned* len)
2638{
2639 const BYTE *tmp;
2640
2641 if (!hlpfile->first_page) {WINE_WARN("no page\n"); return FALSE;};
2642 if (buf + 0x19 > end) {WINE_WARN("header too small\n"); return FALSE;};
2643
2644 tmp = buf + 0x15;
2645 if (buf[0x14] == HLP_DISPLAY || buf[0x14] == HLP_TABLE)
2646 {
2647 fetch_long(&tmp);
2648 *len = fetch_ushort(&tmp);
2649 }
2650 else *len = end-buf-15;
2651
2652 return TRUE;
2653}
2654
2655/***********************************************************************
2656 *
2657 * HLPFILE_DoReadHlpFile
2658 */
2659static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
2660{
2661 BOOL ret;
2662 HFILE hFile;
2663 OFSTRUCT ofs;
2664 BYTE* buf;
2665 DWORD ref = 0x0C;
2666 unsigned index, old_index, offset, len, offs, topicoffset;
2667
2668 hFile = OpenFile(lpszPath, &ofs, OF_READ);
2669 if (hFile == HFILE_ERROR) return FALSE;
2670
2672 _lclose(hFile);
2673 if (!ret) return FALSE;
2674
2675 if (!HLPFILE_SystemCommands(hlpfile)) return FALSE;
2676
2677 if (hlpfile->version <= 16 && !HLPFILE_GetTOMap(hlpfile)) return FALSE;
2678
2679 /* load phrases support */
2680 if (!HLPFILE_UncompressLZ77_Phrases(hlpfile))
2682
2683 if (!HLPFILE_Uncompress_Topic(hlpfile)) return FALSE;
2684 if (!HLPFILE_ReadFont(hlpfile)) return FALSE;
2685
2686 old_index = -1;
2687 offs = 0;
2688 do
2689 {
2690 BYTE* end;
2691
2692 if (hlpfile->version <= 16)
2693 {
2694 index = (ref - 0x0C) / hlpfile->dsize;
2695 offset = (ref - 0x0C) % hlpfile->dsize;
2696 }
2697 else
2698 {
2699 index = (ref - 0x0C) >> 14;
2700 offset = (ref - 0x0C) & 0x3FFF;
2701 }
2702
2703 if (hlpfile->version <= 16 && index != old_index && old_index != -1)
2704 {
2705 /* we jumped to the next block, adjust pointers */
2706 ref -= 12;
2707 offset -= 12;
2708 }
2709
2710 WINE_TRACE("ref=%08x => [%u/%u]\n", ref, index, offset);
2711
2712 if (index >= hlpfile->topic_maplen) {WINE_WARN("maplen\n"); break;}
2713 buf = hlpfile->topic_map[index] + offset;
2714 if (buf + 0x15 >= hlpfile->topic_end) {WINE_WARN("extra\n"); break;}
2715 end = min(buf + GET_UINT(buf, 0), hlpfile->topic_end);
2716 if (index != old_index) {offs = 0; old_index = index;}
2717
2718 switch (buf[0x14])
2719 {
2720 case HLP_TOPICHDR: /* Topic Header */
2721 if (hlpfile->version <= 16)
2722 topicoffset = ref + index * 12;
2723 else
2724 topicoffset = index * 0x8000 + offs;
2725 if (!HLPFILE_AddPage(hlpfile, buf, end, ref, topicoffset)) return FALSE;
2726 break;
2727
2728 case HLP_DISPLAY30:
2729 case HLP_DISPLAY:
2730 case HLP_TABLE:
2731 if (!HLPFILE_SkipParagraph(hlpfile, buf, end, &len)) return FALSE;
2732 offs += len;
2733 break;
2734
2735 default:
2736 WINE_ERR("buf[0x14] = %x\n", buf[0x14]);
2737 }
2738
2739 if (hlpfile->version <= 16)
2740 {
2741 ref += GET_UINT(buf, 0xc);
2742 if (GET_UINT(buf, 0xc) == 0)
2743 break;
2744 }
2745 else
2746 ref = GET_UINT(buf, 0xc);
2747 } while (ref != 0xffffffff);
2748
2749 HLPFILE_GetKeywords(hlpfile);
2750 HLPFILE_GetMap(hlpfile);
2751 if (hlpfile->version <= 16) return TRUE;
2752 return HLPFILE_GetContext(hlpfile);
2753}
2754
2755/***********************************************************************
2756 *
2757 * HLPFILE_ReadHlpFile
2758 */
2760{
2761 HLPFILE* hlpfile;
2762
2763 for (hlpfile = first_hlpfile; hlpfile; hlpfile = hlpfile->next)
2764 {
2765 if (!strcmp(lpszPath, hlpfile->lpszPath))
2766 {
2767 hlpfile->wRefCount++;
2768 return hlpfile;
2769 }
2770 }
2771
2773 sizeof(HLPFILE) + strlen(lpszPath) + 1);
2774 if (!hlpfile) return 0;
2775
2776 hlpfile->lpszPath = (char*)hlpfile + sizeof(HLPFILE);
2777 hlpfile->contents_start = 0xFFFFFFFF;
2778 hlpfile->next = first_hlpfile;
2779 hlpfile->wRefCount = 1;
2780
2781 strcpy(hlpfile->lpszPath, lpszPath);
2782
2783 first_hlpfile = hlpfile;
2784 if (hlpfile->next) hlpfile->next->prev = hlpfile;
2785
2786 if (!HLPFILE_DoReadHlpFile(hlpfile, lpszPath))
2787 {
2788 HLPFILE_FreeHlpFile(hlpfile);
2789 hlpfile = 0;
2790 }
2791
2792 return hlpfile;
2793}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
PBATCH_CONTEXT bc
Definition: batch.c:67
#define LongToPtr(l)
Definition: basetsd.h:91
const WCHAR * link
Definition: db.cpp:997
#define LF_FACESIZE
Definition: dimm.idl:39
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define GetProcessHeap()
Definition: compat.h:736
#define lstrcpynA
Definition: compat.h:751
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
Definition: create.c:368
const WCHAR * text
Definition: package.c:1799
unsigned char
Definition: typeof.h:29
static VOID BitBlt(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_reads_bytes_(Delta *Height) PUCHAR Buffer, _In_ ULONG BitsPerPixel, _In_ ULONG Delta)
Definition: common.c:57
#define BI_RGB
Definition: precomp.h:56
#define RGB(r, g, b)
Definition: precomp.h:71
#define GetBValue(quad)
Definition: precomp.h:75
#define GetGValue(quad)
Definition: precomp.h:74
ULONG RGBQUAD
Definition: precomp.h:59
#define GetRValue(quad)
Definition: precomp.h:73
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLintptr offset
Definition: glext.h:5920
const GLfloat * m
Definition: glext.h:10848
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
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
static BOOL HLPFILE_Uncompress_Topic(HLPFILE *hlpfile)
Definition: hlpfile.c:2468
BOOL HLPFILE_BrowsePage(HLPFILE_PAGE *page, struct RtfData *rd, unsigned font_scale, unsigned relative)
Definition: hlpfile.c:1703
static const BYTE * HLPFILE_DecompressGfx(const BYTE *src, unsigned csz, unsigned sz, BYTE packing, BYTE **alloc)
Definition: hlpfile.c:640
static LONG fetch_long(const BYTE **ptr)
Definition: hlpfile.c:566
static BOOL HLPFILE_RtfAddHexBytes(struct RtfData *rd, const void *_ptr, unsigned sz)
Definition: hlpfile.c:752
static BOOL HLPFILE_RtfAddMetaFile(struct RtfData *rd, HLPFILE *file, const BYTE *beg, BYTE pack)
Definition: hlpfile.c:1062
static short fetch_short(const BYTE **ptr)
Definition: hlpfile.c:601
static BOOL HLPFILE_RtfAddText(struct RtfData *rd, const char *str)
Definition: hlpfile.c:714
static BOOL HLPFILE_SkipParagraph(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned *len)
Definition: hlpfile.c:2637
static unsigned short fetch_ushort(const BYTE **ptr)
Definition: hlpfile.c:618
static void * HLPFILE_BPTreeSearch(BYTE *buf, const void *key, HLPFILE_BPTreeCompare comp)
Definition: hlpfile.c:69
#define getbit()
static unsigned GET_UINT(const BYTE *buffer, unsigned i)
Definition: hlpfile.c:47
static BOOL HLPFILE_GetTOMap(HLPFILE *hlpfile)
Definition: hlpfile.c:2244
HLPFILE_PAGE * HLPFILE_PageByMap(HLPFILE *hlpfile, LONG lMap, ULONG *relative)
Definition: hlpfile.c:467
static unsigned short GET_USHORT(const BYTE *buffer, unsigned i)
Definition: hlpfile.c:37
static void HLPFILE_DeletePage(HLPFILE_PAGE *page)
Definition: hlpfile.c:2280
static BOOL HLPFILE_GetContext(HLPFILE *hlpfile)
Definition: hlpfile.c:2167
void HLPFILE_BPTreeEnum(BYTE *buf, HLPFILE_BPTreeCallback cb, void *cookie)
Definition: hlpfile.c:125
static BOOL HLPFILE_ReadFont(HLPFILE *hlpfile)
Definition: hlpfile.c:1852
static BOOL HLPFILE_RtfAddControl(struct RtfData *rd, const char *str)
Definition: hlpfile.c:706
static BOOL HLPFILE_Uncompress_Phrases40(HLPFILE *hlpfile)
Definition: hlpfile.c:2391
HLPFILE_PAGE * HLPFILE_PageByHash(HLPFILE *hlpfile, LONG lHash, ULONG *relative)
Definition: hlpfile.c:437
LONG HLPFILE_Hash(LPCSTR lpszContext)
Definition: hlpfile.c:547
static INT HLPFILE_UncompressedLZ77_Size(const BYTE *ptr, const BYTE *end)
Definition: hlpfile.c:168
static HLPFILE_PAGE * HLPFILE_Contents(HLPFILE *hlpfile, ULONG *relative)
Definition: hlpfile.c:399
static BOOL HLPFILE_DoReadHlpFile(HLPFILE *hlpfile, LPCSTR lpszPath)
Definition: hlpfile.c:2659
static BOOL HLPFILE_RtfAddGfxByAddr(struct RtfData *rd, HLPFILE *hlpfile, const BYTE *ref, ULONG size)
Definition: hlpfile.c:1109
static BOOL HLPFILE_Uncompress3(HLPFILE *hlpfile, char *dst, const char *dst_end, const BYTE *src, const BYTE *src_end)
Definition: hlpfile.c:272
static void HLPFILE_Uncompress2(HLPFILE *hlpfile, const BYTE *ptr, const BYTE *end, BYTE *newptr, const BYTE *newend)
Definition: hlpfile.c:233
static ULONG fetch_ulong(const BYTE **ptr)
Definition: hlpfile.c:584
static BOOL HLPFILE_RtfAddGfxByIndex(struct RtfData *rd, HLPFILE *hlpfile, unsigned index)
Definition: hlpfile.c:1155
static int comp_FindSubFile(void *p, const void *key, int leaf, void **next)
Definition: hlpfile.c:491
void HLPFILE_FreeHlpFile(HLPFILE *hlpfile)
Definition: hlpfile.c:2297
static HLPFILE_LINK * HLPFILE_AllocLink(struct RtfData *rd, int cookie, const char *str, unsigned len, LONG hash, BOOL clrChange, BOOL bHotSpot, unsigned wnd)
Definition: hlpfile.c:1176
static short GET_SHORT(const BYTE *buffer, unsigned i)
Definition: hlpfile.c:42
static BOOL HLPFILE_RtfAddBitmap(struct RtfData *rd, HLPFILE *file, const BYTE *beg, BYTE type, BYTE pack)
Definition: hlpfile.c:961
static BOOL HLPFILE_FindSubFile(HLPFILE *hlpfile, LPCSTR name, BYTE **subbuf, BYTE **subend)
Definition: hlpfile.c:503
static void HLPFILE_UncompressRLE(const BYTE *src, const BYTE *end, BYTE *dst, unsigned dstsz)
Definition: hlpfile.c:335
HLPFILE_PAGE * HLPFILE_PageByOffset(HLPFILE *hlpfile, LONG offset, ULONG *relative)
Definition: hlpfile.c:369
static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, const BYTE *buf, const BYTE *end, unsigned ref, unsigned offset)
Definition: hlpfile.c:2533
static BOOL HLPFILE_RtfAddRawString(struct RtfData *rd, const char *str, size_t sz)
Definition: hlpfile.c:691
static int comp_PageByHash(void *p, const void *key, int leaf, void **next)
Definition: hlpfile.c:420
static BOOL HLPFILE_GetMap(HLPFILE *hlpfile)
Definition: hlpfile.c:2220
static BOOL HLPFILE_SystemCommands(HLPFILE *hlpfile)
Definition: hlpfile.c:1997
#define X(b, s)
static BOOL HLPFILE_GetKeywords(HLPFILE *hlpfile)
Definition: hlpfile.c:2187
static unsigned HLPFILE_HalfPointsScale(HLPFILE_PAGE *page, unsigned pts)
Definition: hlpfile.c:1214
static BOOL HLPFILE_BrowseParagraph(HLPFILE_PAGE *page, struct RtfData *rd, BYTE *buf, BYTE *end, unsigned *parlen)
Definition: hlpfile.c:1223
static void HLPFILE_AddHotSpotLinks(struct RtfData *rd, HLPFILE *file, const BYTE *start, ULONG hs_size, ULONG hs_offset)
Definition: hlpfile.c:785
HLPFILE * HLPFILE_ReadHlpFile(LPCSTR lpszPath)
Definition: hlpfile.c:2759
static BOOL HLPFILE_ReadFileToBuffer(HLPFILE *hlpfile, HFILE hFile)
Definition: hlpfile.c:1968
static HLPFILE * first_hlpfile
Definition: hlpfile.c:52
static void HLPFILE_DeleteMacro(HLPFILE_MACRO *macro)
Definition: hlpfile.c:2264
static BOOL HLPFILE_UncompressLZ77_Phrases(HLPFILE *hlpfile)
Definition: hlpfile.c:2346
static BOOL HLPFILE_RtfAddTransparentBitmap(struct RtfData *rd, const BITMAPINFO *bi, const void *pict, unsigned nc)
Definition: hlpfile.c:880
static BYTE * HLPFILE_UncompressLZ77(const BYTE *ptr, const BYTE *end, BYTE *newptr)
Definition: hlpfile.c:195
#define HLP_TOPICHDR
Definition: hlpfile.h:209
#define HLP_DISPLAY30
Definition: hlpfile.h:208
#define HLP_DISPLAY
Definition: hlpfile.h:210
#define HLP_TABLE
Definition: hlpfile.h:211
struct tagHlpFileHotSpotLink HLPFILE_HOTSPOTLINK
int(* HLPFILE_BPTreeCompare)(void *p, const void *key, int leaf, void **next)
Definition: hlpfile.h:168
void(* HLPFILE_BPTreeCallback)(void *p, void **next, void *cookie)
Definition: hlpfile.h:179
#define fs
Definition: i386-dis.c:444
#define bits
Definition: infblock.c:15
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1031
#define c
Definition: ke_i.h:80
#define debugstr_a
Definition: kernel32.h:31
static real win[4][36]
int WINAPI _lclose(HFILE hFile)
Definition: lfile.c:138
long WINAPI _hread(HFILE hFile, LPVOID lpBuffer, long lBytes)
Definition: lfile.c:20
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define for
Definition: utility.h:88
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static UINT UINT last
Definition: font.c:45
static DWORD page_size
Definition: loader.c:53
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE hFile
Definition: mswsock.h:90
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
u32_t magic(void)
int xx
Definition: npserver.c:29
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define INT
Definition: polytest.cpp:20
#define minor(rdev)
Definition: propsheet.cpp:929
#define major(rdev)
Definition: propsheet.cpp:928
static char title[]
Definition: ps.c:92
static unsigned __int64 next
Definition: rand_nt.c:6
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:47
#define alloc
Definition: rosglue.h:13
const WCHAR * str
int rd
Definition: scanf.h:134
#define WINE_TRACE
Definition: debug.h:354
#define WINE_WARN
Definition: debug.h:360
#define WINE_FIXME
Definition: debug.h:366
#define WINE_ERR
Definition: debug.h:371
long dst_end
Definition: timezone.c:17
#define memset(x, y, z)
Definition: compat.h:39
COLORREF color
Definition: hlpfile.h:97
HFONT hFont
Definition: hlpfile.h:96
LOGFONTA LogFont
Definition: hlpfile.h:95
LONG lMap
Definition: hlpfile.h:89
unsigned long offset
Definition: hlpfile.h:90
char name[9]
Definition: hlpfile.h:30
char type[10]
Definition: hlpfile.h:29
COLORREF nsr_color
Definition: hlpfile.h:37
COLORREF sr_color
Definition: hlpfile.h:36
char caption[51]
Definition: hlpfile.h:31
BYTE lfStrikeOut
Definition: dimm.idl:49
BYTE lfClipPrecision
Definition: dimm.idl:52
BYTE lfUnderline
Definition: dimm.idl:48
BYTE lfQuality
Definition: dimm.idl:53
BYTE lfOutPrecision
Definition: dimm.idl:51
LONG lfOrientation
Definition: dimm.idl:45
BYTE lfItalic
Definition: dimm.idl:47
BYTE lfPitchAndFamily
Definition: dimm.idl:54
LONG lfHeight
Definition: dimm.idl:42
LONG lfEscapement
Definition: dimm.idl:44
BYTE lfCharSet
Definition: dimm.idl:50
LONG lfWeight
Definition: dimm.idl:46
CHAR lfFaceName[LF_FACESIZE]
Definition: dimm.idl:55
LONG lfWidth
Definition: dimm.idl:43
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: inflate.c:139
Definition: cookie.c:34
Definition: fci.c:127
char name[1]
Definition: fci.c:135
Definition: ffs.h:70
Definition: _hash_fun.h:40
Definition: copy.c:22
Definition: name.c:39
Definition: module.h:576
Definition: send.c:48
ULONG biClrImportant
Definition: precomp.h:52
USHORT biBitCount
Definition: precomp.h:46
LONG biYPelsPerMeter
Definition: precomp.h:50
ULONG biCompression
Definition: precomp.h:47
LONG biXPelsPerMeter
Definition: precomp.h:49
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
RGBQUAD bmiColors[1]
Definition: wingdi.h:1477
UINT topic_maplen
Definition: hlpfile.h:138
unsigned * phrases_offsets
Definition: hlpfile.h:133
struct tagHlpFileFile * prev
Definition: hlpfile.h:119
LPSTR lpszTitle
Definition: hlpfile.h:105
HLPFILE_PAGE * first_page
Definition: hlpfile.h:107
HLPFILE_PAGE * last_page
Definition: hlpfile.h:108
unsigned wTOMapLen
Definition: hlpfile.h:115
unsigned long contents_start
Definition: hlpfile.h:117
HLPFILE_WINDOWINFO * windows
Definition: hlpfile.h:147
unsigned wMapLen
Definition: hlpfile.h:113
unsigned * TOMap
Definition: hlpfile.h:116
HICON hIcon
Definition: hlpfile.h:148
BYTE * kwbtree
Definition: hlpfile.h:111
UINT file_buffer_size
Definition: hlpfile.h:103
HLPFILE_MACRO * first_macro
Definition: hlpfile.h:109
HLPFILE_MAP * Map
Definition: hlpfile.h:114
unsigned short charset
Definition: hlpfile.h:126
BYTE * Context
Definition: hlpfile.h:110
BYTE * kwdata
Definition: hlpfile.h:112
unsigned numWindows
Definition: hlpfile.h:146
LPSTR lpszCopyright
Definition: hlpfile.h:106
LPSTR lpszPath
Definition: hlpfile.h:104
BOOL compressed
Definition: hlpfile.h:129
unsigned numBmps
Definition: hlpfile.h:140
BOOL hasPhrases40
Definition: hlpfile.h:131
BYTE * file_buffer
Definition: hlpfile.h:102
char * phrases_buffer
Definition: hlpfile.h:134
unsigned short version
Definition: hlpfile.h:124
UINT num_phrases
Definition: hlpfile.h:132
unsigned short tbsize
Definition: hlpfile.h:127
struct tagHlpFileFile * next
Definition: hlpfile.h:120
unsigned numFonts
Definition: hlpfile.h:143
BYTE ** topic_map
Definition: hlpfile.h:136
unsigned wRefCount
Definition: hlpfile.h:122
unsigned short flags
Definition: hlpfile.h:125
HLPFILE_FONT * fonts
Definition: hlpfile.h:144
HBITMAP * bmps
Definition: hlpfile.h:141
BYTE * topic_end
Definition: hlpfile.h:137
LPSTR help_on_file
Definition: hlpfile.h:153
unsigned short dsize
Definition: hlpfile.h:128
BOOL hasPhrases
Definition: hlpfile.h:130
LPCSTR lpszMacro
Definition: hlpfile.h:64
struct tagHlpFileMacro * next
Definition: hlpfile.h:65
unsigned offset
Definition: hlpfile.h:76
struct tagHlpFilePage * next
Definition: hlpfile.h:78
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
UCHAR rgbReserved
Definition: bootanim.c:106
UCHAR rgbBlue
Definition: bootanim.c:103
UCHAR rgbRed
Definition: bootanim.c:105
UCHAR rgbGreen
Definition: bootanim.c:104
#define max(a, b)
Definition: svc.c:63
#define LONG_PTR
Definition: treelist.c:79
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
int ret
HDC hdcMem
Definition: welcome.c:104
#define HFILE_ERROR
Definition: winbase.h:111
#define OF_READ
Definition: winbase.h:116
int HFILE
Definition: windef.h:298
#define DEFAULT_PITCH
Definition: wingdi.h:443
UINT WINAPI GetEnhMetaFileBits(_In_ HENHMETAFILE hEMF, _In_ UINT nSize, _Out_writes_bytes_opt_(nSize) LPBYTE lpData)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
#define RUSSIAN_CHARSET
Definition: wingdi.h:396
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
#define FF_MODERN
Definition: wingdi.h:449
BOOL WINAPI DeleteEnhMetaFile(_In_opt_ HENHMETAFILE)
#define FF_DECORATIVE
Definition: wingdi.h:447
#define FF_SCRIPT
Definition: wingdi.h:451
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
#define FF_ROMAN
Definition: wingdi.h:450
#define DEFAULT_QUALITY
Definition: wingdi.h:436
#define ARABIC_CHARSET
Definition: wingdi.h:394
#define HANGEUL_CHARSET
Definition: wingdi.h:387
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
HDC WINAPI CreateEnhMetaFileW(_In_opt_ HDC, _In_opt_ LPCWSTR, _In_opt_ LPCRECT, _In_opt_ LPCWSTR)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DEFAULT_CHARSET
Definition: wingdi.h:384
#define THAI_CHARSET
Definition: wingdi.h:397
#define SRCCOPY
Definition: wingdi.h:333
#define GREEK_CHARSET
Definition: wingdi.h:391
#define JOHAB_CHARSET
Definition: wingdi.h:401
#define EE_CHARSET
Definition: wingdi.h:398
#define CHINESEBIG5_CHARSET
Definition: wingdi.h:390
#define OUT_DEFAULT_PRECIS
Definition: wingdi.h:415
#define SRCPAINT
Definition: wingdi.h:334
#define ANSI_CHARSET
Definition: wingdi.h:383
HENHMETAFILE WINAPI CloseEnhMetaFile(_In_ HDC hdc)
#define CLIP_DEFAULT_PRECIS
Definition: wingdi.h:426
#define VIETNAMESE_CHARSET
Definition: wingdi.h:402
#define CBM_INIT
Definition: wingdi.h:365
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:918
BOOL WINAPI DeleteDC(_In_ HDC)
#define MAC_CHARSET
Definition: wingdi.h:403
#define HEBREW_CHARSET
Definition: wingdi.h:393
HBITMAP WINAPI CreateDIBitmap(_In_ HDC hdc, _In_opt_ const BITMAPINFOHEADER *pbmih, _In_ DWORD fdwInit, _In_opt_ const VOID *pvInit, _In_opt_ const BITMAPINFO *pbmi, _In_ UINT uUsage)
#define SHIFTJIS_CHARSET
Definition: wingdi.h:386
#define FF_SWISS
Definition: wingdi.h:452
#define GB2312_CHARSET
Definition: wingdi.h:389
#define SRCAND
Definition: wingdi.h:330
#define BALTIC_CHARSET
Definition: wingdi.h:395
#define TURKISH_CHARSET
Definition: wingdi.h:392
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HICON WINAPI CreateIconFromResourceEx(_In_reads_bytes_(dwResSize) PBYTE presbits, _In_ DWORD dwResSize, _In_ BOOL fIcon, _In_ DWORD dwVer, _In_ int cxDesired, _In_ int cyDesired, _In_ UINT Flags)
HDC WINAPI GetDC(_In_opt_ HWND)
#define CW_USEDEFAULT
Definition: winuser.h:225
#define SW_SHOW
Definition: winuser.h:775
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2053
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193