⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 typelib2.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *	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 + -