📄 typelib2.c
字号:
/*
* TYPELIB2
*
* Copyright 2004 Alastair Bridgewater
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* --------------------------------------------------------------------------------------
* Known problems:
*
* Badly incomplete.
*
* Only works on little-endian systems.
*
*/
#include "config.h"
#include "wine/port.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <ctype.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winuser.h"
#include "wine/unicode.h"
#include "objbase.h"
#include "typelib.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(typelib2);
/* WINE_DEFAULT_DEBUG_CHANNEL(ole); */
/******************************************************************************
* ICreateTypeLib2 {OLEAUT32}
*
* NOTES
* The ICreateTypeLib2 interface provides an interface whereby one may create
* new type library (.tlb) files.
*
* This interface inherits from ICreateTypeLib, and can be freely cast back
* and forth between an ICreateTypeLib and an ICreateTypeLib2 on local clients.
* This dispensation applies only to ICreateTypeLib objects obtained on MSFT
* format type libraries (those made through CreateTypeLib2).
*
* METHODS
*/
/******************************************************************************
* ICreateTypeInfo2 {OLEAUT32}
*
* NOTES
* The ICreateTypeInfo2 interface provides an interface whereby one may add
* type information to type library (.tlb) files.
*
* This interface inherits from ICreateTypeInfo, and can be freely cast back
* and forth between an ICreateTypeInfo and an ICreateTypeInfo2 on local clients.
* This dispensation applies only to ICreateTypeInfo objects obtained on MSFT
* format type libraries (those made through CreateTypeLib2).
*
* METHODS
*/
/******************************************************************************
* ITypeLib2 {OLEAUT32}
*
* NOTES
* The ITypeLib2 interface provides an interface whereby one may query MSFT
* format type library (.tlb) files.
*
* This interface inherits from ITypeLib, and can be freely cast back and
* forth between an ITypeLib and an ITypeLib2 on local clients. This
* dispensation applies only to ITypeLib objects obtained on MSFT format type
* libraries (those made through CreateTypeLib2).
*
* METHODS
*/
/******************************************************************************
* ITypeInfo2 {OLEAUT32}
*
* NOTES
* The ITypeInfo2 interface provides an interface whereby one may query type
* information stored in MSFT format type library (.tlb) files.
*
* This interface inherits from ITypeInfo, and can be freely cast back and
* forth between an ITypeInfo and an ITypeInfo2 on local clients. This
* dispensation applies only to ITypeInfo objects obtained on MSFT format type
* libraries (those made through CreateTypeLib2).
*
* METHODS
*/
/*================== Implementation Structures ===================================*/
enum MSFT_segment_index {
MSFT_SEG_TYPEINFO = 0, /* type information */
MSFT_SEG_IMPORTINFO, /* import information */
MSFT_SEG_IMPORTFILES, /* import filenames */
MSFT_SEG_REFERENCES, /* references (?) */
MSFT_SEG_GUIDHASH, /* hash table for guids? */
MSFT_SEG_GUID, /* guid storage */
MSFT_SEG_NAMEHASH, /* hash table for names */
MSFT_SEG_NAME, /* name storage */
MSFT_SEG_STRING, /* string storage */
MSFT_SEG_TYPEDESC, /* type descriptions */
MSFT_SEG_ARRAYDESC, /* array descriptions */
MSFT_SEG_CUSTDATA, /* custom data */
MSFT_SEG_CUSTDATAGUID, /* custom data guids */
MSFT_SEG_UNKNOWN, /* ??? */
MSFT_SEG_UNKNOWN2, /* ??? */
MSFT_SEG_MAX /* total number of segments */
};
typedef struct tagMSFT_ImpFile {
int guid;
LCID lcid;
int version;
char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */
} MSFT_ImpFile;
typedef struct tagICreateTypeLib2Impl
{
const ICreateTypeLib2Vtbl *lpVtbl;
const ITypeLib2Vtbl *lpVtblTypeLib2;
LONG ref;
WCHAR *filename;
MSFT_Header typelib_header;
MSFT_pSeg typelib_segdir[MSFT_SEG_MAX];
char *typelib_segment_data[MSFT_SEG_MAX];
int typelib_segment_block_length[MSFT_SEG_MAX];
INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */
INT *typelib_namehash_segment;
INT *typelib_guidhash_segment;
struct tagICreateTypeInfo2Impl *typeinfos;
struct tagICreateTypeInfo2Impl *last_typeinfo;
} ICreateTypeLib2Impl;
static inline ICreateTypeLib2Impl *impl_from_ITypeLib2( ITypeLib2 *iface )
{
return (ICreateTypeLib2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeLib2Impl, lpVtblTypeLib2));
}
typedef struct tagICreateTypeInfo2Impl
{
const ICreateTypeInfo2Vtbl *lpVtbl;
const ITypeInfo2Vtbl *lpVtblTypeInfo2;
LONG ref;
ICreateTypeLib2Impl *typelib;
MSFT_TypeInfoBase *typeinfo;
INT *typedata;
int typedata_allocated;
int typedata_length;
int indices[42];
int names[42];
int offsets[42];
int datawidth;
struct tagICreateTypeInfo2Impl *next_typeinfo;
} ICreateTypeInfo2Impl;
static inline ICreateTypeInfo2Impl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
{
return (ICreateTypeInfo2Impl *)((char*)iface - FIELD_OFFSET(ICreateTypeInfo2Impl, lpVtblTypeInfo2));
}
static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface);
/*================== Internal functions ===================================*/
/****************************************************************************
* ctl2_init_header
*
* Initializes the type library header of a new typelib.
*/
static void ctl2_init_header(
ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
{
This->typelib_header.magic1 = 0x5446534d;
This->typelib_header.magic2 = 0x00010002;
This->typelib_header.posguid = -1;
This->typelib_header.lcid = 0x0409; /* or do we use the current one? */
This->typelib_header.lcid2 = 0x0409;
This->typelib_header.varflags = 0x40;
This->typelib_header.version = 0;
This->typelib_header.flags = 0;
This->typelib_header.nrtypeinfos = 0;
This->typelib_header.helpstring = -1;
This->typelib_header.helpstringcontext = 0;
This->typelib_header.helpcontext = 0;
This->typelib_header.nametablecount = 0;
This->typelib_header.nametablechars = 0;
This->typelib_header.NameOffset = -1;
This->typelib_header.helpfile = -1;
This->typelib_header.CustomDataOffset = -1;
This->typelib_header.res44 = 0x20;
This->typelib_header.res48 = 0x80;
This->typelib_header.dispatchpos = -1;
This->typelib_header.nimpinfos = 0;
}
/****************************************************************************
* ctl2_init_segdir
*
* Initializes the segment directory of a new typelib.
*/
static void ctl2_init_segdir(
ICreateTypeLib2Impl *This) /* [I] The typelib to initialize. */
{
int i;
MSFT_pSeg *segdir;
segdir = &This->typelib_segdir[MSFT_SEG_TYPEINFO];
for (i = 0; i < 15; i++) {
segdir[i].offset = -1;
segdir[i].length = 0;
segdir[i].res08 = -1;
segdir[i].res0c = 0x0f;
}
}
/****************************************************************************
* ctl2_hash_guid
*
* Generates a hash key from a GUID.
*
* RETURNS
*
* The hash key for the GUID.
*/
static int ctl2_hash_guid(
REFGUID guid) /* [I] The guid to find. */
{
int hash;
int i;
hash = 0;
for (i = 0; i < 8; i ++) {
hash ^= ((const short *)guid)[i];
}
return hash & 0x1f;
}
/****************************************************************************
* ctl2_find_guid
*
* Locates a guid in a type library.
*
* RETURNS
*
* The offset into the GUID segment of the guid, or -1 if not found.
*/
static int ctl2_find_guid(
ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
int hash_key, /* [I] The hash key for the guid. */
REFGUID guid) /* [I] The guid to find. */
{
int offset;
MSFT_GuidEntry *guidentry;
offset = This->typelib_guidhash_segment[hash_key];
while (offset != -1) {
guidentry = (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][offset];
if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
offset = guidentry->next_hash;
}
return offset;
}
/****************************************************************************
* ctl2_find_name
*
* Locates a name in a type library.
*
* RETURNS
*
* The offset into the NAME segment of the name, or -1 if not found.
*
* NOTES
*
* The name must be encoded as with ctl2_encode_name().
*/
static int ctl2_find_name(
ICreateTypeLib2Impl *This, /* [I] The typelib to operate against. */
char *name) /* [I] The encoded name to find. */
{
int offset;
int *namestruct;
offset = This->typelib_namehash_segment[name[2] & 0x7f];
while (offset != -1) {
namestruct = (int *)&This->typelib_segment_data[MSFT_SEG_NAME][offset];
if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) {
/* hash codes and lengths match, final test */
if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break;
}
/* move to next item in hash bucket */
offset = namestruct[1];
}
return offset;
}
/****************************************************************************
* ctl2_encode_name
*
* Encodes a name string to a form suitable for storing into a type library
* or comparing to a name stored in a type library.
*
* RETURNS
*
* The length of the encoded name, including padding and length+hash fields.
*
* NOTES
*
* Will throw an exception if name or result are NULL. Is not multithread
* safe in the slightest.
*/
static int ctl2_encode_name(
ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (used for LCID only). */
const WCHAR *name, /* [I] The name string to encode. */
char **result) /* [O] A pointer to a pointer to receive the encoded name. */
{
int length;
static char converted_name[0x104];
int offset;
int value;
length = WideCharToMultiByte(CP_ACP, 0, name, strlenW(name), converted_name+4, 0x100, NULL, NULL);
converted_name[0] = length & 0xff;
converted_name[length + 4] = 0;
converted_name[1] = 0x00;
value = LHashValOfNameSysA(This->typelib_header.varflags & 0x0f, This->typelib_header.lcid, converted_name + 4);
converted_name[2] = value;
converted_name[3] = value >> 8;
for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57;
*result = converted_name;
return (length + 7) & ~3;
}
/****************************************************************************
* ctl2_encode_string
*
* Encodes a string to a form suitable for storing into a type library or
* comparing to a string stored in a type library.
*
* RETURNS
*
* The length of the encoded string, including padding and length fields.
*
* NOTES
*
* Will throw an exception if string or result are NULL. Is not multithread
* safe in the slightest.
*/
static int ctl2_encode_string(
ICreateTypeLib2Impl *This, /* [I] The typelib to operate against (not used?). */
const WCHAR *string, /* [I] The string to encode. */
char **result) /* [O] A pointer to a pointer to receive the encoded string. */
{
int length;
static char converted_string[0x104];
int offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -