From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- tools/widl/write_sltg.c | 265 ++++++++++++++++++++++++++++++++++------ 1 file changed, 228 insertions(+), 37 deletions(-)
diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index 3efd4735163..ad23277c8c3 100644 --- a/tools/widl/write_sltg.c +++ b/tools/widl/write_sltg.c @@ -79,6 +79,12 @@ struct sltg_typelib struct sltg_block *typeinfo; };
+struct sltg_hrefmap +{ + int href_count; + int *href; +}; + #include "pshpack1.h" struct sltg_typeinfo_header { @@ -151,6 +157,46 @@ struct sltg_tail short res32; /* unknown */ short type_bytes; /* bytes used by type descriptions */ }; + +struct sltg_hrefinfo +{ + char magic; /* 0xdf */ + char res01; /* 0x00 */ + int res02; /* 0xffffffff */ + int res06; /* 0xffffffff */ + int res0a; /* 0xffffffff */ + int res0e; /* 0xffffffff */ + int res12; /* 0xffffffff */ + int res16; /* 0xffffffff */ + int res1a; /* 0xffffffff */ + int res1e; /* 0xffffffff */ + int res22; /* 0xffffffff */ + int res26; /* 0xffffffff */ + int res2a; /* 0xffffffff */ + int res2e; /* 0xffffffff */ + int res32; /* 0xffffffff */ + int res36; /* 0xffffffff */ + int res3a; /* 0xffffffff */ + int res3e; /* 0xffffffff */ + short res42;/* 0xffff */ + int number; /* this is 8 times the number of refs */ + /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ + + short res50;/* 0xffff */ + char res52; /* 0x01 */ + int res53; /* 0x00000000 */ + /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii + * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the + * ref refers to the nth type listed in this library (0 based). Else + * the xxxx (which maybe fewer than 4 digits) is the offset into the name + * table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#" + * The guid is the typelib guid; the ref again refers to the nth type of + * the imported typelib. + */ + + char resxx; /* 0xdf */ +}; + #include "poppack.h"
static void init_sltg_data(struct sltg_data *data) @@ -440,12 +486,12 @@ static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t return index_name; }
-static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind) +static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind, + const struct sltg_hrefmap *hrefmap) { ti->magic = 0x0501; ti->href_offset = -1; ti->res06 = -1; - ti->member_offset = sizeof(*ti); ti->res0e = -1; ti->version = get_attrv(type->attrs, ATTR_VERSION); ti->res16 = 0xfffe0000; @@ -454,6 +500,110 @@ static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, i ti->misc.unknown2 = 0x02; ti->misc.typekind = kind; ti->res1e = -1; + + ti->member_offset = sizeof(*ti); + + if (hrefmap->href_count) + { + char name[64]; + int i, hrefinfo_size; + + hrefinfo_size = sizeof(struct sltg_hrefinfo); + + for (i = 0; i < hrefmap->href_count; i++) + { + sprintf(name, "*\Rffff*#%x", hrefmap->href[i]); + hrefinfo_size += 8 + 2 + strlen(name); + } + + ti->href_offset = ti->member_offset; + ti->member_offset += hrefinfo_size; + } +} + +static void init_sltg_tail(struct sltg_tail *tail) +{ + tail->cFuncs = 0; + tail->cVars = 0; + tail->cImplTypes = 0; + tail->res06 = 0; + tail->funcs_off = -1; + tail->vars_off = 0; + tail->impls_off = -1; + tail->funcs_bytes = -1; + tail->vars_bytes = 0; + tail->impls_bytes = -1; + tail->tdescalias_vt = -1; + tail->res16 = -1; + tail->res18 = 0; + tail->res1a = 0; + tail->simple_alias = 0; + tail->res1e = 0; + tail->cbSizeInstance = 0; + tail->cbAlignment = 4; + tail->res24 = -1; + tail->res26 = -1; + tail->cbSizeVft = 0; + tail->res2a = -1; + tail->res2c = -1; + tail->res2e = -1; + tail->res30 = -1; + tail->res32 = 0; + tail->type_bytes = 0; +} + +static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap) +{ + struct sltg_hrefinfo hrefinfo; + char name[64]; + int i; + + if (!hrefmap->href_count) return; + + hrefinfo.magic = 0xdf; + hrefinfo.res01 = 0; + hrefinfo.res02 = -1; + hrefinfo.res06 = -1; + hrefinfo.res0a = -1; + hrefinfo.res0e = -1; + hrefinfo.res12 = -1; + hrefinfo.res16 = -1; + hrefinfo.res1a = -1; + hrefinfo.res1e = -1; + hrefinfo.res22 = -1; + hrefinfo.res26 = -1; + hrefinfo.res2a = -1; + hrefinfo.res2e = -1; + hrefinfo.res32 = -1; + hrefinfo.res36 = -1; + hrefinfo.res3a = -1; + hrefinfo.res3e = -1; + hrefinfo.res42 = -1; + hrefinfo.number = hrefmap->href_count * 8; + hrefinfo.res50 = -1; + hrefinfo.res52 = 1; + hrefinfo.res53 = 0; + hrefinfo.resxx = 0xdf; + + append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50)); + + for (i = 0; i < hrefmap->href_count; i++) + append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8); + + append_data(data, &hrefinfo.res50, 7); + + for (i = 0; i < hrefmap->href_count; i++) + { + short len; + + sprintf(name, "*\Rffff*#%x", hrefmap->href[i]); + len = strlen(name); + + append_data(data, &len, sizeof(len)); + append_data(data, name, len); + } + + append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx)); }
static void dump_var_desc(const char *data, int size) @@ -519,6 +669,9 @@ static int get_element_size(type_t *type) case VT_VARIANT: return pointer_size == 8 ? 24 : 16;
+ case VT_USERDEFINED: + return 0; + default: error("get_element_size: unrecognized vt %d\n", vt); break; @@ -527,9 +680,41 @@ static int get_element_size(type_t *type) return 0; }
-static short write_var_desc(struct sltg_data *data, type_t *type, short flags, short base_offset, int *size_instance) +static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href) +{ + int i, href = -1; + + for (i = 0; i < hrefmap->href_count; i++) + { + if (hrefmap->href[i] == typelib_href) + { + href = i; + break; + } + } + + if (href == -1) + { + href = hrefmap->href_count; + + if (hrefmap->href) + hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1)); + else + hrefmap->href = xmalloc(sizeof(*hrefmap->href)); + + hrefmap->href[hrefmap->href_count] = typelib_href; + hrefmap->href_count++; + } + + chat("typelib href %d mapped to local href %d\n", typelib_href, href); + + return href << 2; +} + +static short write_var_desc(struct sltg_data *data, type_t *type, short flags, short base_offset, + int *size_instance, struct sltg_hrefmap *hrefmap) { - short vt, desc_offset; + short vt, vt_flags, desc_offset;
chat("write_var_desc: type %p, type->name %s\n", type, type->name ? type->name : "NULL"); @@ -619,27 +804,47 @@ static short write_var_desc(struct sltg_data *data, type_t *type, short flags, s chat("write_var_desc: vt VT_PTR | 0x0400\n"); vt = VT_PTR | 0x0400; append_data(data, &vt, sizeof(vt)); - write_var_desc(data, ref, 0, base_offset, size_instance); + write_var_desc(data, ref, 0, base_offset, size_instance, hrefmap); } else - write_var_desc(data, ref, 0x0e00, base_offset, size_instance); + write_var_desc(data, ref, 0x0e00, base_offset, size_instance, hrefmap); return desc_offset; }
chat("write_var_desc: vt %d, flags %04x\n", vt, flags);
+ vt_flags = vt | flags; + append_data(data, &vt_flags, sizeof(vt_flags)); + + if (vt == VT_USERDEFINED) + { + short href; + + while (type->typelib_idx < 0 && type_is_alias(type)) + type = type_alias_get_aliasee_type(type); + + chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n", + type, type->name, type_get_type(type), type->typelib_idx); + + if (type->typelib_idx == -1) + error("write_var_desc: trying to ref not added type\n"); + + href = local_href(hrefmap, type->typelib_idx); + chat("write_var_desc: VT_USERDEFINED, local href %d\n", href); + + append_data(data, &href, sizeof(href)); + } + if (size_instance) *size_instance += get_element_size(type);
- vt |= flags; - append_data(data, &vt, sizeof(vt)); - return desc_offset; }
static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) { struct sltg_data data, *var_data = NULL; + struct sltg_hrefmap hrefmap; const char *index_name; struct sltg_typeinfo_header ti; struct sltg_member_header member; @@ -647,15 +852,17 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) int member_offset, var_count = 0, var_data_size = 0, size_instance = 0; short *type_desc_offset = NULL;
- chat("add_structure_typeinfo: %s\n", type->name); + chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name); + + type->typelib_idx = typelib->block_count; + + hrefmap.href_count = 0; + hrefmap.href = NULL;
init_sltg_data(&data);
index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
- init_typeinfo(&ti, type, TKIND_RECORD); - append_data(&data, &ti, sizeof(ti)); - if (type_struct_get_fields(type)) { int i = 0; @@ -676,7 +883,7 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) init_sltg_data(&var_data[i]);
base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable); - type_desc_offset[i] = write_var_desc(&var_data[i], var->declspec.type, 0, base_offset, &size_instance); + type_desc_offset[i] = write_var_desc(&var_data[i], var->declspec.type, 0, base_offset, &size_instance, &hrefmap); dump_var_desc(var_data[i].data, var_data[i].size);
if (var_data[i].size > sizeof(short)) @@ -685,6 +892,11 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) } }
+ init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap); + append_data(&data, &ti, sizeof(ti)); + + write_hrefmap(&data, &hrefmap); + member_offset = data.size;
member.res00 = 0x0001; @@ -736,32 +948,11 @@ static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) } }
- tail.cFuncs = 0; + init_sltg_tail(&tail); + tail.cVars = var_count; - tail.cImplTypes = 0; - tail.res06 = 0; - tail.funcs_off = -1; - tail.vars_off = 0; - tail.impls_off = -1; - tail.funcs_bytes = -1; tail.vars_bytes = var_data_size; - tail.impls_bytes = -1; - tail.tdescalias_vt = -1; - tail.res16 = -1; - tail.res18 = 0; - tail.res1a = 0; - tail.simple_alias = 0; - tail.res1e = 0; tail.cbSizeInstance = size_instance; - tail.cbAlignment = 4; - tail.res24 = -1; - tail.res26 = -1; - tail.cbSizeVft = 0; - tail.res2a = -1; - tail.res2c = -1; - tail.res2e = -1; - tail.res30 = -1; - tail.res32 = 0; tail.type_bytes = data.size - member_offset - sizeof(member); append_data(&data, &tail, sizeof(tail));