blob: ed80a481205fce96aea027231981008a4f2c5345 [file] [log] [blame]
/*
* TYPELIB
*
* Copyright 1997 Marcus Meissner
* 1999 Rein Klazes
* there is much left to do here before it can be usefull for real world
* programs
* know problems:
* -. Only one format of typelibs is supported
* -. All testing until sofar is done using special written windows programs
* -. Data structures are straightforward, but slow for look-ups.
* -. (related) nothing is hashed
* -. a typelib is always read in its entirely into memory and never released.
* -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
* of them I don't know yet how to implement them.
* -. Most error return values are just guessed not checked with windows
* behaviour.
* -. all locale stuf ignored
* -. move stuf to wine/dlls
* -. didn't bother with a c++ interface
* -. lousy fatal error handling
* -. some methods just return pointers to internal data structures, this is
* partly laziness, partly I want to check how windows does it.
*
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
#include "winerror.h"
#include "winreg.h"
#include "oleauto.h"
#include "winnls.h"
#include "wine/winbase16.h"
#include "heap.h"
#include "wine/obj_base.h"
#include "debugtools.h"
#include "winversion.h"
/* FIXME: get rid of these */
typedef struct ITypeInfoVtbl ITypeLib_VTable, *LPTYPEINFO_VTABLE ;
typedef struct ITypeLibVtbl *LPTYPELIB_VTABLE ;
#include "typelib.h"
DEFAULT_DEBUG_CHANNEL(ole)
DECLARE_DEBUG_CHANNEL(typelib)
/****************************************************************************
* QueryPathOfRegTypeLib16 [TYPELIB.14]
*
* the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
* RETURNS
* path of typelib
*/
HRESULT WINAPI
QueryPathOfRegTypeLib16(
REFGUID guid, /* [in] referenced guid */
WORD wMaj, /* [in] major version */
WORD wMin, /* [in] minor version */
LCID lcid, /* [in] locale id */
LPBSTR16 path /* [out] path of typelib */
) {
char xguid[80];
char typelibkey[100],pathname[260];
DWORD plen;
if (HIWORD(guid)) {
WINE_StringFromCLSID(guid,xguid);
sprintf(typelibkey,"SOFTWARE\\Classes\\Typelib\\%s\\%d.%d\\%lx\\win16",
xguid,wMaj,wMin,lcid
);
} else {
sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
FIXME_(ole)("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
return E_FAIL;
}
plen = sizeof(pathname);
if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
/* try again without lang specific id */
if (SUBLANGID(lcid))
return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
FIXME_(ole)("key %s not found\n",typelibkey);
return E_FAIL;
}
*path = SysAllocString16(pathname);
return S_OK;
}
/****************************************************************************
* QueryPathOfRegTypeLib [OLEAUT32.164]
* RETURNS
* path of typelib
*/
HRESULT WINAPI
QueryPathOfRegTypeLib(
REFGUID guid, /* [in] referenced guid */
WORD wMaj, /* [in] major version */
WORD wMin, /* [in] minor version */
LCID lcid, /* [in] locale id */
LPBSTR path /* [out] path of typelib */
) {
char xguid[80];
char typelibkey[100],pathname[260];
DWORD plen;
if (HIWORD(guid)) {
WINE_StringFromCLSID(guid,xguid);
sprintf(typelibkey,"SOFTWARE\\Classes\\Typelib\\%s\\%d.%d\\%lx\\win32",
xguid,wMaj,wMin,lcid
);
} else {
sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
FIXME_(ole)("(%s,%d,%d,0x%04lx,%p),stub!\n",xguid,wMaj,wMin,(DWORD)lcid,path);
return E_FAIL;
}
plen = sizeof(pathname);
if (RegQueryValue16(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
/* try again without lang specific id */
if (SUBLANGID(lcid))
return QueryPathOfRegTypeLib(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
FIXME_(ole)("key %s not found\n",typelibkey);
return E_FAIL;
}
*path = HEAP_strdupAtoW(GetProcessHeap(),0,pathname);
return S_OK;
}
/******************************************************************************
* LoadTypeLib [TYPELIB.3] Loads and registers a type library
* NOTES
* Docs: OLECHAR FAR* szFile
* Docs: iTypeLib FAR* FAR* pptLib
*
* RETURNS
* Success: S_OK
* Failure: Status
*/
HRESULT WINAPI LoadTypeLib16(
OLECHAR *szFile, /* [in] Name of file to load from */
void * *pptLib) /* [out] Pointer to pointer to loaded type library */
{
FIXME_(ole)("('%s',%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
if (pptLib!=0)
*pptLib=0;
return E_FAIL;
}
/******************************************************************************
* LoadTypeLib [OLEAUT32.161]
* Loads and registers a type library
* NOTES
* Docs: OLECHAR FAR* szFile
* Docs: iTypeLib FAR* FAR* pptLib
*
* RETURNS
* Success: S_OK
* Failure: Status
*/
int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypelib);
HRESULT WINAPI LoadTypeLib(
OLECHAR *szFile, /* [in] Name of file to load from */
ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
{
LPSTR p;
HRESULT res;
TRACE_(typelib)("('%s',%p)\n",debugstr_w(szFile),pptLib);
p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile);
res= TLB_ReadTypeLib(p, pptLib);
/* XXX need to free p ?? */
TRACE_(typelib)(" returns %ld\n",res);
return res;
}
/******************************************************************************
* LoadRegTypeLib [OLEAUT32.162]
*/
HRESULT WINAPI LoadRegTypeLib(
REFGUID rguid, /* [in] referenced guid */
WORD wVerMajor, /* [in] major version */
WORD wVerMinor, /* [in] minor version */
LCID lcid, /* [in] locale id */
ITypeLib **ppTLib /* [out] path of typelib */
) {
BSTR bstr=NULL;
HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor,
lcid, &bstr);
if(SUCCEEDED(res)){
res= LoadTypeLib(bstr, ppTLib);
SysFreeString(bstr);
}
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)rguid,xriid);
TRACE_(typelib)("(IID: %s) load %s (%p)\n",xriid,
SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
}
return res;
}
/******************************************************************************
* RegisterTypeLib [OLEAUT32.163]
* Adds information about a type library to the System Registry
* NOTES
* Docs: ITypeLib FAR * ptlib
* Docs: OLECHAR FAR* szFullPath
* Docs: OLECHAR FAR* szHelpDir
*
* RETURNS
* Success: S_OK
* Failure: Status
*/
HRESULT WINAPI RegisterTypeLib(
ITypeLib * ptlib, /*[in] Pointer to the library*/
OLECHAR * szFullPath, /*[in] full Path of the library*/
OLECHAR * szHelpDir) /*[in] dir to the helpfile for the library,
may be NULL*/
{ FIXME_(ole)("(%p,%s,%s): stub\n",ptlib, debugstr_w(szFullPath),debugstr_w(szHelpDir));
return S_OK; /* FIXME: pretend everything is OK */
}
/******************************************************************************
* UnRegisterTypeLib [OLEAUT32.186]
* Removes information about a type library from the System Registry
* NOTES
*
* RETURNS
* Success: S_OK
* Failure: Status
*/
HRESULT WINAPI UnRegisterTypeLib(
REFGUID libid, /* [in] Guid of the library */
WORD wVerMajor, /* [in] major version */
WORD wVerMinor, /* [in] minor version */
LCID lcid, /* [in] locale id */
SYSKIND syskind)
{
char xriid[50];
WINE_StringFromCLSID((LPCLSID)libid,xriid);
TRACE_(typelib)("(IID: %s): stub\n",xriid);
return S_OK; /* FIXME: pretend everything is OK */
}
/****************************************************************************
* OABuildVersion (TYPELIB.15)
* RETURNS
* path of typelib
*/
DWORD WINAPI OABuildVersion16(void)
{
WINDOWS_VERSION ver = VERSION_GetVersion();
switch (ver) {
case WIN95:
return MAKELONG(0xbd0, 0xa); /* Win95A */
case WIN31:
return MAKELONG(0xbd3, 0x3); /* WfW 3.11 */
default:
FIXME_(ole)("Version value not known yet. Please investigate it !");
return MAKELONG(0xbd0, 0xa); /* return Win95A for now */
}
}
/* for better debugging info leave the static out for the time being */
#define static
/*=======================Itypelib methods ===============================*/
/* ITypeLib methods */
static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
VOID **ppvObject);
static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB This);
static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB This);
static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB This);
static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB This, UINT index,
ITypeInfo **ppTInfo);
static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB This, UINT index,
TYPEKIND *pTKind);
static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB This, REFGUID guid,
ITypeInfo **ppTinfo);
static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB This,
LPTLIBATTR *ppTLibAttr);
static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB This,
ITypeComp **ppTComp);
static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB This, INT index,
BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext,
BSTR *pBstrHelpFile);
static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB This, LPOLESTR szNameBuf,
ULONG lHashVal, BOOL *pfName);
static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB This, LPOLESTR szNameBuf,
ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound);
static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB This,
TLIBATTR *pTLibAttr);
static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * This, REFGUID guid,
VARIANT *pVarVal);
static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * This,
UINT *pcUniqueNames, UINT *pcchUniqueNames);
static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * This,
INT index, LCID lcid, BSTR *pbstrHelpString,
INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll);
static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * This,
CUSTDATA *pCustData);
static ICOM_VTABLE(ITypeLib) tlbvt = {
ITypeLib_fnQueryInterface,
ITypeLib_fnAddRef,
ITypeLib_fnRelease,
ITypeLib_fnGetTypeInfoCount,
ITypeLib_fnGetTypeInfo,
ITypeLib_fnGetTypeInfoType,
ITypeLib_fnGetTypeInfoOfGuid,
ITypeLib_fnGetLibAttr,
ITypeLib_fnGetTypeComp,
ITypeLib_fnGetDocumentation,
ITypeLib_fnIsName,
ITypeLib_fnFindName,
ITypeLib_fnReleaseTLibAttr,
ITypeLib2_fnGetCustData,
ITypeLib2_fnGetLibStatistics,
ITypeLib2_fnGetDocumentation2,
ITypeLib2_fnGetAllCustData
};
/* TypeInfo Methods */
static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO This, REFIID riid,
VOID **ppvObject);
static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO This);
static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO This);
static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO This,
LPTYPEATTR *ppTypeAttr);
static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO This,
ITypeComp * *ppTComp);
static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO This, UINT index,
LPFUNCDESC *ppFuncDesc);
static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO This, UINT index,
LPVARDESC *ppVarDesc);
static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO This, MEMBERID memid,
BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames);
static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO This,
UINT index, HREFTYPE *pRefType);
static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO This,
UINT index, INT *pImplTypeFlags);
static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO This,
LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId);
static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO This, VOID *pIUnk,
MEMBERID memid, UINT16 dwFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *pArgErr);
static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO This,
MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
DWORD *pdwHelpContext, BSTR *pBstrHelpFile);
static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO This,
MEMBERID memid, INVOKEKIND invKind, BSTR *pBstrDllName,
BSTR *pBstrName, WORD *pwOrdinal);
static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO This,
HREFTYPE hRefType, ITypeInfo * *ppTInfo);
static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO This,
MEMBERID memid, INVOKEKIND invKind, PVOID *ppv);
static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO This,
IUnknown *pUnk, REFIID riid, VOID * *ppvObj);
static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO This, MEMBERID memid,
BSTR *pBstrMops);
static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO This,
ITypeLib * *ppTLib, UINT *pIndex);
static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO This,
TYPEATTR *pTypeAttr);
static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO This,
FUNCDESC *pFuncDesc);
static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO This,
VARDESC *pVarDesc);
/* itypeinfo2 methods */
static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * This,
TYPEKIND *pTypeKind);
static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * This,
UINT *pTypeFlags);
static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * This,
MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex);
static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * This,
MEMBERID memid, UINT *pVarIndex);
static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * This,
REFGUID guid, VARIANT *pVarVal);
static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * This,
UINT index, REFGUID guid, VARIANT *pVarVal);
static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * This,
UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal);
static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * This,
UINT index, REFGUID guid, VARIANT *pVarVal);
static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * This,
UINT index, REFGUID guid, VARIANT *pVarVal);
static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * This,
MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll);
static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * This,
CUSTDATA *pCustData);
static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * This,
UINT index, CUSTDATA *pCustData);
static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * This,
UINT indexFunc, UINT indexParam, CUSTDATA *pCustData);
static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * This,
UINT index, CUSTDATA *pCustData);
static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * This,
UINT index, CUSTDATA *pCustData);
static ICOM_VTABLE(ITypeInfo) tinfvt = {
ITypeInfo_fnQueryInterface,
ITypeInfo_fnAddRef,
ITypeInfo_fnRelease,
ITypeInfo_fnGetTypeAttr,
ITypeInfo_fnGetTypeComp,
ITypeInfo_fnGetFuncDesc,
ITypeInfo_fnGetVarDesc,
ITypeInfo_fnGetNames,
ITypeInfo_fnGetRefTypeOfImplType,
ITypeInfo_fnGetImplTypeFlags,
ITypeInfo_fnGetIDsOfNames,
ITypeInfo_fnInvoke,
ITypeInfo_fnGetDocumentation,
ITypeInfo_fnGetDllEntry,
ITypeInfo_fnGetRefTypeInfo,
ITypeInfo_fnAddressOfMember,
ITypeInfo_fnCreateInstance,
ITypeInfo_fnGetMops,
ITypeInfo_fnGetContainingTypeLib,
ITypeInfo_fnReleaseTypeAttr,
ITypeInfo_fnReleaseFuncDesc,
ITypeInfo_fnReleaseVarDesc,
ITypeInfo2_fnGetTypeKind,
ITypeInfo2_fnGetTypeFlags,
ITypeInfo2_fnGetFuncIndexOfMemId,
ITypeInfo2_fnGetVarIndexOfMemId,
ITypeInfo2_fnGetCustData,
ITypeInfo2_fnGetFuncCustData,
ITypeInfo2_fnGetParamCustData,
ITypeInfo2_fnGetVarCustData,
ITypeInfo2_fnGetImplTypeCustData,
ITypeInfo2_fnGetDocumentation2,
ITypeInfo2_fnGetAllCustData,
ITypeInfo2_fnGetAllFuncCustData,
ITypeInfo2_fnGetAllParamCustData,
ITypeInfo2_fnGetAllVarCustData,
ITypeInfo2_fnGetAllImplTypeCustData,
};
static TYPEDESC stndTypeDesc[VT_LPWSTR+1]={/* VT_LPWSTR is largest type that */
/* may appear in type description*/
{{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
{{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
{{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
{{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
{{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
{{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
{{0},30},{{0},31}};
static void TLB_abort()
{
*((int *)0)=0;
}
static void * TLB_Alloc(unsigned size)
{
void * ret;
if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
/* FIXME */
ERR_(ole)("cannot allocate memory\n");
}
return ret;
}
/* candidate for a more global appearance... */
static BSTR TLB_DupAtoBstr(PCHAR Astr)
{
int len;
BSTR bstr;
DWORD *pdw ;
if(!Astr)
return NULL;
len=strlen(Astr);
pdw =TLB_Alloc((len+3)*sizeof(OLECHAR));
pdw[0]=(len)*sizeof(OLECHAR);
bstr=(BSTR)&( pdw[1]);
lstrcpyAtoW( bstr, Astr);
TRACE_(typelib)("copying %s to (%p)\n", Astr, bstr);
return bstr;
}
static void TLB_Free(void * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
/* read function */
DWORD TLB_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
{
DWORD bytesread=0;
if (( where != DO_NOT_SEEK &&
(0xffffffff == SetFilePointer( pcx->hFile, where, 0,FILE_BEGIN))
) ||
!ReadFile(pcx->hFile, buffer, count, &bytesread, NULL)
) {
/* FIXME */
ERR_(typelib)("read error is 0x%lx reading %ld bytes at 0x%lx\n",
GetLastError(), count, where);
TLB_abort();
exit(1);
}
return bytesread;
}
static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
{
if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
memset(pGuid,0, sizeof(GUID));
return;
}
TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
}
PCHAR TLB_ReadName( TLBContext *pcx, int offset)
{
char * name;
TLBNameIntro niName;
TLB_Read(&niName, sizeof(niName), pcx,
pcx->pTblDir->pNametab.offset+offset);
niName.namelen &= 0xFF; /* FIXME: correct ? */
name=TLB_Alloc((niName.namelen & 0xff) +1);
TLB_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
name[niName.namelen & 0xff]='\0';
return name;
}
PCHAR TLB_ReadString( TLBContext *pcx, int offset)
{
char * string;
INT16 length;
if(offset<0) return NULL;
TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
if(length <= 0) return 0;
string=TLB_Alloc(length +1);
TLB_Read(string, length, pcx, DO_NOT_SEEK);
string[length]='\0';
return string;
}
/*
* read a value and fill a VARIANT structure
*/
static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
{
int size;
if(offset <0) { /* data is packed in here */
pVar->vt = (offset & 0x7c000000 )>> 26;
V_UNION(pVar, iVal) = offset & 0xffff;
return;
}
TLB_Read(&(pVar->vt), sizeof(VARTYPE), pcx,
pcx->pTblDir->pCustData.offset + offset );
switch(pVar->vt){
case VT_EMPTY: /* FIXME: is this right? */
case VT_NULL: /* FIXME: is this right? */
case VT_I2 : /* this should not happen */
case VT_I4 :
case VT_R4 :
case VT_ERROR :
case VT_BOOL :
case VT_I1 :
case VT_UI1 :
case VT_UI2 :
case VT_UI4 :
case VT_INT :
case VT_UINT :
case VT_VOID : /* FIXME: is this right? */
case VT_HRESULT :
size=4; break;
case VT_R8 :
case VT_CY :
case VT_DATE :
case VT_I8 :
case VT_UI8 :
case VT_DECIMAL : /* FIXME: is this right? */
case VT_FILETIME :
size=8;break;
/* pointer types with known behaviour */
case VT_BSTR :{
char * ptr;
TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
ptr=TLB_Alloc(size);/* allocate temp buffer */
TLB_Read(ptr, size, pcx, DO_NOT_SEEK ); /* read string (ANSI) */
V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
/* FIXME: do we need a AtoW conversion here? */
V_UNION(pVar, bstrVal[size])=L'\0';
while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
TLB_Free(ptr);
}
size=-4; break;
/* FIXME: this will not work AT ALL when the variant contains a pointer */
case VT_DISPATCH :
case VT_VARIANT :
case VT_UNKNOWN :
case VT_PTR :
case VT_SAFEARRAY :
case VT_CARRAY :
case VT_USERDEFINED :
case VT_LPSTR :
case VT_LPWSTR :
case VT_BLOB :
case VT_STREAM :
case VT_STORAGE :
case VT_STREAMED_OBJECT :
case VT_STORED_OBJECT :
case VT_BLOB_OBJECT :
case VT_CF :
case VT_CLSID :
default:
size=0;
FIXME_(ole)("VARTYPE %d is not supported, setting pointer to NULL\n",
pVar->vt);
}
if(size>0) /* (big|small) endian correct? */
TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
return ;
}
/*
* create a linked list with custom data
*/
static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
{
TLBCDGuid entry;
TLBCustData* pNew;
int count=0;
while(offset >=0){
count++;
pNew=TLB_Alloc(sizeof(TLBCustData));
TLB_Read(&entry, sizeof(entry), pcx,
pcx->pTblDir->pCDGuids.offset+offset);
TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx);
/* add new custom data at head of the list */
pNew->next=*ppCustData;
*ppCustData=pNew;
offset = entry.next;
}
return count;
}
static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd )
{
if(type <0)
pTd->vt=type & VT_TYPEMASK;
else
*pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
}
static void TLB_DoFuncs(TLBContext *pcx, int cFuncs, int cVars,
int offset, TLBFuncDesc ** pptfd)
{
/*
* member information is stored in a data structure at offset
* indicated by the memoffset field of the typeinfo structure
* There are several distinctive parts.
* the first part starts with a field that holds the total length
* of this (first) part excluding this field. Then follow the records,
* for each member there is one record.
*
* First entry is always the length of the record (excluding this
* length word).
* Rest of the record depends on the type of the member. If there is
* a field indicating the member type (function variable intereface etc)
* I have not found it yet. At this time we depend on the information
* in the type info and the usual order how things are stored.
*
* Second follows an array sized nrMEM*sizeof(INT) with a memeber id
* for each member;
*
* Third is a equal sized array with file offsets to the name entry
* of each member.
*
* Forth and last (?) part is an array with offsets to the records in the
* first part of this file segment.
*/
int infolen, nameoffset, reclength, nrattributes;
char recbuf[512];
TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf;
int i, j;
int recoffset=offset+sizeof(INT);
TLB_Read(&infolen,sizeof(INT), pcx, offset);
for(i=0;i<cFuncs;i++){
*pptfd=TLB_Alloc(sizeof(TLBFuncDesc));
/* name, eventually add to a hash table */
TLB_Read(&nameoffset, sizeof(INT), pcx,
offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
(*pptfd)->Name=TLB_ReadName(pcx, nameoffset);
/* read the function information record */
TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
reclength &=0x1ff;
TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
/* do the attributes */
nrattributes=(reclength-pFuncRec->nrargs*3*sizeof(int)-0x18)
/sizeof(int);
if(nrattributes>0){
(*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
if(nrattributes>1){
(*pptfd)->HelpString = TLB_ReadString(pcx,
pFuncRec->OptAttr[1]) ;
if(nrattributes>2){
if(pFuncRec->FKCCIC & 0x2000)
(*pptfd)->Entry = (char *) pFuncRec->OptAttr[2] ;
else
(*pptfd)->Entry = TLB_ReadString(pcx,
pFuncRec->OptAttr[2]);
if(nrattributes>5 )
(*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
if(nrattributes>6 && pFuncRec->FKCCIC & 0x80){
TLB_CustData(pcx, pFuncRec->OptAttr[6],
&(*pptfd)->pCustData);
}
}
}
}
/* fill the FuncDesc Structure */
TLB_Read(&(*pptfd)->funcdesc.memid, sizeof(INT), pcx,
offset + infolen + ( i + 1) * sizeof(INT));
(*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
(*pptfd)->funcdesc.invkind = ((pFuncRec->FKCCIC) >>3) & 0xF;
(*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >>8 & 0xF;
(*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
(*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
(*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
(*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
TLB_GetTdesc(pcx, pFuncRec->DataType,
&(*pptfd)->funcdesc.elemdescFunc.tdesc) ;
/* do the parameters/arguments */
if(pFuncRec->nrargs){
TLBParameterInfo paraminfo;
(*pptfd)->funcdesc.lprgelemdescParam=
TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
(*pptfd)->pParamDesc=TLB_Alloc(pFuncRec->nrargs *
sizeof(TLBParDesc));
TLB_Read(&paraminfo,sizeof(paraminfo), pcx, recoffset+reclength -
pFuncRec->nrargs * sizeof(TLBParameterInfo));
for(j=0;j<pFuncRec->nrargs;j++){
TLB_GetTdesc(pcx, paraminfo.DataType,
&(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ;
V_UNION(&((*pptfd)->funcdesc.lprgelemdescParam[j]),
paramdesc.wParamFlags) = paraminfo.Flags;
(*pptfd)->pParamDesc[j].Name=(void *)paraminfo.oName;
TLB_Read(&paraminfo,sizeof(TLBParameterInfo), pcx,
DO_NOT_SEEK);
}
/* second time around */
for(j=0;j<pFuncRec->nrargs;j++){
/* name */
(*pptfd)->pParamDesc[j].Name=
TLB_ReadName(pcx, (int)(*pptfd)->pParamDesc[j].Name);
/* default value */
if((PARAMFLAG_FHASDEFAULT & V_UNION(&((*pptfd)->funcdesc.
lprgelemdescParam[j]),paramdesc.wParamFlags)) &&
((pFuncRec->FKCCIC) & 0x1000)){
INT *pInt=(INT *)((char *)pFuncRec + reclength -
(pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
PARAMDESC * pParamDesc= &V_UNION(&((*pptfd)->funcdesc.
lprgelemdescParam[j]),paramdesc);
pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
pParamDesc->pparamdescex->cBytes= sizeof(PARAMDESCEX);
TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
pInt[j], pcx);
}
/* custom info */
if(nrattributes>7+j && pFuncRec->FKCCIC & 0x80)
TLB_CustData(pcx, pFuncRec->OptAttr[7+j],
&(*pptfd)->pParamDesc[j].pCustData);
}
}
/* scode is not used: archaic win16 stuff FIXME: right? */
(*pptfd)->funcdesc.cScodes = 0 ;
(*pptfd)->funcdesc.lprgscode = NULL ;
pptfd=&((*pptfd)->next);
recoffset += reclength;
}
}
static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars,
int offset, TLBVarDesc ** pptvd)
{
int infolen, nameoffset, reclength;
char recbuf[256];
TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf;
int i;
int recoffset;
TLB_Read(&infolen,sizeof(INT), pcx, offset);
TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
recoffset += offset+sizeof(INT);
for(i=0;i<cVars;i++){
*pptvd=TLB_Alloc(sizeof(TLBVarDesc));
/* name, eventually add to a hash table */
TLB_Read(&nameoffset, sizeof(INT), pcx,
offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
(*pptvd)->Name=TLB_ReadName(pcx, nameoffset);
/* read the variable information record */
TLB_Read(&reclength, sizeof(INT), pcx, recoffset);
reclength &=0xff;
TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
/* Optional data */
if(reclength >(6*sizeof(INT)) )
(*pptvd)->HelpContext=pVarRec->HelpContext;
if(reclength >(7*sizeof(INT)) )
(*pptvd)->HelpString = TLB_ReadString(pcx, pVarRec->oHelpString) ;
if(reclength >(8*sizeof(INT)) )
if(reclength >(9*sizeof(INT)) )
(*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
/* fill the VarDesc Structure */
TLB_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
offset + infolen + ( i + 1) * sizeof(INT));
(*pptvd)->vardesc.varkind = pVarRec->VarKind;
(*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
TLB_GetTdesc(pcx, pVarRec->DataType,
&(*pptvd)->vardesc.elemdescVar.tdesc) ;
/* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
if(pVarRec->VarKind == VAR_CONST ){
V_UNION(&((*pptvd)->vardesc),lpvarValue)=TLB_Alloc(sizeof(VARIANT));
TLB_ReadValue(V_UNION(&((*pptvd)->vardesc),lpvarValue),
pVarRec->OffsValue, pcx);
}else
V_UNION(&((*pptvd)->vardesc),oInst)=pVarRec->OffsValue;
pptvd=&((*pptvd)->next);
recoffset += reclength;
}
}
/* fill in data for a hreftype (offset). When the refernced type is contained
* in the typelib, its just an (file) offset in the type info base dir.
* If comes fom import, its an offset+1 in the ImpInfo table
* */
static void TLB_DoRefType(TLBContext *pcx,
int offset, TLBRefType ** pprtd)
{
int j;
if(!HREFTYPE_INTHISFILE( offset)) {
/* external typelib */
TLBImpInfo impinfo;
TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
TLB_Read(&impinfo, sizeof(impinfo), pcx,
pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
if(pImpLib->offset==impinfo.oImpFile) break;
pImpLib=pImpLib->next;
}
if(pImpLib){
(*pprtd)->reference=offset;
(*pprtd)->pImpTLInfo=pImpLib;
TLB_ReadGuid(&(*pprtd)->guid, impinfo.oGuid, pcx);
}else{
ERR_(typelib)("Cannot find a reference\n");
(*pprtd)->reference=-1;
(*pprtd)->pImpTLInfo=(void *)-1;
}
}else{
/* in this typelib */
(*pprtd)->reference=offset;
(*pprtd)->pImpTLInfo=(void *)-2;
}
}
/* process Implemented Interfaces of a com class */
static void TLB_DoImplTypes(TLBContext *pcx, int count,
int offset, TLBRefType ** pprtd)
{
int i;
TLBRefRecord refrec;
for(i=0;i<count;i++){
if(offset<0) break; /* paranoia */
*pprtd=TLB_Alloc(sizeof(TLBRefType));
TLB_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
TLB_DoRefType(pcx, refrec.reftype, pprtd);
(*pprtd)->flags=refrec.flags;
(*pprtd)->ctCustData=
TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData);
offset=refrec.onext;
pprtd=&((*pprtd)->next);
}
}
/*
* process a typeinfo record
*/
TLBTypeInfo * TLB_DoTypeInfo(TLBContext *pcx, int count, TLBLibInfo* pLibInfo)
{
TLBTypeInfoBase tiBase;
TLBTypeInfo *ptiRet;
ptiRet=TLB_Alloc(sizeof(TLBTypeInfo));
ptiRet->lpvtbl = &tinfvt;
ptiRet->ref=1;
TLB_Read(&tiBase, sizeof(tiBase) ,pcx ,
pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
/* this where we are coming from */
ptiRet->pTypeLib=pLibInfo;
ptiRet->index=count;
/* fill in the typeattr fields */
TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
TLB_GetTdesc(pcx, tiBase.datatype1,
&ptiRet->TypeAttr.tdescAlias) ;
/* FIXME: */
/* IDLDESC idldescType; *//* never saw this one != zero */
/* name, eventually add to a hash table */
ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset);
TRACE_(typelib)("reading %s\n", ptiRet->Name);
/* help info */
ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs);
ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
ptiRet->dwHelpContext=tiBase.helpcontext;
/* note: InfoType's Help file and HelpStringDll come from the containing
* library. Further HelpString and Docstring appear to be the same thing :(
*/
/* functions */
if(ptiRet->TypeAttr.cFuncs >0 )
TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
tiBase.memoffset, & ptiRet->funclist);
/* variables */
if(ptiRet->TypeAttr.cVars >0 )
TLB_DoVars(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars,
tiBase.memoffset, & ptiRet->varlist);
if(ptiRet->TypeAttr.cImplTypes >0 ){
if(ptiRet->TypeAttr.typekind == TKIND_COCLASS)
TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes ,
tiBase.datatype1, & ptiRet->impltypelist);
else if(ptiRet->TypeAttr.typekind != TKIND_DISPATCH){
ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType));
TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist);
}
}
ptiRet->ctCustData=
TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
return ptiRet;
}
long TLB_FindTlb(TLBContext *pcx)
{/* FIXME: should parse the file properly
* hack to find our tlb data
*/
#define TLBBUFSZ 1024
char buff[TLBBUFSZ+1]; /* room for a trailing '\0' */
long ret=0,found=0;
int count;
char *pChr;
#define LOOK_FOR_MAGIC(magic) \
count=TLB_Read(buff, TLBBUFSZ, pcx, 0); \
do { \
buff[count]='\0'; \
pChr = buff; \
while (pChr) { \
pChr = memchr(pChr,magic[0],count-(pChr-buff));\
if (pChr) { \
if (!memcmp(pChr,magic,4)) { \
ret+= pChr-buff; \
found = 1; \
break; \
} \
pChr++; \
} \
} \
if (found) break; \
ret+=count; \
count=TLB_Read(buff, TLBBUFSZ, pcx, DO_NOT_SEEK);\
} while(count>0);
LOOK_FOR_MAGIC(TLBMAGIC2);
if(count)
return ret;
LOOK_FOR_MAGIC(TLBMAGIC1);
if(count)
ERR_(ole)("type library format not (yet) implemented\n");
else
ERR_(ole)("not type library found in this file\n");
return -1;
}
#undef LOOK_FOR_MAGIC
int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypeLib)
{
TLBContext cx;
OFSTRUCT ofStruct;
long oStart,lPSegDir;
TLBLibInfo* pLibInfo=NULL;
TLB2Header tlbHeader;
TLBSegDir tlbSegDir;
if((cx.hFile=OpenFile(file, &ofStruct, OF_READWRITE))==HFILE_ERROR) {
ERR_(typelib)("cannot open %s error 0x%lx\n",file, GetLastError());
return E_FAIL;
}
/* get pointer to beginning of typelib data */
if((oStart=TLB_FindTlb(&cx))<0){
if(oStart==-1)
ERR_(typelib)("cannot locate typelib in %s\n",file);
else
ERR_(typelib)("unsupported typelib format in %s\n",file);
return E_FAIL;
}
cx.oStart=oStart;
pLibInfo=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TLBLibInfo));
if (!pLibInfo){
CloseHandle(cx.hFile);
return E_OUTOFMEMORY;
}
pLibInfo->lpvtbl = &tlbvt;
pLibInfo->ref=1;
cx.pLibInfo=pLibInfo;
/* read header */
TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
/* there is a small number of information here until the next important
* part:
* the segment directory . Try to calculate the amount of data */
lPSegDir=sizeof(tlbHeader)+
(tlbHeader.nrtypeinfos)*4+
(tlbHeader.varflags & HELPDLLFLAG? 4 :0);
/* now read the segment directory */
TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
cx.pTblDir=&tlbSegDir;
/* just check two entries */
if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F ||
tlbSegDir.pImpInfo.res0c != 0x0F
) {
ERR_(typelib)("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
CloseHandle(cx.hFile);
return E_FAIL;
}
/* now fill our internal data */
/* TLIBATTR fields */
TLB_ReadGuid(&pLibInfo->LibAttr.guid, tlbHeader.posguid, &cx);
pLibInfo->LibAttr.lcid=tlbHeader.lcid;
pLibInfo->LibAttr.syskind=tlbHeader.varflags & 0x0f; /* check the mask */
pLibInfo->LibAttr.wMajorVerNum=LOWORD(tlbHeader.version);
pLibInfo->LibAttr.wMinorVerNum=HIWORD(tlbHeader.version);
pLibInfo->LibAttr.wLibFlags=(WORD) tlbHeader.flags & 0xffff;/* check mask */
/* name, eventually add to a hash table */
pLibInfo->Name=TLB_ReadName(&cx, tlbHeader.NameOffset);
/* help info */
pLibInfo->DocString=TLB_ReadString(&cx, tlbHeader.helpstring);
pLibInfo->HelpFile=TLB_ReadString(&cx, tlbHeader.helpfile);
if( tlbHeader.varflags & HELPDLLFLAG){
int offset;
TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
pLibInfo->HelpStringDll=TLB_ReadString(&cx, offset);
}
pLibInfo->dwHelpContext=tlbHeader.helpstringcontext;
/* custom data */
if(tlbHeader.CustomDataOffset >= 0) {
pLibInfo->ctCustData=
TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pLibInfo->pCustData);
}
/* fill in typedescriptions */
if(tlbSegDir.pTypdescTab.length >0){
int i, j, cTD=tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
INT16 td[4];
pLibInfo->pTypeDesc=
TLB_Alloc( cTD * sizeof(TYPEDESC));
TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
for(i=0;i<cTD;){
/* FIXME: add several sanity checks here */
pLibInfo->pTypeDesc[i].vt=td[0] & VT_TYPEMASK;
if(td[0]==VT_PTR ||td[0]==VT_SAFEARRAY){/* FIXME: check safearray */
if(td[3]<0)
V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
& stndTypeDesc[td[2]];
else
V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)=
& pLibInfo->pTypeDesc[td[3]/8];
}else if(td[0]==VT_CARRAY)
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
(void *)((int) td[2]); /* temp store offset in*/
/* array descr table here */
else if(td[0]==VT_USERDEFINED)
V_UNION(&(pLibInfo->pTypeDesc[i]),hreftype)=MAKELONG(td[2],td[3]);
if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
}
/* second time around to fill the array subscript info */
for(i=0;i<cTD;i++){
if(pLibInfo->pTypeDesc[i].vt != VT_CARRAY) continue;
if(tlbSegDir.pArrayDescriptions.offset>0){
TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset +
(int) V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc));
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=
TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
if(td[1]<0)
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem.vt=td[0] & VT_TYPEMASK;
else
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem=stndTypeDesc[td[0]/8];
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->cDims=td[2];
for(j=0;j<td[2];j++){
TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements,
sizeof(INT), &cx, DO_NOT_SEEK);
TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)
->rgbounds[j].lLbound,
sizeof(INT), &cx, DO_NOT_SEEK);
}
}else{
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=NULL;
ERR_(ole)("didn't find array description data\n");
}
}
}
/* imported type libs */
if(tlbSegDir.pImpFiles.offset>0){
TLBImpLib **ppImpLib=&(pLibInfo->pImpLibs);
int offset=tlbSegDir.pImpFiles.offset;
int oGuid;
UINT16 size;
while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length){
*ppImpLib=TLB_Alloc(sizeof(TLBImpLib));
(*ppImpLib)->offset=offset - tlbSegDir.pImpFiles.offset;
TLB_Read(&oGuid, sizeof(INT), &cx, offset);
TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
/* we are skipping some unknown info here */
TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT)));
size >>=2;
(*ppImpLib)->name=TLB_Alloc(size+1);
TLB_Read((*ppImpLib)->name,size, &cx, DO_NOT_SEEK);
offset=(offset+3*(sizeof(INT))+sizeof(UINT16)+size+3) & 0xfffffffc;
ppImpLib=&(*ppImpLib)->next;
}
}
/* type info's */
if(tlbHeader.nrtypeinfos >=0 ){
/*pLibInfo->TypeInfoCount=tlbHeader.nrtypeinfos; */
TLBTypeInfo **ppTI=&(pLibInfo->pTypeInfo);
int i;
for(i=0;i<(int)tlbHeader.nrtypeinfos;i++){
*ppTI=TLB_DoTypeInfo(&cx, i, pLibInfo);
ppTI=&((*ppTI)->next);
(pLibInfo->TypeInfoCount)++;
}
}
CloseHandle(cx.hFile);
*ppTypeLib=(LPTYPELIB)pLibInfo;
return S_OK;
}
/*================== ITypeLib(2) Methods ===================================*/
/* ITypeLib::QueryInterface
*/
static HRESULT WINAPI ITypeLib_fnQueryInterface( LPTYPELIB This, REFIID riid,
VOID **ppvObject)
{
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE_(typelib)("(%p)->(IID: %s)\n",This,xriid);
}
*ppvObject=NULL;
if(IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid,&IID_ITypeLib)||
IsEqualIID(riid,&IID_ITypeLib2))
*ppvObject = This;
if(*ppvObject){
(*(LPTYPELIB*)ppvObject)->lpvtbl->fnAddRef(This);
TRACE_(typelib)("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
return S_OK;
}
TRACE_(typelib)("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/* ITypeLib::AddRef
*/
static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB iface)
{
ICOM_THIS( TLBLibInfo, iface);
TRACE_(typelib)("(%p)->ref is %u\n",This, This->ref);
return ++(This->ref);
}
/* ITypeLib::Release
*/
static ULONG WINAPI ITypeLib_fnRelease( LPTYPELIB iface)
{
ICOM_THIS( TLBLibInfo, iface);
FIXME_(typelib)("(%p)->ref is %u: stub\n",This, This->ref);
(This->ref)--;
return S_OK;
}
/* ITypeLib::GetTypeInfoCount
*
* Returns the number of type descriptions in the type library
*/
static UINT WINAPI ITypeLib_fnGetTypeInfoCount( LPTYPELIB iface)
{
ICOM_THIS( TLBLibInfo, iface);
TRACE_(typelib)("(%p)->count is %d\n",This, This->TypeInfoCount);
return This->TypeInfoCount;
}
/* ITypeLib::GetTypeInfo
*
*etrieves the specified type description in the library.
*/
static HRESULT WINAPI ITypeLib_fnGetTypeInfo( LPTYPELIB iface, UINT index,
ITypeInfo **ppTInfo)
{
int i;
ICOM_THIS( TLBLibInfo, iface);
TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
TRACE_(typelib)("(%p) index %d \n",This, index);
for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo && i != index;i++)
*ppTLBTInfo=(*ppTLBTInfo)->next;
if(*ppTLBTInfo){
(*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
TRACE_(typelib)("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
return S_OK;
}
TRACE_(typelib)("-- element not found\n");
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeLibs::GetTypeInfoType
*
* Retrieves the type of a type description.
*/
static HRESULT WINAPI ITypeLib_fnGetTypeInfoType( LPTYPELIB iface, UINT index,
TYPEKIND *pTKind)
{
int i;
TLBTypeInfo *pTInfo;
ICOM_THIS( TLBLibInfo, iface);
TRACE_(typelib)("(%p) index %d \n",This, index);
for(i=0,pTInfo=This->pTypeInfo;pTInfo && i != index;i++)
pTInfo=(pTInfo)->next;
if(pTInfo){
*pTKind=pTInfo->TypeAttr.typekind;
TRACE_(typelib)("-- found Type (%p)->%d\n",pTKind,*pTKind);
return S_OK;
}
TRACE_(typelib)("-- element not found\n");
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeLib::GetTypeInfoOfGuid
*
* Retrieves the type description that corresponds to the specified GUID.
*
*/
static HRESULT WINAPI ITypeLib_fnGetTypeInfoOfGuid( LPTYPELIB iface,
REFGUID guid, ITypeInfo **ppTInfo)
{
int i;
ICOM_THIS( TLBLibInfo, iface);
TLBTypeInfo **ppTLBTInfo=(TLBTypeInfo **)ppTInfo;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %sx)\n",This,xriid);
}
for(i=0,*ppTLBTInfo=This->pTypeInfo;*ppTLBTInfo &&
!IsEqualIID(guid,&(*ppTLBTInfo)->TypeAttr.guid);i++)
*ppTLBTInfo=(*ppTLBTInfo)->next;
if(*ppTLBTInfo){
(*ppTLBTInfo)->lpvtbl->fnAddRef(*ppTInfo);
TRACE_(typelib)("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo);
return S_OK;
}
TRACE_(typelib)("-- element not found\n");
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeLib::GetLibAttr
*
* Retrieves the structure that contains the library's attributes.
*
*/
static HRESULT WINAPI ITypeLib_fnGetLibAttr( LPTYPELIB iface,
LPTLIBATTR *ppTLibAttr)
{
ICOM_THIS( TLBLibInfo, iface);
TRACE_(typelib)("(%p)\n",This);
/* FIXME: must do a copy here */
*ppTLibAttr=&This->LibAttr;
return S_OK;
}
/* ITypeLib::GetTypeComp
*
* Enables a client compiler to bind to a library's types, variables,
* constants, and global functions.
*
*/
static HRESULT WINAPI ITypeLib_fnGetTypeComp( LPTYPELIB iface,
ITypeComp **ppTComp)
{
ICOM_THIS( TLBLibInfo, iface);
FIXME_(typelib)("(%p): stub!\n",This);
return E_NOTIMPL;
}
/* ITypeLib::GetDocumentation
*
* Retrieves the library's documentation string, the complete Help file name
* and path, and the context identifier for the library Help topic in the Help
* file.
*
*/
static HRESULT WINAPI ITypeLib_fnGetDocumentation( LPTYPELIB iface, INT index,
BSTR *pBstrName, BSTR *pBstrDocString, DWORD *pdwHelpContext,
BSTR *pBstrHelpFile)
{
ICOM_THIS( TLBLibInfo, iface);
HRESULT result;
ITypeInfo *pTInfo;
TRACE_(typelib)("(%p) index %d Name(%p) DocString(%p)"
" HelpContext(%p) HelpFile(%p)\n",
This, index, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
if(index<0){ /* documentation for the typelib */
if(pBstrName)
*pBstrName=TLB_DupAtoBstr(This->Name);
if(pBstrDocString)
*pBstrName=TLB_DupAtoBstr(This->DocString);
if(pdwHelpContext)
*pdwHelpContext=This->dwHelpContext;
if(pBstrHelpFile)
*pBstrName=TLB_DupAtoBstr(This->HelpFile);
}else {/* for a typeinfo */
result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
if(SUCCEEDED(result)){
result=ITypeInfo_GetDocumentation(pTInfo, MEMBERID_NIL, pBstrName,
pBstrDocString, pdwHelpContext, pBstrHelpFile);
ITypeInfo_Release(pTInfo);
}
if(!SUCCEEDED(result))
return result;
}
return S_OK;
}
/* ITypeLib::IsName
*
* Indicates whether a passed-in string contains the name of a type or member
* described in the library.
*
*/
static HRESULT WINAPI ITypeLib_fnIsName( LPTYPELIB iface, LPOLESTR szNameBuf,
ULONG lHashVal, BOOL *pfName)
{
ICOM_THIS( TLBLibInfo, iface);
TLBTypeInfo *pTInfo;
TLBFuncDesc *pFInfo;
TLBVarDesc *pVInfo;
int i;
PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
*pfName=TRUE;
if(!strcmp(astr,This->Name)) goto ITypeLib_fnIsName_exit;
for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnIsName_exit;
for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnIsName_exit;
for(i=0;i<pFInfo->funcdesc.cParams;i++)
if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
goto ITypeLib_fnIsName_exit;
}
for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnIsName_exit;
}
*pfName=FALSE;
ITypeLib_fnIsName_exit:
TRACE_(typelib)("(%p)slow! search for %s: %s found!\n", This,
debugstr_a(astr), *pfName?"NOT":"");
HeapFree( GetProcessHeap(), 0, astr );
return S_OK;
}
/* ITypeLib::FindName
*
* Finds occurrences of a type description in a type library. This may be used
* to quickly verify that a name exists in a type library.
*
*/
static HRESULT WINAPI ITypeLib_fnFindName( LPTYPELIB iface, LPOLESTR szNameBuf,
ULONG lHashVal, ITypeInfo **ppTInfo, MEMBERID *rgMemId, UINT16 *pcFound)
{
ICOM_THIS( TLBLibInfo, iface);
TLBTypeInfo *pTInfo;
TLBFuncDesc *pFInfo;
TLBVarDesc *pVInfo;
int i,j = 0;
PCHAR astr= HEAP_strdupWtoA( GetProcessHeap(), 0, szNameBuf );
for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
if(!strcmp(astr,pTInfo->Name)) goto ITypeLib_fnFindName_exit;
for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
if(!strcmp(astr,pFInfo->Name)) goto ITypeLib_fnFindName_exit;
for(i=0;i<pFInfo->funcdesc.cParams;i++)
if(!strcmp(astr,pFInfo->pParamDesc[i].Name))
goto ITypeLib_fnFindName_exit;
}
for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next) ;
if(!strcmp(astr,pVInfo->Name)) goto ITypeLib_fnFindName_exit;
continue;
ITypeLib_fnFindName_exit:
pTInfo->lpvtbl->fnAddRef((LPTYPEINFO)pTInfo);
ppTInfo[j]=(LPTYPEINFO)pTInfo;
j++;
}
TRACE_(typelib)("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
This, *pcFound, debugstr_a(astr), j);
*pcFound=j;
HeapFree( GetProcessHeap(), 0, astr );
return S_OK;
}
/* ITypeLib::ReleaseTLibAttr
*
* Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
*
*/
static VOID WINAPI ITypeLib_fnReleaseTLibAttr( LPTYPELIB iface, TLIBATTR *pTLibAttr)
{
ICOM_THIS( TLBLibInfo, iface);
TRACE_(typelib)("freeing (%p)\n",This);
/* nothing to do */
}
/* ITypeLib2::GetCustData
*
* gets the custom data
*/
static HRESULT WINAPI ITypeLib2_fnGetCustData( ITypeLib * iface, REFGUID guid,
VARIANT *pVarVal)
{
ICOM_THIS( TLBLibInfo, iface);
TLBCustData *pCData;
for(pCData=This->pCustData; pCData; pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n",This,xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeLib2::GetLibStatistics
*
* Returns statistics about a type library that are required for efficient
* sizing of hash tables.
*
*/
static HRESULT WINAPI ITypeLib2_fnGetLibStatistics( ITypeLib * iface,
UINT *pcUniqueNames, UINT *pcchUniqueNames)
{
ICOM_THIS( TLBLibInfo, iface);
FIXME_(typelib)("(%p): stub!\n", This);
if(pcUniqueNames) *pcUniqueNames=1;
if(pcchUniqueNames) *pcchUniqueNames=1;
return S_OK;
}
/* ITypeLib2::GetDocumentation2
*
* Retrieves the library's documentation string, the complete Help file name
* and path, the localization context to use, and the context ID for the
* library Help topic in the Help file.
*
*/
static HRESULT WINAPI ITypeLib2_fnGetDocumentation2( ITypeLib * iface,
INT index, LCID lcid, BSTR *pbstrHelpString,
INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
{
ICOM_THIS( TLBLibInfo, iface);
HRESULT result;
ITypeInfo *pTInfo;
FIXME_(typelib)("(%p) index %d lcid %ld half implemented stub!\n", This,
index, lcid);
/* the help string should be obtained from the helpstringdll,
* using the _DLLGetDocumentation function, based on the supplied
* lcid. Nice to do sometime...
*/
if(index<0){ /* documentation for the typelib */
if(pbstrHelpString)
*pbstrHelpString=TLB_DupAtoBstr(This->DocString);
if(pdwHelpStringContext)
*pdwHelpStringContext=This->dwHelpContext;
if(pbstrHelpStringDll)
*pbstrHelpStringDll=TLB_DupAtoBstr(This->HelpStringDll);
}else {/* for a typeinfo */
result=ITypeLib_fnGetTypeInfo(iface, index, &pTInfo);
if(SUCCEEDED(result)){
result=ITypeInfo2_fnGetDocumentation2(pTInfo, MEMBERID_NIL, lcid,
pbstrHelpString, pdwHelpStringContext, pbstrHelpStringDll);
ITypeInfo_Release(pTInfo);
}
if(!SUCCEEDED(result))
return result;
}
return S_OK;
}
/* ITypeLib2::GetAllCustData
*
* Gets all custom data items for the library.
*
*/
static HRESULT WINAPI ITypeLib2_fnGetAllCustData( ITypeLib * iface,
CUSTDATA *pCustData)
{
ICOM_THIS( TLBLibInfo, iface);
TLBCustData *pCData;
int i;
TRACE_(typelib)("(%p) returning %d items\n", This, This->ctCustData);
pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=This->ctCustData;
for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
/*================== ITypeInfo(2) Methods ===================================*/
/* ITypeInfo::QueryInterface
*/
static HRESULT WINAPI ITypeInfo_fnQueryInterface( LPTYPEINFO iface, REFIID riid,
VOID **ppvObject)
{
ICOM_THIS( TLBTypeInfo, iface);
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)riid,xriid);
TRACE_(typelib)("(%p)->(IID: %s)\n",This,xriid);
}
*ppvObject=NULL;
if(IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid,&IID_ITypeInfo)||
IsEqualIID(riid,&IID_ITypeInfo2))
*ppvObject = This;
if(*ppvObject){
(*(LPTYPEINFO*)ppvObject)->lpvtbl->fnAddRef(iface);
TRACE_(typelib)("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
return S_OK;
}
TRACE_(typelib)("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/* ITypeInfo::AddRef
*/
static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO iface)
{
ICOM_THIS( TLBTypeInfo, iface);
TRACE_(typelib)("(%p)->ref is %u\n",This, This->ref);
(This->pTypeLib->ref)++;
return ++(This->ref);
}
/* ITypeInfo::Release
*/
static ULONG WINAPI ITypeInfo_fnRelease( LPTYPEINFO iface)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p)->ref is %u: stub\n",This, This->ref);
(This->ref)--;
(This->pTypeLib->ref)--;
return S_OK;
}
/* ITypeInfo::GetTypeAttr
*
* Retrieves a TYPEATTR structure that contains the attributes of the type
* description.
*
*/
static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( LPTYPEINFO iface,
LPTYPEATTR *ppTypeAttr)
{
ICOM_THIS( TLBTypeInfo, iface);
TRACE_(typelib)("(%p)\n",This);
/* FIXME: must do a copy here */
*ppTypeAttr=&This->TypeAttr;
return S_OK;
}
/* ITypeInfo::GetTypeComp
*
* Retrieves the ITypeComp interface for the type description, which enables a
* client compiler to bind to the type description's members.
*
*/
static HRESULT WINAPI ITypeInfo_fnGetTypeComp( LPTYPEINFO iface,
ITypeComp * *ppTComp)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!\n", This);
return S_OK;
}
/* ITypeInfo::GetFuncDesc
*
* Retrieves the FUNCDESC structure that contains information about a
* specified function.
*
*/
static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( LPTYPEINFO iface, UINT index,
LPFUNCDESC *ppFuncDesc)
{
ICOM_THIS( TLBTypeInfo, iface);
int i;
TLBFuncDesc * pFDesc;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
;
if(pFDesc){
/* FIXME: must do a copy here */
*ppFuncDesc=&pFDesc->funcdesc;
return S_OK;
}
return E_INVALIDARG;
}
/* ITypeInfo::GetVarDesc
*
* Retrieves a VARDESC structure that describes the specified variable.
*
*/
static HRESULT WINAPI ITypeInfo_fnGetVarDesc( LPTYPEINFO iface, UINT index,
LPVARDESC *ppVarDesc)
{
ICOM_THIS( TLBTypeInfo, iface);
int i;
TLBVarDesc * pVDesc;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
;
if(pVDesc){
/* FIXME: must do a copy here */
*ppVarDesc=&pVDesc->vardesc;
return S_OK;
}
return E_INVALIDARG;
}
/* ITypeInfo_GetNames
*
* Retrieves the variable with the specified member ID (or the name of the
* property or method and its parameters) that correspond to the specified
* function ID.
*/
static HRESULT WINAPI ITypeInfo_fnGetNames( LPTYPEINFO iface, MEMBERID memid,
BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBFuncDesc * pFDesc;
TLBVarDesc * pVDesc;
int i;
TRACE_(typelib)("(%p) memid=0x%08lx Maxname=%d\n", This, memid,
cMaxNames);
for(pFDesc=This->funclist; pFDesc->funcdesc.memid != memid && pFDesc;
pFDesc=pFDesc->next)
;
if(pFDesc){
/* function found, now return function and parameter names */
for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++){
if(!i) *rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
else
rgBstrNames[i]=TLB_DupAtoBstr(pFDesc->pParamDesc[i-1].Name);
}
*pcNames=i;
}else{
for(pVDesc=This->varlist; pVDesc->vardesc.memid != memid && pVDesc;
pVDesc=pVDesc->next)
;
if(pVDesc){
*rgBstrNames=TLB_DupAtoBstr(pFDesc->Name);
*pcNames=1;
}else{
if(This->TypeAttr.typekind==TKIND_INTERFACE &&
This->TypeAttr.cImplTypes ){
/* recursive search */
ITypeInfo *pTInfo;
HRESULT result;
result=This->lpvtbl->fnGetRefTypeInfo(iface,
This->impltypelist->reference, &pTInfo);
if(SUCCEEDED(result)){
result=pTInfo->lpvtbl->fnGetNames(pTInfo, memid, rgBstrNames,
cMaxNames, pcNames);
pTInfo->lpvtbl->fnRelease(pTInfo);
return result;
}
WARN_(typelib)("Could not search inherited interface!\n");
} else
WARN_(typelib)("no names found\n");
*pcNames=0;
return TYPE_E_ELEMENTNOTFOUND;
}
}
return S_OK;
}
/* ITypeInfo::GetRefTypeOfImplType
*
* If a type description describes a COM class, it retrieves the type
* description of the implemented interface types. For an interface,
* GetRefTypeOfImplType returns the type information for inherited interfaces,
* if any exist.
*
*/
static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( LPTYPEINFO iface,
UINT index, HREFTYPE *pRefType)
{
ICOM_THIS( TLBTypeInfo, iface);
int(i);
TLBRefType *pIref;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pIref=This->impltypelist; i<index && pIref;
i++, pIref=pIref->next)
;
if(i==index){
*pRefType=pIref->reference;
return S_OK;
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo::GetImplTypeFlags
*
* Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
* or base interface in a type description.
*/
static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( LPTYPEINFO iface,
UINT index, INT *pImplTypeFlags)
{
ICOM_THIS( TLBTypeInfo, iface);
int(i);
TLBRefType *pIref;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pIref=This->impltypelist; i<index && pIref; i++, pIref=pIref->next)
;
if(i==index && pIref){
*pImplTypeFlags=pIref->flags;
return S_OK;
}
*pImplTypeFlags=0;
return TYPE_E_ELEMENTNOTFOUND;
}
/* GetIDsOfNames
* Maps between member names and member IDs, and parameter names and
* parameter IDs.
*/
static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( LPTYPEINFO iface,
LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBFuncDesc * pFDesc;
TLBVarDesc * pVDesc;
HRESULT ret=S_OK;
PCHAR aszName= HEAP_strdupWtoA( GetProcessHeap(), 0, *rgszNames);
TRACE_(typelib)("(%p) Name %s cNames %d\n", This, debugstr_a(aszName),
cNames);
for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
int i, j;
if( !strcmp(aszName, pFDesc->Name)) {
if(cNames) *pMemId=pFDesc->funcdesc.memid;
for(i=1; i < cNames; i++){
PCHAR aszPar= HEAP_strdupWtoA( GetProcessHeap(), 0,
rgszNames[i]);
for(j=0; j<pFDesc->funcdesc.cParams; j++)
if(strcmp(aszPar,pFDesc->pParamDesc[j].Name))
break;
if( j<pFDesc->funcdesc.cParams)
pMemId[i]=j;
else
ret=DISP_E_UNKNOWNNAME;
HeapFree( GetProcessHeap(), 0, aszPar);
};
HeapFree (GetProcessHeap(), 0, aszName);
return ret;
}
}
for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
if( !strcmp(aszName, pVDesc->Name)) {
if(cNames) *pMemId=pVDesc->vardesc.memid;
HeapFree (GetProcessHeap(), 0, aszName);
return ret;
}
}
/* not found, see if this is and interface with an inheritance */
if(This->TypeAttr.typekind==TKIND_INTERFACE &&
This->TypeAttr.cImplTypes ){
/* recursive search */
ITypeInfo *pTInfo;
ret=This->lpvtbl->fnGetRefTypeInfo(iface,
This->impltypelist->reference, &pTInfo);
if(SUCCEEDED(ret)){
ret=pTInfo->lpvtbl->fnGetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
pTInfo->lpvtbl->fnRelease(pTInfo);
return ret;
}
WARN_(typelib)("Could not search inherited interface!\n");
} else
WARN_(typelib)("no names found\n");
return DISP_E_UNKNOWNNAME;
}
/* ITypeInfo::Invoke
*
* Invokes a method, or accesses a property of an object, that implements the
* interface described by the type description.
*/
static HRESULT WINAPI ITypeInfo_fnInvoke( LPTYPEINFO iface, VOID *pIUnk,
MEMBERID memid, UINT16 dwFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *pArgErr)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!", This);
return S_OK;
}
/* ITypeInfo::GetDocumentation
*
* Retrieves the documentation string, the complete Help file name and path,
* and the context ID for the Help topic for a specified type description.
*/
static HRESULT WINAPI ITypeInfo_fnGetDocumentation( LPTYPEINFO iface,
MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBFuncDesc * pFDesc;
TLBVarDesc * pVDesc;
TRACE_(typelib)("(%p) memid %ld Name(%p) DocString(%p)"
" HelpContext(%p) HelpFile(%p)\n",
This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
if(pBstrName)
*pBstrName=TLB_DupAtoBstr(This->Name);
if(pBstrDocString)
*pBstrDocString=TLB_DupAtoBstr(This->DocString);
if(pdwHelpContext)
*pdwHelpContext=This->dwHelpContext;
if(pBstrHelpFile)
*pBstrHelpFile=TLB_DupAtoBstr(This->DocString);/* FIXME */
return S_OK;
}else {/* for a member */
for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
if(pFDesc->funcdesc.memid==memid){
return S_OK;
}
for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
if(pVDesc->vardesc.memid==memid){
return S_OK;
}
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo::GetDllEntry
*
* Retrieves a description or specification of an entry point for a function
* in a DLL.
*/
static HRESULT WINAPI ITypeInfo_fnGetDllEntry( LPTYPEINFO iface, MEMBERID memid,
INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
WORD *pwOrdinal)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!\n", This);
return E_FAIL;
}
/* ITypeInfo::GetRefTypeInfo
*
* If a type description references other type descriptions, it retrieves
* the referenced type descriptions.
*/
static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( LPTYPEINFO iface,
HREFTYPE hRefType, ITypeInfo * *ppTInfo)
{
ICOM_THIS( TLBTypeInfo, iface);
HRESULT result;
if(HREFTYPE_INTHISFILE(hRefType)){
ITypeLib *pTLib;
int Index;
result=This->lpvtbl->fnGetContainingTypeLib(iface, &pTLib,
&Index);
if(SUCCEEDED(result)){
result=pTLib->lpvtbl->fnGetTypeInfo(pTLib,
HREFTYPE_INDEX(hRefType),
ppTInfo);
pTLib->lpvtbl->fnRelease(pTLib );
}
} else{
/* imported type lib */
TLBRefType * pRefType;
TLBLibInfo *pTypeLib;
for( pRefType=This->impltypelist; pRefType &&
pRefType->reference != hRefType; pRefType=pRefType->next)
;
if(!pRefType)
return TYPE_E_ELEMENTNOTFOUND; /* FIXME : correct? */
pTypeLib=pRefType->pImpTLInfo->pImpTypeLib;
if(pTypeLib) /* typelib already loaded */
result=pTypeLib->lpvtbl->fnGetTypeInfoOfGuid(
(LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
else{
result=LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
0,0,0, /* FIXME */
(LPTYPELIB *)&pTypeLib);
if(!SUCCEEDED(result)){
BSTR libnam=TLB_DupAtoBstr(pRefType->pImpTLInfo->name);
result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib);
SysFreeString(libnam);
}
if(SUCCEEDED(result)){
result=pTypeLib->lpvtbl->fnGetTypeInfoOfGuid(
(LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo);
pRefType->pImpTLInfo->pImpTypeLib=pTypeLib;
}
}
}
TRACE_(typelib)("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
return result;
}
/* ITypeInfo::AddressOfMember
*
* Retrieves the addresses of static functions or variables, such as those
* defined in a DLL.
*/
static HRESULT WINAPI ITypeInfo_fnAddressOfMember( LPTYPEINFO iface,
MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!\n", This);
return S_OK;
}
/* ITypeInfo::CreateInstance
*
* Creates a new instance of a type that describes a component object class
* (coclass).
*/
static HRESULT WINAPI ITypeInfo_fnCreateInstance( LPTYPEINFO iface,
IUnknown *pUnk, REFIID riid, VOID **ppvObj)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!\n", This);
return S_OK;
}
/* ITypeInfo::GetMops
*
* Retrieves marshaling information.
*/
static HRESULT WINAPI ITypeInfo_fnGetMops( LPTYPEINFO iface, MEMBERID memid,
BSTR *pBstrMops)
{
ICOM_THIS( TLBTypeInfo, iface);
FIXME_(typelib)("(%p) stub!\n", This);
return S_OK;
}
/* ITypeInfo::GetContainingTypeLib
*
* Retrieves the containing type library and the index of the type description
* within that type library.
*/
static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( LPTYPEINFO iface,
ITypeLib * *ppTLib, UINT *pIndex)
{
ICOM_THIS( TLBTypeInfo, iface);
*ppTLib=(LPTYPELIB )(This->pTypeLib);
*pIndex=This->index;
(*ppTLib)->lpvtbl->fnAddRef(*ppTLib);
TRACE_(typelib)("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
return S_OK;
}
/* ITypeInfo::ReleaseTypeAttr
*
* Releases a TYPEATTR previously returned by GetTypeAttr.
*
*/
static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( LPTYPEINFO iface,
TYPEATTR* pTypeAttr)
{
ICOM_THIS( TLBTypeInfo, iface);
TRACE_(typelib)("(%p)->(%p)\n", This, pTypeAttr);
return S_OK;
}
/* ITypeInfo::ReleaseFuncDesc
*
* Releases a FUNCDESC previously returned by GetFuncDesc. *
*/
static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc( LPTYPEINFO iface,
FUNCDESC *pFuncDesc)
{
ICOM_THIS( TLBTypeInfo, iface);
TRACE_(typelib)("(%p)->(%p)\n", This, pFuncDesc);
return S_OK;
}
/* ITypeInfo::ReleaseVarDesc
*
* Releases a VARDESC previously returned by GetVarDesc.
*/
static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( LPTYPEINFO iface,
VARDESC *pVarDesc)
{
ICOM_THIS( TLBTypeInfo, iface);
TRACE_(typelib)("(%p)->(%p)\n", This, pVarDesc);
return S_OK;
}
/* ITypeInfo2::GetTypeKind
*
* Returns the TYPEKIND enumeration quickly, without doing any allocations.
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo * iface,
TYPEKIND *pTypeKind)
{
ICOM_THIS( TLBTypeInfo, iface);
*pTypeKind=This->TypeAttr.typekind;
TRACE_(typelib)("(%p) type 0x%0x\n", This,*pTypeKind);
return S_OK;
}
/* ITypeInfo2::GetTypeFlags
*
* Returns the type flags without any allocations. This returns a DWORD type
* flag, which expands the type flags without growing the TYPEATTR (type
* attribute).
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo * iface,
UINT *pTypeFlags)
{
ICOM_THIS( TLBTypeInfo, iface);
*pTypeFlags=This->TypeAttr.wTypeFlags;
TRACE_(typelib)("(%p) flags 0x%04x\n", This,*pTypeFlags);
return S_OK;
}
/* ITypeInfo2::GetFuncIndexOfMemId
* Binds to a specific member based on a known DISPID, where the member name
* is not known (for example, when binding to a default member).
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo * iface,
MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBFuncDesc *pFuncInfo;
int i;
HRESULT result;
/* FIXME: should check for invKind??? */
for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
if(pFuncInfo){
*pFuncIndex=i;
result= S_OK;
}else{
*pFuncIndex=0;
result=E_INVALIDARG;
}
TRACE_(typelib)("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
return result;
}
/* TypeInfo2::GetVarIndexOfMemId
*
* Binds to a specific member based on a known DISPID, where the member name
* is not known (for example, when binding to a default member).
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo * iface,
MEMBERID memid, UINT *pVarIndex)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBVarDesc *pVarInfo;
int i;
HRESULT result;
for(i=0, pVarInfo=This->varlist; pVarInfo &&
memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
;
if(pVarInfo){
*pVarIndex=i;
result= S_OK;
}else{
*pVarIndex=0;
result=E_INVALIDARG;
}
TRACE_(typelib)("(%p) memid 0x%08lx -> %s\n", This,
memid, SUCCEEDED(result)? "SUCCES":"FAILED");
return result;
}
/* ITypeInfo2::GetCustData
*
* Gets the custom data
*/
static HRESULT WINAPI ITypeInfo2_fnGetCustData( ITypeInfo * iface,
REFGUID guid, VARIANT *pVarVal)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData;
for(pCData=This->pCustData; pCData; pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n", This, xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeInfo2::GetFuncCustData
*
* Gets the custom data
*/
static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData( ITypeInfo * iface,
UINT index, REFGUID guid, VARIANT *pVarVal)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData=NULL;
TLBFuncDesc * pFDesc;
int i;
for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
pFDesc=pFDesc->next)
;
if(pFDesc)
for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n",This,xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeInfo2::GetParamCustData
*
* Gets the custom data
*/
static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( ITypeInfo * iface,
UINT indexFunc, UINT indexParam, REFGUID guid, VARIANT *pVarVal)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData=NULL;
TLBFuncDesc * pFDesc;
int i;
for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
pFDesc=pFDesc->next)
;
if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n",This,xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeInfo2::GetVarcCustData
*
* Gets the custom data
*/
static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( ITypeInfo * iface,
UINT index, REFGUID guid, VARIANT *pVarVal)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData=NULL;
TLBVarDesc * pVDesc;
int i;
for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
pVDesc=pVDesc->next)
;
if(pVDesc)
for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n",This,xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeInfo2::GetImplcCustData
*
* Gets the custom data
*/
static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( ITypeInfo * iface,
UINT index, REFGUID guid, VARIANT *pVarVal)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData=NULL;
TLBRefType * pRDesc;
int i;
for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
pRDesc=pRDesc->next)
;
if(pRDesc)
for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
if( IsEqualIID(guid, &pCData->guid)) break;
if(TRACE_ON(typelib)){
char xriid[50];
WINE_StringFromCLSID((LPCLSID)guid,xriid);
TRACE_(typelib)("(%p) guid %s %s found!x)\n",This,xriid,
pCData? "" : "NOT");
}
if(pCData){
VariantInit( pVarVal);
VariantCopy( pVarVal, &pCData->data);
return S_OK;
}
return E_INVALIDARG; /* FIXME: correct? */
}
/* ITypeInfo2::GetDocumentation2
*
* Retrieves the documentation string, the complete Help file name and path,
* the localization context to use, and the context ID for the library Help
* topic in the Help file.
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2( ITypeInfo * iface,
MEMBERID memid, LCID lcid, BSTR *pbstrHelpString,
INT *pdwHelpStringContext, BSTR *pbstrHelpStringDll)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBFuncDesc * pFDesc;
TLBVarDesc * pVDesc;
TRACE_(typelib)("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
"HelpStringContext(%p) HelpStringDll(%p)\n",
This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
pbstrHelpStringDll );
/* the help string should be obtained from the helpstringdll,
* using the _DLLGetDocumentation function, based on the supplied
* lcid. Nice to do sometime...
*/
if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
if(pbstrHelpString)
*pbstrHelpString=TLB_DupAtoBstr(This->Name);
if(pdwHelpStringContext)
*pdwHelpStringContext=This->dwHelpStringContext;
if(pbstrHelpStringDll)
*pbstrHelpStringDll=
TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
return S_OK;
}else {/* for a member */
for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
if(pFDesc->funcdesc.memid==memid){
if(pbstrHelpString)
*pbstrHelpString=TLB_DupAtoBstr(pFDesc->HelpString);
if(pdwHelpStringContext)
*pdwHelpStringContext=pFDesc->HelpStringContext;
if(pbstrHelpStringDll)
*pbstrHelpStringDll=
TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
return S_OK;
}
for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
if(pVDesc->vardesc.memid==memid){
if(pbstrHelpString)
*pbstrHelpString=TLB_DupAtoBstr(pVDesc->HelpString);
if(pdwHelpStringContext)
*pdwHelpStringContext=pVDesc->HelpStringContext;
if(pbstrHelpStringDll)
*pbstrHelpStringDll=
TLB_DupAtoBstr(This->pTypeLib->HelpStringDll);/* FIXME */
return S_OK;
}
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo2::GetAllCustData
*
* Gets all custom data items for the Type info.
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetAllCustData( ITypeInfo * iface,
CUSTDATA *pCustData)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData;
int i;
TRACE_(typelib)("(%p) returning %d items\n", This, This->ctCustData);
pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=This->ctCustData;
for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
/* ITypeInfo2::GetAllFuncCustData
*
* Gets all custom data items for the specified Function
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData( ITypeInfo * iface,
UINT index, CUSTDATA *pCustData)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData;
TLBFuncDesc * pFDesc;
int i;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
pFDesc=pFDesc->next)
;
if(pFDesc){
pCustData->prgCustData =
TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=pFDesc->ctCustData;
for(i=0, pCData=pFDesc->pCustData; pCData; i++,
pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue,
& pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo2::GetAllParamCustData
*
* Gets all custom data items for the Functions
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo * iface,
UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData=NULL;
TLBFuncDesc * pFDesc;
int i;
TRACE_(typelib)("(%p) index %d\n", This, indexFunc);
for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
pFDesc=pFDesc->next)
;
if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
pCustData->prgCustData =
TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
pCData; i++, pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue,
& pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo2::GetAllVarCustData
*
* Gets all custom data items for the specified Variable
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo * iface,
UINT index, CUSTDATA *pCustData)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData;
TLBVarDesc * pVDesc;
int i;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
pVDesc=pVDesc->next)
;
if(pVDesc){
pCustData->prgCustData =
TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=pVDesc->ctCustData;
for(i=0, pCData=pVDesc->pCustData; pCData; i++,
pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue,
& pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
return TYPE_E_ELEMENTNOTFOUND;
}
/* ITypeInfo2::GetAllImplCustData
*
* Gets all custom data items for the specified implementation type
*
*/
static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( ITypeInfo * iface,
UINT index, CUSTDATA *pCustData)
{
ICOM_THIS( TLBTypeInfo, iface);
TLBCustData *pCData;
TLBRefType * pRDesc;
int i;
TRACE_(typelib)("(%p) index %d\n", This, index);
for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
pRDesc=pRDesc->next)
;
if(pRDesc){
pCustData->prgCustData =
TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
if(pCustData->prgCustData ){
pCustData->cCustData=pRDesc->ctCustData;
for(i=0, pCData=pRDesc->pCustData; pCData; i++,
pCData = pCData->next){
pCustData->prgCustData[i].guid=pCData->guid;
VariantCopy(& pCustData->prgCustData[i].varValue,
& pCData->data);
}
}else{
ERR_(typelib)(" OUT OF MEMORY! \n");
return E_OUTOFMEMORY;
}
return S_OK;
}
return TYPE_E_ELEMENTNOTFOUND;
}