[PATCH v3 0/5] MR5397: widl: Add support for structures.
-- v3: widl: Add support for VT_USERDEFINED to SLTG typelib generator. widl: Properly align name table entries. widl: Add support for structures. widl: Add more traces. widl: Use generic 'struct sltg_data' for collecting data. https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
From: Dmitry Timoshkov <dmitry(a)baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru> --- tools/widl/write_sltg.c | 53 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index 0c8913d2ecc..880bfcfbe5c 100644 --- a/tools/widl/write_sltg.c +++ b/tools/widl/write_sltg.c @@ -39,16 +39,10 @@ static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } }; -struct sltg_index +struct sltg_data { int size, allocated; - char *names; -}; - -struct sltg_name_table -{ - int size, allocated; - char *names; + char *data; }; struct sltg_library @@ -74,8 +68,8 @@ struct sltg_block struct sltg_typelib { typelib_t *typelib; - struct sltg_index index; - struct sltg_name_table name_table; + struct sltg_data index; + struct sltg_data name_table; struct sltg_library library; struct sltg_block *blocks; int block_count; @@ -83,7 +77,14 @@ struct sltg_typelib short typeinfo_count; }; -static int add_index(struct sltg_index *index, const char *name) +static void init_sltg_data(struct sltg_data *data) +{ + data->size = 0; + data->allocated = 0; + data->data = NULL; +} + +static int add_index(struct sltg_data *index, const char *name) { int name_offset = index->size; int new_size = index->size + strlen(name) + 1; @@ -91,27 +92,25 @@ static int add_index(struct sltg_index *index, const char *name) if (new_size > index->allocated) { index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size; - index->names = xrealloc(index->names, index->allocated); + index->data = xrealloc(index->data, index->allocated); } - strcpy(index->names + index->size, name); + strcpy(index->data + index->size, name); index->size = new_size; return name_offset; } -static void init_index(struct sltg_index *index) +static void init_index(struct sltg_data *index) { static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 }; - index->size = 0; - index->allocated = 0; - index->names = NULL; + init_sltg_data(index); add_index(index, compobj); } -static int add_name(struct sltg_name_table *name_table, const char *name) +static int add_name(struct sltg_data *name_table, const char *name) { int name_offset = name_table->size; int new_size = name_table->size + strlen(name) + 1 + 8; @@ -121,22 +120,20 @@ static int add_name(struct sltg_name_table *name_table, const char *name) if (new_size > name_table->allocated) { name_table->allocated = name_table->allocated ? max(name_table->allocated * 2, new_size) : new_size; - name_table->names = xrealloc(name_table->names, name_table->allocated); + name_table->data = xrealloc(name_table->data, name_table->allocated); } - memset(name_table->names + name_table->size, 0xff, 8); - strcpy(name_table->names + name_table->size + 8, name); + memset(name_table->data + name_table->size, 0xff, 8); + strcpy(name_table->data + name_table->size + 8, name); name_table->size = new_size; - name_table->names[name_table->size - 1] = 0; /* clear alignment */ + name_table->data[name_table->size - 1] = 0; /* clear alignment */ return name_offset; } -static void init_name_table(struct sltg_name_table *name_table) +static void init_name_table(struct sltg_data *name_table) { - name_table->size = 0; - name_table->allocated = 0; - name_table->names = NULL; + init_sltg_data(name_table); } static void init_library(struct sltg_typelib *sltg) @@ -418,7 +415,7 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star entry.next = 0; put_data(&entry, sizeof(entry)); - put_data(sltg->index.names, sltg->index.size); + put_data(sltg->index.data, sltg->index.size); memset(pad, 0, 9); put_data(pad, 9); @@ -458,7 +455,7 @@ static void sltg_write_nametable(struct sltg_typelib *typelib) memset(pad, 0xff, 0x200); put_data(pad, 0x200); put_data(&typelib->name_table.size, sizeof(typelib->name_table.size)); - put_data(typelib->name_table.names, typelib->name_table.size); + put_data(typelib->name_table.data, typelib->name_table.size); } static void sltg_write_remainder(void) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
From: Dmitry Timoshkov <dmitry(a)baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru> --- tools/widl/write_sltg.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index 880bfcfbe5c..be25fdc5567 100644 --- a/tools/widl/write_sltg.c +++ b/tools/widl/write_sltg.c @@ -89,6 +89,8 @@ static int add_index(struct sltg_data *index, const char *name) int name_offset = index->size; int new_size = index->size + strlen(name) + 1; + chat("add_index: name_offset %d, \"%s\"\n", name_offset, name); + if (new_size > index->allocated) { index->allocated = index->allocated ? max(index->allocated * 2, new_size) : new_size; @@ -115,6 +117,8 @@ static int add_name(struct sltg_data *name_table, const char *name) int name_offset = name_table->size; int new_size = name_table->size + strlen(name) + 1 + 8; + chat("add_name: %s\n", name); + new_size = (new_size + 1) & ~1; /* align */ if (new_size > name_table->allocated) @@ -195,6 +199,8 @@ static void init_library(struct sltg_typelib *sltg) static void add_block(struct sltg_typelib *sltg, void *data, int length, const char *name) { + chat("add_block: %p,%d,\"%s\"\n", data, length, name); + sltg->blocks = xrealloc(sltg->blocks, sizeof(sltg->blocks[0]) * (sltg->block_count + 1)); sltg->blocks[sltg->block_count].length = length; sltg->blocks[sltg->block_count].data = data; @@ -404,6 +410,8 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star entry.length = sltg->blocks[i].length; entry.index_string = sltg->blocks[i].index_string; entry.next = header.first_blk + i; + chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", + i, entry.length, entry.index_string, entry.next); put_data(&entry, sizeof(entry)); } @@ -413,8 +421,11 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star 12 /* name table header */ + 0x200 /* name table hash */ + sltg->name_table.size; entry.index_string = sltg->blocks[sltg->block_count - 1].index_string; entry.next = 0; + chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n", + i, entry.length, entry.index_string, entry.next); put_data(&entry, sizeof(entry)); + chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size); put_data(sltg->index.data, sltg->index.size); memset(pad, 0, 9); put_data(pad, 9); @@ -427,9 +438,12 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star } /* library block */ + chat("library_block_start = %#x\n", (int)output_buffer_pos); *library_block_start = output_buffer_pos; + chat("sltg_write_header: writing library block %d: %d bytes\n", i, sltg->blocks[i].length); put_data(sltg->blocks[sltg->block_count - 1].data, sltg->blocks[sltg->block_count - 1].length); + chat("sltg_write_header: writing pad 0x40 bytes\n"); memset(pad, 0xff, 0x40); put_data(pad, 0x40); } @@ -443,6 +457,8 @@ static void sltg_write_helpstrings(struct sltg_typelib *typelib) { static const char dummy[6]; + chat("sltg_write_helpstrings: writing dummy 6 bytes\n"); + put_data(dummy, sizeof(dummy)); } @@ -451,6 +467,8 @@ static void sltg_write_nametable(struct sltg_typelib *typelib) static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff }; char pad[0x200]; + chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size); + put_data(dummy, sizeof(dummy)); memset(pad, 0xff, 0x200); put_data(pad, 0x200); @@ -490,11 +508,13 @@ static void save_all_changes(struct sltg_typelib *typelib) sltg_write_typeinfo(typelib); name_table_offset = (int *)(output_buffer + output_buffer_pos); + chat("name_table_offset = %#x\n", (int)output_buffer_pos); put_data(&library_block_start, sizeof(library_block_start)); sltg_write_helpstrings(typelib); *name_table_offset = output_buffer_pos - library_block_start; + chat("*name_table_offset = %#x\n", *name_table_offset); sltg_write_nametable(typelib); sltg_write_remainder(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
From: Dmitry Timoshkov <dmitry(a)baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru> --- tools/widl/write_sltg.c | 521 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 517 insertions(+), 4 deletions(-) diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index be25fdc5567..c924eff89ed 100644 --- a/tools/widl/write_sltg.c +++ b/tools/widl/write_sltg.c @@ -1,7 +1,7 @@ /* * Typelib (SLTG) generation * - * Copyright 2015 Dmitry Timoshkov + * Copyright 2015,2016 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -75,8 +75,84 @@ struct sltg_typelib int block_count; int first_block; short typeinfo_count; + int typeinfo_size; + struct sltg_block *typeinfo; }; +#include "pshpack1.h" +struct sltg_typeinfo_header +{ + short magic; + int href_offset; + int res06; + int member_offset; + int res0e; + int version; + int res16; + struct + { + unsigned unknown1 : 3; + unsigned flags : 13; + unsigned unknown2 : 8; + unsigned typekind : 8; + } misc; + int res1e; +}; + +struct sltg_member_header +{ + short res00; + short res02; + char res04; + int extra; +}; + +struct sltg_variable +{ + char magic; /* 0x0a */ + char flags; + short next; + short name; + short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */ + short type; /* if flags & 0x02 this is the type, else offset to type */ + int memid; + short helpcontext; + short helpstring; + short varflags; /* only present if magic & 0x20 */ +}; + +struct sltg_tail +{ + short cFuncs; + short cVars; + short cImplTypes; + short res06; /* always 0000 */ + short funcs_off; /* offset to functions (starting from the member header) */ + short vars_off; /* offset to vars (starting from the member header) */ + short impls_off; /* offset to implemented types (starting from the member header) */ + short funcs_bytes; /* bytes used by function data */ + short vars_bytes; /* bytes used by var data */ + short impls_bytes; /* bytes used by implemented type data */ + short tdescalias_vt; /* for TKIND_ALIAS */ + short res16; /* always ffff */ + short res18; /* always 0000 */ + short res1a; /* always 0000 */ + short simple_alias; /* tdescalias_vt is a vt rather than an offset? */ + short res1e; /* always 0000 */ + short cbSizeInstance; + short cbAlignment; + short res24; /* always ffff */ + short res26; /* always ffff */ + short cbSizeVft; + short res2a; /* always ffff */ + short res2c; /* always ffff */ + short res2e; /* always ffff */ + short res30; /* always ffff */ + short res32; /* unknown */ + short type_bytes; /* bytes used by type descriptions */ +}; +#include "poppack.h" + static void init_sltg_data(struct sltg_data *data) { data->size = 0; @@ -254,6 +330,52 @@ static void add_library_block(struct sltg_typelib *typelib) add_block(typelib, block, size, "dir"); } +static const char *new_index_name(void) +{ + static char name[11] = "AAAAAAAAAA"; + static int pos = 0; + char *new_name; + + if (name[pos] == 'Z') + { + pos++; + if (pos > 9) + error("too many index names\n"); + } + + name[pos]++; + + new_name = xmalloc(sizeof(name)); + strcpy(new_name, name); + return new_name; +} + +static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int length, const char *name) +{ + chat("sltg_add_typeinfo: %p,%d,%s\n", data, length, name); + + sltg->typeinfo = xrealloc(sltg->typeinfo, sizeof(sltg->typeinfo[0]) * (sltg->typeinfo_count + 1)); + sltg->typeinfo[sltg->typeinfo_count].length = length; + sltg->typeinfo[sltg->typeinfo_count].data = data; + sltg->typeinfo[sltg->typeinfo_count].index_string = 0; + sltg->typeinfo_count++; + sltg->typeinfo_size += length; +} + +static void append_data(struct sltg_data *block, const void *data, int size) +{ + int new_size = block->size + size; + + if (new_size > block->allocated) + { + block->allocated = max(block->allocated * 2, new_size); + block->data = xrealloc(block->data, block->allocated); + } + + memcpy(block->data + block->size, data, size); + block->size = new_size; +} + static void add_typedef_typeinfo(struct sltg_typelib *typelib, type_t *type) { error("add_typedef_typeinfo: %s not implemented\n", type->name); @@ -269,9 +391,387 @@ static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type) error("add_interface_typeinfo: %s not implemented\n", type->name); } +static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, short kind) +{ + struct sltg_data block; + const char *index_name, *other_name; + short val; + void *p; + int helpcontext = 0; + GUID guid = { 0 }; + const expr_t *expr; + + index_name = new_index_name(); + other_name = new_index_name(); + + expr = get_attrp(type->attrs, ATTR_HELPCONTEXT); + if (expr) helpcontext = expr->cval; + + p = get_attrp(type->attrs, ATTR_UUID); + if (p) guid = *(GUID *)p; + + init_sltg_data(&block); + + val = strlen(index_name); + append_data(&block, &val, sizeof(val)); + append_data(&block, index_name, val); + val = strlen(other_name); + append_data(&block, &val, sizeof(val)); + append_data(&block, other_name, val); + val = -1; /* res1a */ + append_data(&block, &val, sizeof(val)); + val = add_name(&typelib->name_table, type->name); /* name offset */ + append_data(&block, &val, sizeof(val)); + val = 0; /* FIXME: helpstring */ + append_data(&block, &val, sizeof(val)); + val = -1; /* res20 */ + append_data(&block, &val, sizeof(val)); + append_data(&block, &helpcontext, sizeof(helpcontext)); + val = -1; /* res26 */ + append_data(&block, &val, sizeof(val)); + append_data(&block, &guid, sizeof(guid)); + append_data(&block, &kind, sizeof(kind)); + + sltg_add_typeinfo(typelib, block.data, block.size, index_name); + + return index_name; +} + +static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind) +{ + 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; + ti->misc.unknown1 = 0x02; + ti->misc.flags = 0; /* FIXME */ + ti->misc.unknown2 = 0x02; + ti->misc.typekind = kind; + ti->res1e = -1; +} + +static void dump_var_desc(const char *data, int size) +{ + const unsigned char *p = (const unsigned char *)data; + int i; + + if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return; + + chat("dump_var_desc: size %d bytes\n", size); + + for (i = 0; i < size; i++) + fprintf(stderr, " %02x", *p++); + + fprintf(stderr, "\n"); +} + +static int get_element_size(type_t *type) +{ + int vt = get_type_vt(type); + + switch (vt) + { + case VT_I1: + case VT_UI1: + return 1; + + case VT_UI2: + case VT_I2: + case VT_BOOL: + return 2; + + case VT_INT: + case VT_UINT: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_ERROR: + case VT_HRESULT: + return 4; + + case VT_R8: + case VT_I8: + case VT_UI8: + case VT_CY: + case VT_DATE: + return 8; + + case VT_DECIMAL: + return 16; + + case VT_PTR: + case VT_UNKNOWN: + case VT_DISPATCH: + case VT_BSTR: + case VT_LPSTR: + case VT_LPWSTR: + return 4; + + case VT_VOID: + return 0; + + case VT_VARIANT: + return 16; + + default: + error("get_element_size: unrecognized vt %d\n", vt); + break; + } + + return 0; +} + +static short write_var_desc(struct sltg_data *data, type_t *type, short flags, short base_offset, int *size_instance) +{ + short vt, desc_offset; + + chat("write_var_desc: type %p, type->name %s\n", + type, type->name ? type->name : "NULL"); + + if (is_array(type) && !type_array_is_decl_as_ptr(type)) + { + int num_dims, elements, array_start, size, array_size; + type_t *atype; + struct + { + short cDims; + short fFeatures; + int cbElements; + int cLocks; + int pvData; + int bound[2]; + } *array; + int *bound; + short vt_off[2]; + + elements = 1; + num_dims = 0; + + atype = type; + + while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) + { + num_dims++; + elements *= type_array_get_dim(atype); + + atype = type_array_get_element_type(atype); + } + + chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements); + + array_start = data->size; + + size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */; + array = xmalloc(size); + + array->cDims = num_dims; + array->fFeatures = 0x0004; /* FADF_EMBEDDED */ + array->cbElements = get_element_size(atype); + array->cLocks = 0; + array->pvData = 0; + + bound = array->bound; + + array_size = array->cbElements; + atype = type; + + while (is_array(atype) && !type_array_is_decl_as_ptr(atype)) + { + bound[0] = type_array_get_dim(atype); + array_size *= bound[0]; + bound[1] = 0; + bound += 2; + + atype = type_array_get_element_type(atype); + } + + *size_instance += array_size; + size_instance = NULL; /* don't account for element size */ + + append_data(data, array, size); + + desc_offset = data->size; + + vt_off[0] = VT_CARRAY; + vt_off[1] = array_start + base_offset; + append_data(data, vt_off, sizeof(vt_off)); + + /* fall through to write array element description */ + type = atype; + } + else + desc_offset = data->size; + + vt = get_type_vt(type); + + if (vt == VT_PTR) + { + type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type); + + if (is_ptr(ref)) + { + 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); + } + else + write_var_desc(data, ref, 0x0e00, base_offset, size_instance); + return desc_offset; + } + + chat("write_var_desc: vt %d, flags %04x\n", vt, flags); + + if (size_instance) + *size_instance += get_element_size(type); + + vt |= flags; + append_data(data, &vt, sizeof(vt)); + + return desc_offset; +} + +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 add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type) { - error("add_structure_typeinfo: %s not implemented\n", type->name); + struct sltg_data data, *var_data = NULL; + const char *index_name; + struct sltg_typeinfo_header ti; + struct sltg_member_header member; + struct sltg_tail tail; + 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); + + 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; + var_t *var; + + var_count = list_count(type_struct_get_fields(type)); + + var_data = xmalloc(var_count * sizeof(*var_data)); + type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset)); + + LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) + { + short base_offset; + + chat("add_structure_typeinfo: var %p, name %s, type %p\n", + var, var->name, var->declspec.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); + dump_var_desc(var_data[i].data, var_data[i].size); + + if (var_data[i].size > sizeof(short)) + var_data_size += var_data[i].size; + i++; + } + } + + member_offset = data.size; + + member.res00 = 0x0001; + member.res02 = 0xffff; + member.res04 = 0x01; + member.extra = var_data_size + var_count * sizeof(struct sltg_variable); + append_data(&data, &member, sizeof(member)); + + var_data_size = 0; + + if (type_struct_get_fields(type)) + { + int i = 0; + short next = member_offset; + var_t *var; + + LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry) + { + struct sltg_variable variable; + + next += sizeof(variable); + + variable.magic = 0x2a; /* always write flags to simplify calculations */ + variable.name = add_name(&typelib->name_table, var->name); + variable.byte_offs = 0; + if (var_data[i].size > sizeof(short)) + { + variable.flags = 0; + var_data_size = next - member_offset + type_desc_offset[i]; + variable.type = var_data_size; + next += var_data[i].size; + } + else + { + variable.flags = 0x02; + variable.type = *(short *)var_data[i].data; + } + variable.next = i < var_count - 1 ? next - member_offset : -1; + variable.memid = 0x40000000 + i; + variable.helpcontext = -2; /* 0xfffe */ + variable.helpstring = -1; + variable.varflags = 0; + + append_data(&data, &variable, sizeof(variable)); + if (var_data[i].size > sizeof(short)) + append_data(&data, var_data[i].data, var_data[i].size); + + i++; + } + } + + init_sltg_tail(&tail); + tail.cVars = var_count; + tail.vars_bytes = var_data_size; + tail.cbSizeInstance = size_instance; + tail.type_bytes = data.size - member_offset - sizeof(member); + append_data(&data, &tail, sizeof(tail)); + + add_block(typelib, data.data, data.size, index_name); } static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type) @@ -409,7 +909,7 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star { entry.length = sltg->blocks[i].length; entry.index_string = sltg->blocks[i].index_string; - entry.next = header.first_blk + i; + entry.next = header.first_blk + i + 1; /* point to next block */ chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n", i, entry.length, entry.index_string, entry.next); put_data(&entry, sizeof(entry)); @@ -417,7 +917,7 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star /* library block length includes helpstrings and name table */ entry.length = sltg->blocks[sltg->block_count - 1].length + 0x40 /* pad after library block */ + - sizeof(sltg->typeinfo_count) + 4 /* library block offset */ + 6 /* dummy help strings */ + + sizeof(sltg->typeinfo_count) + sltg->typeinfo_size + 4 /* library block offset */ + 6 /* dummy help strings */ + 12 /* name table header */ + 0x200 /* name table hash */ + sltg->name_table.size; entry.index_string = sltg->blocks[sltg->block_count - 1].index_string; entry.next = 0; @@ -450,7 +950,15 @@ static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_star static void sltg_write_typeinfo(struct sltg_typelib *typelib) { + short i; + put_data(&typelib->typeinfo_count, sizeof(typelib->typeinfo_count)); + + for (i = 0; i < typelib->typeinfo_count; i++) + { + chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, typelib->typeinfo[i].length); + put_data(typelib->typeinfo[i].data, typelib->typeinfo[i].length); + } } static void sltg_write_helpstrings(struct sltg_typelib *typelib) @@ -538,8 +1046,13 @@ int create_sltg_typelib(typelib_t *typelib) struct sltg_typelib sltg; const statement_t *stmt; + if (pointer_size != 4) + error("Only 32-bit platform is supported\n"); + sltg.typelib = typelib; sltg.typeinfo_count = 0; + sltg.typeinfo_size = 0; + sltg.typeinfo = NULL; sltg.blocks = NULL; sltg.block_count = 0; sltg.first_block = 1; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
From: Dmitry Timoshkov <dmitry(a)baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru> --- tools/widl/write_sltg.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index c924eff89ed..1ab853fb945 100644 --- a/tools/widl/write_sltg.c +++ b/tools/widl/write_sltg.c @@ -192,10 +192,15 @@ static int add_name(struct sltg_data *name_table, const char *name) { int name_offset = name_table->size; int new_size = name_table->size + strlen(name) + 1 + 8; + int aligned_size; chat("add_name: %s\n", name); - new_size = (new_size + 1) & ~1; /* align */ + aligned_size = (new_size + 0x1f) & ~0x1f; + if (aligned_size - new_size < 4) + new_size = aligned_size; + else + new_size = (new_size + 1) & ~1; if (new_size > name_table->allocated) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
From: Dmitry Timoshkov <dmitry(a)baikal.ru> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru> --- tools/widl/write_sltg.c | 174 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 13 deletions(-) diff --git a/tools/widl/write_sltg.c b/tools/widl/write_sltg.c index 1ab853fb945..ac4db609919 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,30 @@ struct sltg_tail short res32; /* unknown */ short type_bytes; /* bytes used by type descriptions */ }; + +struct sltg_hrefinfo +{ + char magic; /* 0xdf */ + char res01; /* 0x00 */ + char res02[0x42]; /* 0xff... */ + 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) @@ -442,7 +472,8 @@ 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, short kind, + const struct sltg_hrefmap *hrefmap) { ti->magic = 0x0501; ti->href_offset = -1; @@ -456,6 +487,61 @@ 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; + + 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 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; + memset(hrefinfo.res02, 0xff, sizeof(hrefinfo.res02)); + 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) @@ -521,6 +607,9 @@ static int get_element_size(type_t *type) case VT_VARIANT: return 16; + case VT_USERDEFINED: + return 0; + default: error("get_element_size: unrecognized vt %d\n", vt); break; @@ -529,9 +618,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"); @@ -621,21 +742,40 @@ 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; } @@ -673,6 +813,7 @@ static void init_sltg_tail(struct sltg_tail *tail) 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; @@ -680,15 +821,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; @@ -709,7 +852,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)) @@ -718,6 +861,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; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
On Wed Mar 27 12:00:59 2024 +0000, Huw Davies wrote:
There are refactoring changes in both of those commits that would actually be trivial to split out. _Reviewing_ larger commits is the real struggle. Does new version of the patches look better?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66270
On Wed Mar 27 18:50:48 2024 +0000, Dmitry Timoshkov wrote:
I collected a bunch of different SLTG typelibs for investigation (from Windows 3.1, Visual Basic, some applications written in VB), and it seems that names depend on used midl version: sometimes it's AAAAAAAAAA based, sometimes 0000000000. So I decided to intentionally differ in name generation, after all what we need is just distinct names. Ah, fair enough. I figured there might be a reason it'd need to be alphanumeric.
The second part does look unintended though; don't we want Z0000... to be followed by 01000...? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66309
On Wed Mar 27 18:50:48 2024 +0000, Elizabeth Figura wrote:
Ah, fair enough. I figured there might be a reason it'd need to be alphanumeric. The second part does look unintended though; don't we want Z0000... to be followed by 01000...? To be fair I guess it'd only matter if we exceed 420 names, but that's not *that* large of a limit. Plus, if all we care about is uniqueness, we could do something much easier and just have e.g. sprintf(name, "%10u", counter++);
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66310
On Wed Mar 27 10:12:48 2024 +0000, Dmitry Timoshkov wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/5397/diffs?diff_id=107383&start_sha=8c08486fcff3381186fb470cb6a8f12db2705b09#1c5042b1a3d4d3dc361922dd9071991f8ac136f7_181_165) Oh you're right, I was explicitly looking for the same struct in oleaut32 and missed it, sorry :-(
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66311
On Wed Mar 27 18:50:48 2024 +0000, Elizabeth Figura wrote:
To be fair I guess it'd only matter if we exceed 420 names, but that's not *that* large of a limit. Plus, if all we care about is uniqueness, we could do something much easier and just have e.g. sprintf(name, "%10u", counter++); I followed your earlier comment and in a newer version of the patches used 'AAAAAAAAAA'. I think that we could consider changing the naming scheme once we hit a real problem.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66313
Is there anything else that could be improved in the patches? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66504
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
The Mac build failure looks unrelated. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397#note_66597
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5397
participants (4)
-
Dmitry Timoshkov -
Dmitry Timoshkov (@dmitry) -
Elizabeth Figura (@zfigura) -
Huw Davies (@huw)