📄 typelib2.c
字号:
length = WideCharToMultiByte(CP_ACP, 0, string, strlenW(string), converted_string+2, 0x102, NULL, NULL);
converted_string[0] = length & 0xff;
converted_string[1] = (length >> 8) & 0xff;
for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57;
*result = converted_string;
return (length + 5) & ~3;
}
/****************************************************************************
* ctl2_alloc_segment
*
* Allocates memory from a segment in a type library.
*
* RETURNS
*
* Success: The offset within the segment of the new data area.
* Failure: -1 (this is invariably an out of memory condition).
*
* BUGS
*
* Does not (yet) handle the case where the allocated segment memory needs to grow.
*/
static int ctl2_alloc_segment(
ICreateTypeLib2Impl *This, /* [I] The type library in which to allocate. */
enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */
int size, /* [I] The amount to allocate. */
int block_size) /* [I] Initial allocation block size, or 0 for default. */
{
int offset;
if(!This->typelib_segment_data[segment]) {
if (!block_size) block_size = 0x2000;
This->typelib_segment_block_length[segment] = block_size;
This->typelib_segment_data[segment] = HeapAlloc(GetProcessHeap(), 0, block_size);
if (!This->typelib_segment_data[segment]) return -1;
memset(This->typelib_segment_data[segment], 0x57, block_size);
}
while ((This->typelib_segdir[segment].length + size) > This->typelib_segment_block_length[segment]) {
char *block;
block_size = This->typelib_segment_block_length[segment];
block = HeapReAlloc(GetProcessHeap(), 0, This->typelib_segment_data[segment], block_size << 1);
if (!block) return -1;
if (segment == MSFT_SEG_TYPEINFO) {
/* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */
ICreateTypeInfo2Impl *typeinfo;
for (typeinfo = This->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) {
typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - This->typelib_segment_data[segment]];
}
}
memset(block + block_size, 0x57, block_size);
This->typelib_segment_block_length[segment] = block_size << 1;
This->typelib_segment_data[segment] = block;
}
offset = This->typelib_segdir[segment].length;
This->typelib_segdir[segment].length += size;
return offset;
}
/****************************************************************************
* ctl2_alloc_typeinfo
*
* Allocates and initializes a typeinfo structure in a type library.
*
* RETURNS
*
* Success: The offset of the new typeinfo.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_typeinfo(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
int nameoffset) /* [I] The offset of the name for this typeinfo. */
{
int offset;
MSFT_TypeInfoBase *typeinfo;
offset = ctl2_alloc_segment(This, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0);
if (offset == -1) return -1;
This->typelib_typeinfo_offsets[This->typelib_header.nrtypeinfos++] = offset;
typeinfo = (void *)(This->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset);
typeinfo->typekind = (This->typelib_header.nrtypeinfos - 1) << 16;
typeinfo->memoffset = -1; /* should be EOF if no elements */
typeinfo->res2 = 0;
typeinfo->res3 = -1;
typeinfo->res4 = 3;
typeinfo->res5 = 0;
typeinfo->cElement = 0;
typeinfo->res7 = 0;
typeinfo->res8 = 0;
typeinfo->res9 = 0;
typeinfo->resA = 0;
typeinfo->posguid = -1;
typeinfo->flags = 0;
typeinfo->NameOffset = nameoffset;
typeinfo->version = 0;
typeinfo->docstringoffs = -1;
typeinfo->helpstringcontext = 0;
typeinfo->helpcontext = 0;
typeinfo->oCustData = -1;
typeinfo->cbSizeVft = 0;
typeinfo->cImplTypes = 0;
typeinfo->size = 0;
typeinfo->datatype1 = -1;
typeinfo->datatype2 = 0;
typeinfo->res18 = 0;
typeinfo->res19 = -1;
return offset;
}
/****************************************************************************
* ctl2_alloc_guid
*
* Allocates and initializes a GUID structure in a type library. Also updates
* the GUID hash table as needed.
*
* RETURNS
*
* Success: The offset of the new GUID.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_guid(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
MSFT_GuidEntry *guid) /* [I] The GUID to store. */
{
int offset;
MSFT_GuidEntry *guid_space;
int hash_key;
hash_key = ctl2_hash_guid(&guid->guid);
offset = ctl2_find_guid(This, hash_key, &guid->guid);
if (offset != -1) return offset;
offset = ctl2_alloc_segment(This, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0);
if (offset == -1) return -1;
guid_space = (void *)(This->typelib_segment_data[MSFT_SEG_GUID] + offset);
*guid_space = *guid;
guid_space->next_hash = This->typelib_guidhash_segment[hash_key];
This->typelib_guidhash_segment[hash_key] = offset;
return offset;
}
/****************************************************************************
* ctl2_alloc_name
*
* Allocates and initializes a name within a type library. Also updates the
* name hash table as needed.
*
* RETURNS
*
* Success: The offset within the segment of the new name.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_name(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
const WCHAR *name) /* [I] The name to store. */
{
int length;
int offset;
MSFT_NameIntro *name_space;
char *encoded_name;
length = ctl2_encode_name(This, name, &encoded_name);
offset = ctl2_find_name(This, encoded_name);
if (offset != -1) return offset;
offset = ctl2_alloc_segment(This, MSFT_SEG_NAME, length + 8, 0);
if (offset == -1) return -1;
name_space = (void *)(This->typelib_segment_data[MSFT_SEG_NAME] + offset);
name_space->hreftype = -1;
name_space->next_hash = -1;
memcpy(&name_space->namelen, encoded_name, length);
if (This->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1)
name_space->next_hash = This->typelib_namehash_segment[encoded_name[2] & 0x7f];
This->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset;
This->typelib_header.nametablecount += 1;
This->typelib_header.nametablechars += *encoded_name;
return offset;
}
/****************************************************************************
* ctl2_alloc_string
*
* Allocates and initializes a string in a type library.
*
* RETURNS
*
* Success: The offset within the segment of the new string.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_string(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
const WCHAR *string) /* [I] The string to store. */
{
int length;
int offset;
char *string_space;
char *encoded_string;
length = ctl2_encode_string(This, string, &encoded_string);
for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_STRING].length;
offset += ((((This->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff)
| (This->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) {
if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset;
}
offset = ctl2_alloc_segment(This, MSFT_SEG_STRING, length, 0);
if (offset == -1) return -1;
string_space = This->typelib_segment_data[MSFT_SEG_STRING] + offset;
memcpy(string_space, encoded_string, length);
return offset;
}
/****************************************************************************
* ctl2_alloc_importinfo
*
* Allocates and initializes an import information structure in a type library.
*
* RETURNS
*
* Success: The offset of the new importinfo.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_importinfo(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
MSFT_ImpInfo *impinfo) /* [I] The import information to store. */
{
int offset;
MSFT_ImpInfo *impinfo_space;
for (offset = 0;
offset < This->typelib_segdir[MSFT_SEG_IMPORTINFO].length;
offset += sizeof(MSFT_ImpInfo)) {
if (!memcmp(&(This->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]),
impinfo, sizeof(MSFT_ImpInfo))) {
return offset;
}
}
impinfo->flags |= This->typelib_header.nimpinfos++;
offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0);
if (offset == -1) return -1;
impinfo_space = (void *)(This->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset);
*impinfo_space = *impinfo;
return offset;
}
/****************************************************************************
* ctl2_alloc_importfile
*
* Allocates and initializes an import file definition in a type library.
*
* RETURNS
*
* Success: The offset of the new importinfo.
* Failure: -1 (this is invariably an out of memory condition).
*/
static int ctl2_alloc_importfile(
ICreateTypeLib2Impl *This, /* [I] The type library to allocate in. */
int guidoffset, /* [I] The offset to the GUID for the imported library. */
int major_version, /* [I] The major version number of the imported library. */
int minor_version, /* [I] The minor version number of the imported library. */
const WCHAR *filename) /* [I] The filename of the imported library. */
{
int length;
int offset;
MSFT_ImpFile *importfile;
char *encoded_string;
length = ctl2_encode_string(This, filename, &encoded_string);
encoded_string[0] <<= 2;
encoded_string[0] |= 1;
for (offset = 0; offset < This->typelib_segdir[MSFT_SEG_IMPORTFILES].length;
offset += ((((This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff)
| (This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) {
if (!memcmp(encoded_string, This->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset;
}
offset = ctl2_alloc_segment(This, MSFT_SEG_IMPORTFILES, length + 0xc, 0);
if (offset == -1) return -1;
importfile = (MSFT_ImpFile *)&This->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset];
importfile->guid = guidoffset;
importfile->lcid = This->typelib_header.lcid2;
importfile->version = major_version | (minor_version << 16);
memcpy(&importfile->filename, encoded_string, length);
return offset;
}
/****************************************************************************
* ctl2_alloc_custdata
*
* Allocates and initializes a "custom data" value in a type library.
*
* RETURNS
*
* Success: The offset of the new custdata.
* Failure:
*
* -1: Out of memory.
* -2: Unable to encode VARIANT data (typically a bug).
*/
static int ctl2_alloc_custdata(
ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the value. */
VARIANT *pVarVal) /* [I] The value to encode. */
{
int offset;
TRACE("(%p,%p(%d))\n",This,pVarVal,V_VT(pVarVal));
switch (V_VT(pVarVal)) {
case VT_UI4:
offset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
if (offset == -1) return offset;
*((unsigned short *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = VT_UI4;
*((unsigned long *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = V_UI4(pVarVal);
break;
default:
FIXME("Unknown variable encoding vt %d.\n", V_VT(pVarVal));
return -2;
}
return offset;
}
/****************************************************************************
* ctl2_set_custdata
*
* Adds a custom data element to an object in a type library.
*
* RETURNS
*
* Success: S_OK.
* Failure: One of E_INVALIDARG or E_OUTOFMEMORY.
*/
static HRESULT ctl2_set_custdata(
ICreateTypeLib2Impl *This, /* [I] The type library to store the custom data in. */
REFGUID guid, /* [I] The GUID used as a key to retrieve the custom data. */
VARIANT *pVarVal, /* [I] The custom data itself. */
int *offset) /* [I/O] The list of custom data to prepend to. */
{
MSFT_GuidEntry guidentry;
int dataoffset;
int guidoffset;
int custoffset;
int *custdata;
guidentry.guid = *guid;
guidentry.hreftype = -1;
guidentry.next_hash = -1;
guidoffset = ctl2_alloc_guid(This, &guidentry);
if (guidoffset == -1) return E_OUTOFMEMORY;
dataoffset = ctl2_alloc_custdata(This, pVarVal);
if (dataoffset == -1) return E_OUTOFMEMORY;
if (dataoffset == -2) return E_INVALIDARG;
custoffset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATAGUID, 12, 0);
if (custoffset == -1) return E_OUTOFMEMORY;
custdata = (int *)&This->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset];
custdata[0] = guidoffset;
custdata[1] = dataoffset;
custdata[2] = *offset;
*offset = custoffset;
return S_OK;
}
/****************************************************************************
* ctl2_encode_typedesc
*
* Encodes a type description, storing information in the TYPEDESC and ARRAYDESC
* segments as needed.
*
* RETURNS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -