Commit a34dce46 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Vitaly Lipatov

oleaut32: Implement decoding of SLTG help strings.

Based on the patch by Sebastian Lackner <sebastian@fds-team.de>.
parent 1240bd38
...@@ -3684,6 +3684,87 @@ static BOOL TLB_GUIDFromString(const char *str, GUID *guid) ...@@ -3684,6 +3684,87 @@ static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
return TRUE; return TRUE;
} }
struct bitstream
{
const BYTE *buffer;
DWORD length;
WORD current;
};
static const char *lookup_code(const BYTE *table, DWORD table_size, struct bitstream *bits)
{
const BYTE *p = table;
while (p < table + table_size && *p == 0x80)
{
if (p + 2 >= table + table_size) return NULL;
if (!(bits->current & 0xff))
{
if (!bits->length) return NULL;
bits->current = (*bits->buffer << 8) | 1;
bits->buffer++;
bits->length--;
}
if (bits->current & 0x8000)
{
p += 3;
}
else
{
p = table + (*(p + 2) | (*(p + 1) << 8));
}
bits->current <<= 1;
}
if (p + 1 < table + table_size && *(p + 1))
{
/* FIXME: Whats the meaning of *p? */
const BYTE *q = p + 1;
while (q < table + table_size && *q) q++;
return (q < table + table_size) ? (const char *)(p + 1) : NULL;
}
return NULL;
}
static const TLBString *decode_string(const BYTE *table, const char *stream, DWORD stream_length, ITypeLibImpl *lib)
{
DWORD buf_size, table_size;
const char *p;
struct bitstream bits;
BSTR buf;
TLBString *tlbstr;
if (!stream_length) return NULL;
bits.buffer = (const BYTE *)stream;
bits.length = stream_length;
bits.current = 0;
buf_size = *(const WORD *)table;
table += sizeof(WORD);
table_size = *(const DWORD *)table;
table += sizeof(DWORD);
buf = SysAllocStringLen(NULL, buf_size);
buf[0] = 0;
while ((p = lookup_code(table, table_size, &bits)))
{
static const WCHAR spaceW[] = { ' ',0 };
if (buf[0]) lstrcatW(buf, spaceW);
MultiByteToWideChar(CP_ACP, 0, p, -1, buf + lstrlenW(buf), buf_size - lstrlenW(buf));
}
tlbstr = TLB_append_str(&lib->string_list, buf);
SysFreeString(buf);
return tlbstr;
}
static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib) static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
{ {
WORD bytelen; WORD bytelen;
...@@ -4370,17 +4451,17 @@ static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI, ...@@ -4370,17 +4451,17 @@ static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
/* Because SLTG_OtherTypeInfo is such a painful struct, we make a more /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
manageable copy of it into this */ manageable copy of it into this */
typedef struct { typedef struct {
WORD small_no;
char *index_name; char *index_name;
char *other_name; char *other_name;
WORD res1a; WORD res1a;
WORD name_offs; WORD name_offs;
WORD more_bytes; WORD hlpstr_len;
char *extra; char *extra;
WORD res20; WORD res20;
DWORD helpcontext; DWORD helpcontext;
WORD res26; WORD res26;
GUID uuid; GUID uuid;
WORD typekind;
} SLTG_InternalOtherTypeInfo; } SLTG_InternalOtherTypeInfo;
/**************************************************************************** /****************************************************************************
...@@ -4399,8 +4480,8 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) ...@@ -4399,8 +4480,8 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
LPVOID pBlk, pFirstBlk; LPVOID pBlk, pFirstBlk;
SLTG_LibBlk *pLibBlk; SLTG_LibBlk *pLibBlk;
SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks; SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
char *pAfterOTIBlks = NULL;
char *pNameTable, *ptr; char *pNameTable, *ptr;
const BYTE *hlp_strings;
int i; int i;
DWORD len, order; DWORD len, order;
ITypeInfoImpl **ppTypeInfoImpl; ITypeInfoImpl **ppTypeInfoImpl;
...@@ -4466,53 +4547,55 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) ...@@ -4466,53 +4547,55 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
len += 0x40; len += 0x40;
/* And now TypeInfoCount of SLTG_OtherTypeInfo */ /* And now TypeInfoCount of SLTG_OtherTypeInfo */
pTypeLibImpl->TypeInfoCount = *(WORD *)((char *)pLibBlk + len);
len += sizeof(WORD);
pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount); pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
ptr = (char*)pLibBlk + len; ptr = (char*)pLibBlk + len;
for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) { for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
WORD w, extra; WORD w, extra;
len = 0; len = 0;
pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr; w = *(WORD*)ptr;
w = *(WORD*)(ptr + 2);
if(w != 0xffff) { if(w != 0xffff) {
len += w; len += w;
pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1); pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w); memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 2, w);
pOtherTypeInfoBlks[i].index_name[w] = '\0'; pOtherTypeInfoBlks[i].index_name[w] = '\0';
} }
w = *(WORD*)(ptr + 4 + len); w = *(WORD*)(ptr + 2 + len);
if(w != 0xffff) { if(w != 0xffff) {
TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w)); TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 4 + len, w));
len += w;
pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1); pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w); memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 4 + len, w);
pOtherTypeInfoBlks[i].other_name[w] = '\0'; pOtherTypeInfoBlks[i].other_name[w] = '\0';
len += w;
} }
pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6); pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + 4 + len);
pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8); pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + 6 + len);
extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len); extra = pOtherTypeInfoBlks[i].hlpstr_len = *(WORD*)(ptr + 8 + len);
if(extra) { if(extra) {
pOtherTypeInfoBlks[i].extra = heap_alloc(extra); pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra); memcpy(pOtherTypeInfoBlks[i].extra, ptr + 10 + len, extra);
len += extra; len += extra;
} }
pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len); pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 10 + len);
pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len); pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 12 + len);
pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len); pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 16 + len);
memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID)); memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 18 + len, sizeof(GUID));
pOtherTypeInfoBlks[i].typekind = *(WORD*)(ptr + 18 + sizeof(GUID) + len);
len += sizeof(SLTG_OtherTypeInfo); len += sizeof(SLTG_OtherTypeInfo);
ptr += len; ptr += len;
} }
pAfterOTIBlks = ptr; /* Get the next DWORD */
len = *(DWORD*)ptr;
/* Skip this WORD and get the next DWORD */ hlp_strings = (const BYTE *)ptr + sizeof(DWORD);
len = *(DWORD*)(pAfterOTIBlks + 2); TRACE("max help string length %#x, help strings length %#x\n",
*(WORD *)hlp_strings, *(DWORD *)(hlp_strings + 2));
/* Now add this to pLibBLk look at what we're pointing at and /* Now add this to pLibBLk look at what we're pointing at and
possibly add 0x20, then add 0x216, sprinkle a bit a magic possibly add 0x20, then add 0x216, sprinkle a bit a magic
...@@ -4578,6 +4661,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) ...@@ -4578,6 +4661,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
(*ppTypeInfoImpl)->index = i; (*ppTypeInfoImpl)->index = i;
(*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl); (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
(*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext; (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
(*ppTypeInfoImpl)->DocString = decode_string(hlp_strings, pOtherTypeInfoBlks[i].extra, pOtherTypeInfoBlks[i].hlpstr_len, pTypeLibImpl);
(*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2); (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
(*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind; (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
(*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version; (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
......
...@@ -382,18 +382,18 @@ typedef struct { ...@@ -382,18 +382,18 @@ typedef struct {
/* we then get 0x40 bytes worth of 0xffff or small numbers followed by /* we then get 0x40 bytes worth of 0xffff or small numbers followed by
nrOfFileBlks - 2 of these */ nrOfFileBlks - 2 of these */
typedef struct { typedef struct {
WORD small_no;
SLTG_Name index_name; /* This refers to a name in the directory */ SLTG_Name index_name; /* This refers to a name in the directory */
SLTG_Name other_name; /* Another one of these weird names */ SLTG_Name other_name; /* Another one of these weird names */
WORD res1a; /* 0xffff */ WORD res1a; /* 0xffff */
WORD name_offs; /* offset to name in name table */ WORD name_offs; /* offset to name in name table */
WORD more_bytes; /* if this is non-zero we get this many WORD hlpstr_len; /* if this is non-zero we get this many
bytes before the next element, which seem bytes before the next element, which seem
to reference the docstring of the type ? */ to reference the docstring of the type ? */
WORD res20; /* 0xffff */ WORD res20; /* 0xffff */
DWORD helpcontext; DWORD helpcontext;
WORD res26; /* 0xffff */ WORD res26; /* 0xffff */
GUID uuid; GUID uuid;
WORD typekind;
} SLTG_OtherTypeInfo; } SLTG_OtherTypeInfo;
/* Next we get WORD 0x0003 followed by a DWORD which if we add to /* Next we get WORD 0x0003 followed by a DWORD which if we add to
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment