From 0d969c704363a7108564f7e9603c9c0978173213 Mon Sep 17 00:00:00 2001 From: Huw D M Davies Date: Fri, 7 Sep 2001 15:27:16 +0000 Subject: [PATCH] Add reader for v1 (SLTG) typelibs. Fix a few problems with v2 (MSFT) typelibs. LoadTypeLibEx should do a SearchPath to locate typelib. --- dlls/oleaut32/typelib.c | 1578 ++++++++++++++++++++++++++++++--------- dlls/oleaut32/typelib.h | 371 +++++++-- 2 files changed, 1552 insertions(+), 397 deletions(-) diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 9ce5a2481ce..c207ae5721f 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -4,6 +4,8 @@ * Copyright 1997 Marcus Meissner * 1999 Rein Klazes * 2000 Francois Jacques + * 2001 Huw D M Davies for CodeWeavers + * * -------------------------------------------------------------------------------------- * Known problems (2000, Francois Jacques) * @@ -17,17 +19,12 @@ * * - locale stuff is partially implemented but hasn't been tested. * - * - imported typelib should be stored together in a linked list instead of having - * independant TLBImpLib structures in each ITypeInfo. This way, imported libraries - * are just imported once (major optimization) - * - * - typelib file is still read it's in entirety, but it is released now. - * - some garbage is read from function names on some very rare occasion + * - typelib file is still read in its entirety, but it is released now. + * - some garbage is read from function names on some very rare occasions. * * -------------------------------------------------------------------------------------- * Known problems left from previous implementation (1999, Rein Klazes) : * - * -. Only one format of typelibs is supported * -. Data structures are straightforward, but slow for look-ups. * -. (related) nothing is hashed * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most @@ -262,20 +259,24 @@ HRESULT WINAPI LoadTypeLibEx( REGKIND regkind, /* [in] Specify kind of registration */ ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ { - LPSTR p; + LPSTR p=NULL; + WCHAR szPath[MAX_PATH+1]; HRESULT res; TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); - p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile); - - res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib); - + if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,NULL)) + res = TYPE_E_CANTLOADLIBRARY; + else { + p=HEAP_strdupWtoA(GetProcessHeap(),0,szPath); + res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib); + } if (SUCCEEDED(res)) switch(regkind) { case REGKIND_DEFAULT: /* FIXME: is this correct? */ - if (!p || !p[0] || (p[0] != '\\' && p[0] != '/' && p[1] != ':')) + if (!szFile || !szFile[0] || + (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':')) break; /* else fall-through */ case REGKIND_REGISTER: @@ -290,7 +291,7 @@ HRESULT WINAPI LoadTypeLibEx( break; } - HeapFree(GetProcessHeap(),0,p); + if(p) HeapFree(GetProcessHeap(),0,p); TRACE(" returns %08lx\n",res); return res; } @@ -479,16 +480,20 @@ typedef struct tagTLBCustData /* data structure for import typelibs */ typedef struct tagTLBImpLib { - int offset; /* offset in the file */ + int offset; /* offset in the file (MSFT) + offset in nametable (SLTG) + just used to identify library while reading + data from file */ GUID guid; /* libid */ - BSTR name; /* name; */ + BSTR name; /* name */ - LCID lcid; /* lcid of imported typelib */ + LCID lcid; /* lcid of imported typelib */ - WORD wVersionMajor; /* major version number */ + WORD wVersionMajor; /* major version number */ WORD wVersionMinor; /* minor version number */ - struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib */ + struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or + NULL if not yet loaded */ struct tagTLBImpLib * next; } TLBImpLib; @@ -500,9 +505,9 @@ typedef struct tagITypeLibImpl TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */ /* strings can be stored in tlb as multibyte strings BUT they are *always* - * exported to the application as a UNICODE string. - */ - BSTR Name; + * exported to the application as a UNICODE string. + */ + BSTR Name; BSTR DocString; BSTR HelpFile; BSTR HelpStringDll; @@ -510,38 +515,50 @@ typedef struct tagITypeLibImpl int TypeInfoCount; /* nr of typeinfo's in librarry */ struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */ int ctCustData; /* number of items in cust data list */ - TLBCustData * pCustData; /* linked list to cust data; */ + TLBCustData * pCustData; /* linked list to cust data */ TLBImpLib * pImpLibs; /* linked list to all imported typelibs */ - TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the libary */ + TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the + libary. Only used while read MSFT + typelibs */ } ITypeLibImpl; static struct ICOM_VTABLE(ITypeLib2) tlbvt; /* ITypeLib methods */ -static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength); +static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength); +static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength); /*======================= ITypeInfo implementation =======================*/ -/* data for refernced types in a coclass, or an inherited interface */ +/* data for refernced types */ typedef struct tagTLBRefType { + INT index; /* Type index for internal ref or for external ref + it the format is SLTG. -2 indicates to + use guid */ + GUID guid; /* guid of the referenced type */ - /* (important if its a imported type) */ - HREFTYPE reference; - int flags; - int ctCustData; - TLBCustData * pCustData;/* linked list to custom data; */ - TLBImpLib *pImpTLInfo; + /* if index == TLB_REF_USE_GUID */ + + HREFTYPE reference; /* The href of this ref */ + TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data + TLB_REF_INTERNAL for internal refs + TLB_REF_NOT_FOUND for broken refs */ + struct tagTLBRefType * next; } TLBRefType; +#define TLB_REF_USE_GUID -2 + +#define TLB_REF_INTERNAL (void*)-2 +#define TLB_REF_NOT_FOUND (void*)-1 + /* internal Parameter data */ typedef struct tagTLBParDesc { BSTR Name; int ctCustData; - TLBCustData * pCustData; /* linked list to cust data; */ - TLBRefType * pRefType; /* linked list to referenced types */ + TLBCustData * pCustData; /* linked list to cust data */ } TLBParDesc; /* internal Function data */ @@ -549,7 +566,7 @@ typedef struct tagTLBFuncDesc { FUNCDESC funcdesc; /* lots of info on the function and its attributes. */ BSTR Name; /* the name of this function */ - TLBParDesc *pParamDesc; /* array with name and custom data */ + TLBParDesc *pParamDesc; /* array with param names and custom data */ int helpcontext; int HelpStringContext; BSTR HelpString; @@ -572,6 +589,16 @@ typedef struct tagTLBVarDesc struct tagTLBVarDesc * next; } TLBVarDesc; +/* internal implemented interface data */ +typedef struct tagTLBImplType +{ + HREFTYPE hRef; /* hRef of interface */ + int implflags; /* IMPLFLAG_*s */ + int ctCustData; + TLBCustData * pCustData;/* linked list to custom data; */ + struct tagTLBImplType *next; +} TLBImplType; + /* internal TypeInfo data */ typedef struct tagITypeInfoImpl { @@ -595,7 +622,9 @@ typedef struct tagITypeInfoImpl TLBVarDesc * varlist; /* linked list with variable descriptions */ /* Implemented Interfaces */ - TLBRefType * impltypelist; + TLBImplType * impltypelist; + + TLBRefType * reflist; int ctCustData; TLBCustData * pCustData; /* linked list to cust data; */ struct tagITypeInfoImpl * next; @@ -611,12 +640,12 @@ typedef struct tagTLBContext unsigned int pos; /* current pos */ unsigned int length; /* total length */ void *mapping; /* memory mapping */ - TLBSegDir * pTblDir; + MSFT_SegDir * pTblDir; ITypeLibImpl* pLibInfo; } TLBContext; -static void TLB_DoRefType(TLBContext *pcx, int offset, TLBRefType ** pprtd); +static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset); /* debug @@ -639,26 +668,69 @@ static void dump_VarType(VARTYPE vt,char *szVarType) { case VT_BYREF: case VT_UNKNOWN: sprintf(szVarType, "VT_BYREF"); break; case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break; case VT_ARRAY: sprintf(szVarType, "VT_ARRAY"); break; - case VT_I1: sprintf(szVarType, "VT_I2"); break; + case VT_I1: sprintf(szVarType, "VT_I1"); break; case VT_UI2: sprintf(szVarType, "VT_UI2"); break; case VT_UI4: sprintf(szVarType, "VT_UI4"); break; case VT_INT: sprintf(szVarType, "VT_INT"); break; case VT_UINT: sprintf(szVarType, "VT_UINT"); break; + case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break; default: sprintf(szVarType, "unknown");break; } } + +static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) { + switch(pTD->vt) { + case VT_UI1: sprintf(szVarType, "VT_UI1"); break; + case VT_I2: sprintf(szVarType, "VT_I2"); break; + case VT_I4: sprintf(szVarType, "VT_I4"); break; + case VT_R4: sprintf(szVarType, "VT_R4"); break; + case VT_R8: sprintf(szVarType, "VT_R8"); break; + case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break; + case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break; + case VT_CY: sprintf(szVarType, "VT_CY"); break; + case VT_DATE: sprintf(szVarType, "VT_DATE"); break; + case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break; + case VT_BYREF: case VT_UNKNOWN: sprintf(szVarType, "VT_BYREF"); break; + case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break; + case VT_ARRAY: sprintf(szVarType, "VT_ARRAY"); break; + case VT_I1: sprintf(szVarType, "VT_I1"); break; + case VT_UI2: sprintf(szVarType, "VT_UI2"); break; + case VT_UI4: sprintf(szVarType, "VT_UI4"); break; + case VT_INT: sprintf(szVarType, "VT_INT"); break; + case VT_UINT: sprintf(szVarType, "VT_UINT"); break; + case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break; + case VT_VOID: sprintf(szVarType, "VT_VOID"); break; + case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx", + pTD->u.hreftype); break; + case VT_PTR: sprintf(szVarType, "ptr to "); + dump_TypeDesc(pTD->u.lptdesc, szVarType + 7); + break; + case VT_SAFEARRAY: sprintf(szVarType, "safearray of "); + dump_TypeDesc(pTD->u.lptdesc, szVarType + 13); + break; + case VT_CARRAY: sprintf(szVarType, "%d dim array of ", + pTD->u.lpadesc->cDims); /* FIXME print out sizes */ + dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType)); + break; + + default: sprintf(szVarType, "unknown");break; + } +} + static void dump_ELEMDESC(ELEMDESC *edesc) { char buf[200]; - dump_VarType(edesc->tdesc.vt,buf); + dump_TypeDesc(&edesc->tdesc,buf); MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf); MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags); MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex); } static void dump_FUNCDESC(FUNCDESC *funcdesc) { int i; - MESSAGE("memid is %d\n",(int)funcdesc->memid); - for (i=0;icParams;i++) - MESSAGE("Param %d:\n",i);dump_ELEMDESC(funcdesc->lprgelemdescParam+i); + MESSAGE("memid is %08lx\n",funcdesc->memid); + for (i=0;icParams;i++) { + MESSAGE("Param %d:\n",i); + dump_ELEMDESC(funcdesc->lprgelemdescParam+i); + } MESSAGE("\tfunckind: %d (",funcdesc->funckind); switch (funcdesc->funckind) { case FUNC_VIRTUAL: MESSAGE("virtual");break; @@ -718,16 +790,44 @@ static void dump_TLBVarDesc(TLBVarDesc * pvd) pvd = pvd->next; }; } + +static void dump_TLBImpLib(TLBImpLib *import) +{ + TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)), + debugstr_w(import->name)); + TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor, + import->wVersionMinor, import->lcid, import->offset); +} + static void dump_TLBRefType(TLBRefType * prt) { while (prt) { - TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid))); - TRACE_(typelib)(" href:0x%08lx\n", prt->reference); + TRACE_(typelib)("href:0x%08lx\n", prt->reference); + if(prt->index == -1) + TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid))); + else + TRACE_(typelib)("type no: %d\n", prt->index); + + if(prt->pImpTLInfo != TLB_REF_INTERNAL && + prt->pImpTLInfo != TLB_REF_NOT_FOUND) { + TRACE_(typelib)("in lib\n"); + dump_TLBImpLib(prt->pImpTLInfo); + } prt = prt->next; }; } +static void dump_TLBImplType(TLBImplType * impl) +{ + while (impl) { + TRACE_(typelib)( + "implementing/inheriting interface hRef = %lx implflags %x\n", + impl->hRef, impl->implflags); + impl = impl->next; + } +} + static void dump_Variant(VARIANT * pvar) { char szVarType[15]; @@ -801,7 +901,7 @@ static void dump_TypeInfo(ITypeInfoImpl * pty) TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString)); dump_TLBFuncDesc(pty->funclist); dump_TLBVarDesc(pty->varlist); - dump_TLBRefType(pty->impltypelist); + dump_TLBImplType(pty->impltypelist); } static TYPEDESC stndTypeDesc[VT_LPWSTR+1]= @@ -835,8 +935,14 @@ static void TLB_Free(void * ptr) { HeapFree(GetProcessHeap(), 0, ptr); } + + +/********************************************************************** + * + * Functions for reading MSFT typelibs (those created by CreateTypeLib2) + */ /* read function */ -DWORD TLB_Read(void *buffer, DWORD count, TLBContext *pcx, long where ) +DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where ) { TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n", pcx->pos, count, pcx->oStart, pcx->length, where); @@ -858,7 +964,7 @@ DWORD TLB_Read(void *buffer, DWORD count, TLBContext *pcx, long where ) return count; } -static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) +static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) { TRACE_(typelib)("%s\n", debugstr_guid(pGuid)); @@ -866,22 +972,22 @@ static void TLB_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) memset(pGuid,0, sizeof(GUID)); return; } - TLB_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset ); + MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset ); } -BSTR TLB_ReadName( TLBContext *pcx, int offset) +BSTR MSFT_ReadName( TLBContext *pcx, int offset) { char * name; - TLBNameIntro niName; + MSFT_NameIntro niName; int lengthInChars; WCHAR* pwstring = NULL; BSTR bstrName = NULL; - TLB_Read(&niName, sizeof(niName), pcx, + MSFT_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); + MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK); name[niName.namelen & 0xff]='\0'; lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, @@ -904,7 +1010,7 @@ BSTR TLB_ReadName( TLBContext *pcx, int offset) return bstrName; } -BSTR TLB_ReadString( TLBContext *pcx, int offset) +BSTR MSFT_ReadString( TLBContext *pcx, int offset) { char * string; INT16 length; @@ -912,10 +1018,10 @@ BSTR TLB_ReadString( TLBContext *pcx, int offset) BSTR bstr = NULL; if(offset<0) return NULL; - TLB_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset); + MSFT_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); + MSFT_Read(string, length, pcx, DO_NOT_SEEK); string[length]='\0'; lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS, @@ -940,18 +1046,18 @@ BSTR TLB_ReadString( TLBContext *pcx, int offset) /* * read a value and fill a VARIANT structure */ -static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) +static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) { int size; TRACE_(typelib)("\n"); - if(offset <0) { /* data is packed in here */ + if(offset <0) { /* data are packed in here */ V_VT(pVar) = (offset & 0x7c000000 )>> 26; V_UNION(pVar, iVal) = offset & 0xffff; return; } - TLB_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx, + MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx, pcx->pTblDir->pCustData.offset + offset ); TRACE_(typelib)("Vartype = %x\n", V_VT(pVar)); switch (V_VT(pVar)){ @@ -982,12 +1088,12 @@ static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) /* pointer types with known behaviour */ case VT_BSTR :{ char * ptr; - TLB_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK ); + MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK ); if(size <= 0) { FIXME("BSTR length = %d?\n", size); } else { ptr=TLB_Alloc(size);/* allocate temp buffer */ - TLB_Read(ptr, size, pcx, DO_NOT_SEEK); /* read string (ANSI) */ + MSFT_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'; @@ -1021,15 +1127,15 @@ static void TLB_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) } if(size>0) /* (big|small) endian correct? */ - TLB_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK ); + MSFT_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 ) +static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData ) { - TLBCDGuid entry; + MSFT_CDGuid entry; TLBCustData* pNew; int count=0; @@ -1038,10 +1144,10 @@ static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData ) while(offset >=0){ count++; pNew=TLB_Alloc(sizeof(TLBCustData)); - TLB_Read(&entry, sizeof(entry), pcx, + MSFT_Read(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset); - TLB_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx); - TLB_ReadValue(&(pNew->data), entry.DataOffset, pcx); + MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx); + MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx); /* add new custom data at head of the list */ pNew->next=*ppCustData; *ppCustData=pNew; @@ -1050,18 +1156,23 @@ static int TLB_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData ) return count; } -static void TLB_GetTdesc(TLBContext *pcx, INT type,TYPEDESC * pTd ) +static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd, + ITypeInfoImpl *pTI) { if(type <0) pTd->vt=type & VT_TYPEMASK; else *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))]; + if(pTd->vt == VT_USERDEFINED) + MSFT_DoRefType(pcx, pTI, pTd->u.hreftype); + TRACE_(typelib)("vt type = %X\n", pTd->vt); } static void -TLB_DoFuncs(TLBContext* pcx, +MSFT_DoFuncs(TLBContext* pcx, + ITypeInfoImpl* pTI, int cFuncs, int cVars, int offset, @@ -1096,30 +1207,30 @@ TLB_DoFuncs(TLBContext* pcx, int recoffset = offset + sizeof(INT); char recbuf[512]; - TLBFuncRecord * pFuncRec=(TLBFuncRecord *) recbuf; + MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf; TRACE_(typelib)("\n"); - TLB_Read(&infolen, sizeof(INT), pcx, offset); + MSFT_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, + MSFT_Read(&nameoffset, sizeof(INT), pcx, offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT)); - (*pptfd)->Name = TLB_ReadName(pcx, nameoffset); + (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset); /* read the function information record */ - TLB_Read(&reclength, sizeof(INT), pcx, recoffset); + MSFT_Read(&reclength, sizeof(INT), pcx, recoffset); reclength &= 0x1ff; - TLB_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; + MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; /* do the attributes */ nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18) @@ -1131,7 +1242,7 @@ TLB_DoFuncs(TLBContext* pcx, if ( nrattributes > 1 ) { - (*pptfd)->HelpString = TLB_ReadString(pcx, + (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->OptAttr[1]) ; if ( nrattributes > 2 ) @@ -1142,7 +1253,7 @@ TLB_DoFuncs(TLBContext* pcx, } else { - (*pptfd)->Entry = TLB_ReadString(pcx, + (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->OptAttr[2]); } if( nrattributes > 5 ) @@ -1151,9 +1262,9 @@ TLB_DoFuncs(TLBContext* pcx, if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 ) { - TLB_CustData(pcx, - pFuncRec->OptAttr[6], - &(*pptfd)->pCustData); + MSFT_CustData(pcx, + pFuncRec->OptAttr[6], + &(*pptfd)->pCustData); } } } @@ -1161,7 +1272,7 @@ TLB_DoFuncs(TLBContext* pcx, } /* fill the FuncDesc Structure */ - TLB_Read( & (*pptfd)->funcdesc.memid, + MSFT_Read( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx, offset + infolen + ( i + 1) * sizeof(INT)); @@ -1173,15 +1284,16 @@ TLB_DoFuncs(TLBContext* pcx, (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ; (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ; - TLB_GetTdesc(pcx, - pFuncRec->DataType, - &(*pptfd)->funcdesc.elemdescFunc.tdesc) ; + MSFT_GetTdesc(pcx, + pFuncRec->DataType, + &(*pptfd)->funcdesc.elemdescFunc.tdesc, + pTI); /* do the parameters/arguments */ if(pFuncRec->nrargs) { int j = 0; - TLBParameterInfo paraminfo; + MSFT_ParameterInfo paraminfo; (*pptfd)->funcdesc.lprgelemdescParam = TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC)); @@ -1189,19 +1301,20 @@ TLB_DoFuncs(TLBContext* pcx, (*pptfd)->pParamDesc = TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc)); - TLB_Read(¶minfo, - sizeof(paraminfo), - pcx, - recoffset + reclength - - pFuncRec->nrargs * sizeof(TLBParameterInfo)); + MSFT_Read(¶minfo, + sizeof(paraminfo), + pcx, + recoffset + reclength - + pFuncRec->nrargs * sizeof(MSFT_ParameterInfo)); for ( j = 0 ; j < pFuncRec->nrargs ; j++ ) { TYPEDESC* lpArgTypeDesc = 0; - TLB_GetTdesc(pcx, - paraminfo.DataType, - &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc) ; + MSFT_GetTdesc(pcx, + paraminfo.DataType, + &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc, + pTI); (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags; @@ -1211,10 +1324,10 @@ TLB_DoFuncs(TLBContext* pcx, * from there jump to the end of record, * go back by (j-1) arguments */ - TLB_Read( ¶minfo , - sizeof(TLBParameterInfo), pcx, - recoffset + reclength - ((pFuncRec->nrargs - j - 1) - * sizeof(TLBParameterInfo))); + MSFT_Read( ¶minfo , + sizeof(MSFT_ParameterInfo), pcx, + recoffset + reclength - ((pFuncRec->nrargs - j - 1) + * sizeof(MSFT_ParameterInfo))); lpArgTypeDesc = & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc); @@ -1231,12 +1344,8 @@ TLB_DoFuncs(TLBContext* pcx, break; case VT_USERDEFINED: - (*pptfd)->pParamDesc[j].pRefType = - TLB_Alloc(sizeof(TLBRefType)); - - TLB_DoRefType(pcx, - lpArgTypeDesc->u.hreftype, - & ( (*pptfd)->pParamDesc[j].pRefType )); + MSFT_DoRefType(pcx, pTI, + lpArgTypeDesc->u.hreftype); lpArgTypeDesc = NULL; break; @@ -1272,12 +1381,9 @@ TLB_DoFuncs(TLBContext* pcx, break; case VT_USERDEFINED: - (*pptfd)->pParamDesc[j].pRefType - = TLB_Alloc(sizeof(TLBRefType)); - - TLB_DoRefType(pcx, - lpArgTypeDesc->u.hreftype, - &((*pptfd)->pParamDesc[j].pRefType)); + MSFT_DoRefType(pcx, + pTI, + lpArgTypeDesc->u.hreftype); lpArgTypeDesc = NULL; break; @@ -1293,7 +1399,7 @@ TLB_DoFuncs(TLBContext* pcx, { /* name */ (*pptfd)->pParamDesc[j].Name = - TLB_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name ); + MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name ); /* default value */ if ( (PARAMFLAG_FHASDEFAULT & @@ -1309,15 +1415,15 @@ TLB_DoFuncs(TLBContext* pcx, pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX)); pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX); - TLB_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), + MSFT_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); + MSFT_CustData(pcx, + pFuncRec->OptAttr[7+j], + &(*pptfd)->pParamDesc[j].pCustData); } } } @@ -1330,50 +1436,50 @@ TLB_DoFuncs(TLBContext* pcx, recoffset += reclength; } } -static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars, - int offset, TLBVarDesc ** pptvd) +static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, + int cVars, int offset, TLBVarDesc ** pptvd) { int infolen, nameoffset, reclength; char recbuf[256]; - TLBVarRecord * pVarRec=(TLBVarRecord *) recbuf; + MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf; int i; int recoffset; TRACE_(typelib)("\n"); - TLB_Read(&infolen,sizeof(INT), pcx, offset); - TLB_Read(&recoffset,sizeof(INT), pcx, offset + infolen + + MSFT_Read(&infolen,sizeof(INT), pcx, offset); + MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen + ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT)); recoffset += offset+sizeof(INT); for(i=0;iName=TLB_ReadName(pcx, nameoffset); + (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset); /* read the variable information record */ - TLB_Read(&reclength, sizeof(INT), pcx, recoffset); + MSFT_Read(&reclength, sizeof(INT), pcx, recoffset); reclength &=0xff; - TLB_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ; + MSFT_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) ; + (*pptvd)->HelpString = MSFT_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, + MSFT_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) ; + MSFT_GetTdesc(pcx, pVarRec->DataType, + &(*pptvd)->vardesc.elemdescVar.tdesc, pTI); /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */ if(pVarRec->VarKind == VAR_CONST ){ (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT)); - TLB_ReadValue((*pptvd)->vardesc.u.lpvarValue, + MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue, pVarRec->OffsValue, pcx); } else (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue; @@ -1382,81 +1488,95 @@ static void TLB_DoVars(TLBContext *pcx, int cFuncs, int cVars, } } /* 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 from import, its an offset+1 in the ImpInfo table + * in the typelib, it's just an (file) offset in the type info base dir. + * If comes from import, it's an offset+1 in the ImpInfo table * */ -static void TLB_DoRefType(TLBContext *pcx, - int offset, TLBRefType ** pprtd) +static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, + int offset) { int j; + TLBRefType **ppRefType = &pTI->reflist; TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset); - if(!HREFTYPE_INTHISFILE( offset)) { + while(*ppRefType) { + if((*ppRefType)->reference == offset) + return; + ppRefType = &(*ppRefType)->next; + } + + *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppRefType)); + + if(!MSFT_HREFTYPE_INTHISFILE( offset)) { /* external typelib */ - TLBImpInfo impinfo; + MSFT_ImpInfo impinfo; TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs); TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc)); - TLB_Read(&impinfo, sizeof(impinfo), pcx, + MSFT_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); + (*ppRefType)->reference=offset; + (*ppRefType)->pImpTLInfo = pImpLib; + MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx); + (*ppRefType)->index = TLB_REF_USE_GUID; }else{ ERR("Cannot find a reference\n"); - (*pprtd)->reference=-1; - (*pprtd)->pImpTLInfo=(void *)-1; + (*ppRefType)->reference=-1; + (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND; } }else{ /* in this typelib */ - (*pprtd)->reference=offset; - (*pprtd)->pImpTLInfo=(void *)-2; + (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset); + (*ppRefType)->reference=offset; + (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL; } } /* process Implemented Interfaces of a com class */ -static void TLB_DoImplTypes(TLBContext *pcx, int count, - int offset, TLBRefType ** pprtd) +static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count, + int offset) { int i; - TLBRefRecord refrec; + MSFT_RefRecord refrec; + TLBImplType **ppImpl = &pTI->impltypelist; TRACE_(typelib)("\n"); for(i=0;ipTblDir->pRefTab.offset); - TLB_DoRefType(pcx, refrec.reftype, pprtd); - (*pprtd)->flags=refrec.flags; - (*pprtd)->ctCustData= - TLB_CustData(pcx, refrec.oCustData, &(*pprtd)->pCustData); + *ppImpl=TLB_Alloc(sizeof(**ppImpl)); + MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset); + MSFT_DoRefType(pcx, pTI, refrec.reftype); + (*ppImpl)->hRef = refrec.reftype; + (*ppImpl)->implflags=refrec.flags; + (*ppImpl)->ctCustData= + MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData); offset=refrec.onext; - pprtd=&((*pprtd)->next); + ppImpl=&((*ppImpl)->next); } } /* * process a typeinfo record */ -ITypeInfoImpl * TLB_DoTypeInfo( +ITypeInfoImpl * MSFT_DoTypeInfo( TLBContext *pcx, int count, ITypeLibImpl * pLibInfo) { - TLBTypeInfoBase tiBase; + MSFT_TypeInfoBase tiBase; ITypeInfoImpl *ptiRet; TRACE_(typelib)("count=%u\n", count); ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor(); - TLB_Read(&tiBase, sizeof(tiBase) ,pcx , + MSFT_Read(&tiBase, sizeof(tiBase) ,pcx , pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase)); /* this is where we are coming from */ ptiRet->pTypeLib = pLibInfo; @@ -1464,7 +1584,7 @@ ITypeInfoImpl * TLB_DoTypeInfo( /* fill in the typeattr fields */ FIXME("Assign constructor/destructor memid\n"); - TLB_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx); + MSFT_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 */ @@ -1480,17 +1600,17 @@ ITypeInfoImpl * TLB_DoTypeInfo( 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) ; + MSFT_GetTdesc(pcx, tiBase.datatype1, + &ptiRet->TypeAttr.tdescAlias, ptiRet); /* FIXME: */ /* IDLDESC idldescType; *//* never saw this one != zero */ /* name, eventually add to a hash table */ - ptiRet->Name=TLB_ReadName(pcx, tiBase.NameOffset); + ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset); TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name)); /* help info */ - ptiRet->DocString=TLB_ReadString(pcx, tiBase.docstringoffs); + ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs); ptiRet->dwHelpStringContext=tiBase.helpstringcontext; ptiRet->dwHelpContext=tiBase.helpcontext; /* note: InfoType's Help file and HelpStringDll come from the containing @@ -1498,57 +1618,72 @@ ITypeInfoImpl * TLB_DoTypeInfo( */ /* functions */ if(ptiRet->TypeAttr.cFuncs >0 ) - TLB_DoFuncs(pcx, ptiRet->TypeAttr.cFuncs ,ptiRet->TypeAttr.cVars, - tiBase.memoffset, & ptiRet->funclist); + MSFT_DoFuncs(pcx, ptiRet, 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 ){ + MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, + ptiRet->TypeAttr.cVars, + tiBase.memoffset, & ptiRet->varlist); + if(ptiRet->TypeAttr.cImplTypes >0 ) { switch(ptiRet->TypeAttr.typekind) { case TKIND_COCLASS: - TLB_DoImplTypes(pcx, ptiRet->TypeAttr.cImplTypes , - tiBase.datatype1, & ptiRet->impltypelist); + MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes , + tiBase.datatype1); break; case TKIND_DISPATCH: - ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType)); + ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); if (tiBase.datatype1 != -1) { - TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist); + MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1); + ptiRet->impltypelist->hRef = tiBase.datatype1; } else - { + { /* FIXME: This is a really bad hack to add IDispatch */ char* szStdOle = "stdole2.tlb\0"; int nStdOleLen = strlen(szStdOle); - - ptiRet->impltypelist->guid = IID_IDispatch; - ptiRet->impltypelist->reference = -1; - ptiRet->impltypelist->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib)); - ptiRet->impltypelist->pImpTLInfo->guid = IID_StdOle; - ptiRet->impltypelist->pImpTLInfo->name = SysAllocStringLen(NULL, nStdOleLen + 1); + TLBRefType **ppRef = &ptiRet->reflist; + + while(*ppRef) { + if((*ppRef)->reference == -1) + break; + ppRef = &(*ppRef)->next; + } + if(!*ppRef) { + *ppRef = TLB_Alloc(sizeof(**ppRef)); + (*ppRef)->guid = IID_IDispatch; + (*ppRef)->reference = -1; + (*ppRef)->index = TLB_REF_USE_GUID; + (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib)); + (*ppRef)->pImpTLInfo->guid = IID_StdOle; + (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL, + nStdOleLen + 1); - MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED, - szStdOle, - -1, - ptiRet->impltypelist->pImpTLInfo->name, - SysStringLen(ptiRet->impltypelist->pImpTLInfo->name)); + MultiByteToWideChar(CP_ACP, + MB_PRECOMPOSED, + szStdOle, + -1, + (*ppRef)->pImpTLInfo->name, + SysStringLen((*ppRef)->pImpTLInfo->name)); - ptiRet->impltypelist->pImpTLInfo->lcid = 0; - ptiRet->impltypelist->pImpTLInfo->wVersionMajor = 2; - ptiRet->impltypelist->pImpTLInfo->wVersionMinor = 0; - } + (*ppRef)->pImpTLInfo->lcid = 0; + (*ppRef)->pImpTLInfo->wVersionMajor = 2; + (*ppRef)->pImpTLInfo->wVersionMinor = 0; + } + } break; default: - ptiRet->impltypelist=TLB_Alloc(sizeof(TLBRefType)); - TLB_DoRefType(pcx, tiBase.datatype1, & ptiRet->impltypelist); + ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType)); + MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1); + ptiRet->impltypelist->hRef = tiBase.datatype1; break; - } + } } ptiRet->ctCustData= - TLB_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData); + MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData); TRACE_(typelib)("%s guid: %s kind:%s\n", debugstr_w(ptiRet->Name), @@ -1565,6 +1700,7 @@ ITypeInfoImpl * TLB_DoTypeInfo( * the memory */ #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */ +#define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */ int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib) { int ret = E_FAIL; @@ -1596,7 +1732,7 @@ int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib) /* is there any thing after trailing back-slash ? */ if (pszTypeLibIndex && pszTypeLibIndex < pszFileName + nStrLen) { - /* yes -> it's a index! store DLL name, without the trailing back-slash */ + /* yes -> it's an index! store DLL name, without the trailing back-slash */ size_t nMemToAlloc = pszTypeLibIndex - pszFileName; pszDllName = HeapAlloc(GetProcessHeap(), @@ -1635,16 +1771,21 @@ int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib) LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if(pBase) { + /* retrieve file size */ + DWORD dwTLBLength = GetFileSize(hFile, NULL); + /* first try to load as *.tlb */ dwSignature = *((DWORD*) pBase); if ( dwSignature == MSFT_SIGNATURE) { - /* retrieve file size */ - DWORD dwTLBLength = GetFileSize(hFile, NULL); - - *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength); + *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); ITypeLib2_AddRef(*ppTypeLib); } + else if ( dwSignature == SLTG_SIGNATURE) + { + *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); + ITypeLib2_AddRef(*ppTypeLib); + } UnmapViewOfFile(pBase); } CloseHandle(hMapping); @@ -1674,9 +1815,14 @@ int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib) dwSignature = *((DWORD*) pBase); if ( dwSignature == MSFT_SIGNATURE) { - *ppTypeLib = ITypeLib2_Constructor(pBase, dwTLBLength); + *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); ITypeLib2_AddRef(*ppTypeLib); - } + } + else if ( dwSignature == SLTG_SIGNATURE) + { + *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); + ITypeLib2_AddRef(*ppTypeLib); + } else { FIXME("Header type magic 0x%08lx not supported.\n",dwSignature); @@ -1702,16 +1848,16 @@ int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib) /*================== ITypeLib(2) Methods ===================================*/ /**************************************************************************** - * ITypeLib2_Constructor + * ITypeLib2_Constructor_MSFT * - * loading a typelib from a in-memory image + * loading an MSFT typelib from an in-memory image */ -static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) +static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength) { TLBContext cx; long lPSegDir; - TLB2Header tlbHeader; - TLBSegDir tlbSegDir; + MSFT_Header tlbHeader; + MSFT_SegDir tlbSegDir; ITypeLibImpl * pTypeLibImpl; TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength); @@ -1730,21 +1876,21 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) cx.length = dwTLBLength; /* read header */ - TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); + MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); TRACE("header:\n"); TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 ); if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) { FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1); return NULL; } - /* there is a small number of information here until the next important + /* there is a small amount 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 */ TRACE("read segment directory (at %ld)\n",lPSegDir); - TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir); + MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir); cx.pTblDir = &tlbSegDir; /* just check two entries */ @@ -1757,7 +1903,7 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) /* now fill our internal data */ /* TLIBATTR fields */ - TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx); + MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx); pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid; pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */ pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version); @@ -1765,17 +1911,17 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */ /* name, eventually add to a hash table */ - pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset); + pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset); /* help info */ - pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring); - pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile); + pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring); + pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile); if( tlbHeader.varflags & HELPDLLFLAG) { int offset; - TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader)); - pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset); + MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader)); + pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset); } pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext; @@ -1783,7 +1929,7 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) /* custom data */ if(tlbHeader.CustomDataOffset >= 0) { - pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData); + pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData); } /* fill in typedescriptions */ @@ -1792,7 +1938,7 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT)); INT16 td[4]; pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC)); - TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset); + MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset); for(i=0; ipTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]); } - if(++ipTypeDesc[i].vt != VT_CARRAY) continue; if(tlbSegDir.pArrayDescriptions.offset>0) { - TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc); + MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc); pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1)); if(td[1]<0) @@ -1835,9 +1981,9 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) for(j = 0; jpTypeDesc[i].u.lpadesc->rgbounds[j].cElements, + MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements, sizeof(INT), &cx, DO_NOT_SEEK); - TLB_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound, + MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound, sizeof(INT), &cx, DO_NOT_SEEK); } } @@ -1860,17 +2006,17 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) { *ppImpLib = TLB_Alloc(sizeof(TLBImpLib)); (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset; - TLB_Read(&oGuid, sizeof(INT), &cx, offset); + MSFT_Read(&oGuid, sizeof(INT), &cx, offset); - TLB_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK); - TLB_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK); - TLB_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK); - TLB_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK); + MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK); + MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK); + MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK); + MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK); size >>= 2; (*ppImpLib)->name = TLB_Alloc(size+1); - TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK); - TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); + MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK); + MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc; ppImpLib = &(*ppImpLib)->next; @@ -1886,7 +2032,7 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++) { - *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl); + *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl); ITypeInfo_AddRef((ITypeInfo*) *ppTI); ppTI = &((*ppTI)->next); @@ -1898,6 +2044,773 @@ static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib, DWORD dwTLBLength) return (ITypeLib2*) pTypeLibImpl; } + +static BSTR TLB_MultiByteToBSTR(char *ptr) +{ + DWORD len; + WCHAR *nameW; + BSTR ret; + + len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len); + ret = SysAllocString(nameW); + HeapFree(GetProcessHeap(), 0, nameW); + return ret; +} + +static BOOL TLB_GUIDFromString(char *str, GUID *guid) +{ + char b[3]; + int i; + short s; + + if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) { + FIXME("Can't parse guid %s\n", debugstr_guid(guid)); + return FALSE; + } + + guid->Data4[0] = s >> 8; + guid->Data4[1] = s & 0xff; + + b[2] = '\0'; + for(i = 0; i < 6; i++) { + memcpy(b, str + 24 + 2 * i, 2); + guid->Data4[i + 2] = strtol(b, NULL, 16); + } + return TRUE; +} + +static WORD SLTG_ReadString(char *ptr, BSTR *pBstr) +{ + WORD bytelen; + DWORD len; + WCHAR *nameW; + + *pBstr = NULL; + bytelen = *(WORD*)ptr; + if(bytelen == 0xffff) return 2; + len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0); + nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len); + *pBstr = SysAllocStringLen(nameW, len); + HeapFree(GetProcessHeap(), 0, nameW); + return bytelen + 2; +} + +static WORD SLTG_ReadStringA(char *ptr, char **str) +{ + WORD bytelen; + + *str = NULL; + bytelen = *(WORD*)ptr; + if(bytelen == 0xffff) return 2; + *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1); + memcpy(*str, ptr + 2, bytelen); + (*str)[bytelen] = '\0'; + return bytelen + 2; +} + +static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl) +{ + char *ptr = pLibBlk; + WORD w; + + if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) { + FIXME("libblk magic = %04x\n", w); + return 0; + } + + ptr += 6; + if((w = *(WORD*)ptr) != 0xffff) { + FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w); + ptr += w; + } + ptr += 2; + + ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString); + + ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile); + + pTypeLibImpl->dwHelpContext = *(DWORD*)ptr; + ptr += 4; + + pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr; + ptr += 2; + + pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr; + ptr += 2; + + ptr += 4; /* skip res12 */ + + pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr; + ptr += 2; + + pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr; + ptr += 2; + + pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr; + ptr += 2; + + memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID)); + ptr += sizeof(GUID); + + return ptr - (char*)pLibBlk; +} + +static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem) +{ + BOOL done = FALSE; + TYPEDESC *pTD = &pElem->tdesc; + + /* Handle [in/out] first */ + if((*pType & 0xc000) == 0xc000) + pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE; + else if(*pType & 0x8000) + pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT; + else if(*pType & 0x4000) + pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT; + else + pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN; + + if(*pType & 0x2000) + pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID; + + if(*pType & 0x80) + pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL; + + while(!done) { + if((*pType & 0xe00) == 0xe00) { + pTD->vt = VT_PTR; + pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(TYPEDESC)); + pTD = pTD->u.lptdesc; + } + switch(*pType & 0x7f) { + case VT_PTR: + pTD->vt = VT_PTR; + pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(TYPEDESC)); + pTD = pTD->u.lptdesc; + break; + + case VT_USERDEFINED: + pTD->vt = VT_USERDEFINED; + pTD->u.hreftype = *(++pType) / 4; + done = TRUE; + break; + + case VT_CARRAY: + { + /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of + array */ + + SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType)); + + pTD->vt = VT_CARRAY; + pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(ARRAYDESC) + + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND)); + pTD->u.lpadesc->cDims = pSA->cDims; + memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound, + pSA->cDims * sizeof(SAFEARRAYBOUND)); + + pTD = &pTD->u.lpadesc->tdescElem; + break; + } + + case VT_SAFEARRAY: + { + /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this + useful? */ + + pType++; + pTD->vt = VT_SAFEARRAY; + pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(TYPEDESC)); + pTD = pTD->u.lptdesc; + break; + } + default: + pTD->vt = *pType & 0x7f; + done = TRUE; + break; + } + pType++; + } + return pType; +} + + +static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI, + char *pNameTable) +{ + int ref; + char *name; + TLBRefType **ppRefType; + + if(pRef->magic != SLTG_REF_MAGIC) { + FIXME("Ref magic = %x\n", pRef->magic); + return; + } + name = ( (char*)(&pRef->names) + pRef->number); + + ppRefType = &pTI->reflist; + for(ref = 0; ref < pRef->number >> 3; ref++) { + char *refname; + unsigned int lib_offs, type_num; + + *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppRefType)); + + name += SLTG_ReadStringA(name, &refname); + if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2) + FIXME("Can't sscanf ref\n"); + if(lib_offs != 0xffff) { + TLBImpLib **import = &pTI->pTypeLib->pImpLibs; + + while(*import) { + if((*import)->offset == lib_offs) + break; + import = &(*import)->next; + } + if(!*import) { + char fname[MAX_PATH+1]; + int len; + + *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**import)); + (*import)->offset = lib_offs; + TLB_GUIDFromString( pNameTable + lib_offs + 4, + &(*import)->guid); + if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s", + &(*import)->wVersionMajor, + &(*import)->wVersionMinor, + &(*import)->lcid, fname) != 4) { + FIXME("can't sscanf ref %s\n", + pNameTable + lib_offs + 40); + } + len = strlen(fname); + if(fname[len-1] != '#') + FIXME("fname = %s\n", fname); + fname[len-1] = '\0'; + (*import)->name = TLB_MultiByteToBSTR(fname); + } + (*ppRefType)->pImpTLInfo = *import; + } else { /* internal ref */ + (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL; + } + (*ppRefType)->reference = ref; + (*ppRefType)->index = type_num; + + HeapFree(GetProcessHeap(), 0, refname); + ppRefType = &(*ppRefType)->next; + } + if((BYTE)*name != SLTG_REF_MAGIC) + FIXME("End of ref block magic = %x\n", *name); + dump_TLBRefType(pTI->reflist); +} + +static char *SLTG_DoImpls(SLTG_ImplInfo *info, ITypeInfoImpl *pTI, + BOOL OneOnly) +{ + TLBImplType **ppImplType = &pTI->impltypelist; + + while(1) { + *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppImplType)); + (*ppImplType)->hRef = info->ref; + (*ppImplType)->implflags = info->impltypeflags; + pTI->TypeAttr.cImplTypes++; + ppImplType = &(*ppImplType)->next; + + if(info->next == 0xffff) + break; + if(OneOnly) + FIXME("Interface inheriting more than one interface\n"); + info++; + } + info++; + return (char*)info; +} + +static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI, + char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + char *pFirstItem, *pNextItem; + + if(pTIHeader->href_table != 0xffffffff) { + SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI, + pNameTable); + } + + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + + pFirstItem = pNextItem = (char*)(pMemHeader + 1); + + if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { + pNextItem = SLTG_DoImpls((SLTG_ImplInfo*)pFirstItem, pTI, FALSE); + } + + return; +} + + +static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI, + char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + SLTG_Function *pFunc; + char *pFirstItem, *pNextItem; + TLBFuncDesc **ppFuncDesc = &pTI->funclist; + int num = 0; + + if(pTIHeader->href_table != 0xffffffff) { + SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI, + pNameTable); + } + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + + pFirstItem = pNextItem = (char*)(pMemHeader + 1); + + if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) { + pNextItem = SLTG_DoImpls((SLTG_ImplInfo*)pFirstItem, pTI, TRUE); + } + + for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1; + pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) { + + int param; + WORD *pType, *pArg; + + if(pFunc->magic != SLTG_FUNCTION_MAGIC && + pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) { + FIXME("func magic = %02x\n", pFunc->magic); + return; + } + *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppFuncDesc)); + (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable); + + (*ppFuncDesc)->funcdesc.memid = pFunc->dispid; + (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4; + (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7; + (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3; + (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1; + (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos; + + if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC) + (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags; + + if(pFunc->retnextopt & 0x80) + pType = &pFunc->rettype; + else + pType = (WORD*)(pFirstItem + pFunc->rettype); + + + SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc); + + (*ppFuncDesc)->funcdesc.lprgelemdescParam = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC)); + (*ppFuncDesc)->pParamDesc = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc)); + + pArg = (WORD*)(pFirstItem + pFunc->arg_off); + + for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) { + char *paramName = pNameTable + *pArg; + /* right, if the arg type follows then paramName points to the 2nd + letter of the name (or there is no name), else if the next + WORD is an offset to the arg type then paramName points to the + first letter. Before the name there always seems to be the byte + 0xff or 0x00, so let's take one char off paramName and see what + we're pointing at. Got that? */ + + if(*pArg == 0xffff) /* If we don't have a name the type seems to + always follow. FIXME is this correct? */ + paramName = NULL; + + pArg++; + + if(paramName && + (*(paramName-1) == '\xff' || + *(paramName-1) == '\x00')) { /* the next word is an offset to + the type */ + pType = (WORD*)(pFirstItem + *pArg); + SLTG_DoType(pType, pFirstItem, + &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]); + pArg++; + } else { + if(paramName) + paramName--; + pArg = SLTG_DoType(pArg, pFirstItem, + &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]); + } + + /* Are we an optional param ? */ + if((*ppFuncDesc)->funcdesc.cParams - param <= + (*ppFuncDesc)->funcdesc.cParamsOpt) + (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT; + + if(paramName) { + (*ppFuncDesc)->pParamDesc[param].Name = + TLB_MultiByteToBSTR(paramName); + } + } + + ppFuncDesc = &((*ppFuncDesc)->next); + if(pFunc->next == 0xffff) break; + } + pTI->TypeAttr.cFuncs = num; + dump_TLBFuncDesc(pTI->funclist); +} + +static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + SLTG_RecordItem *pItem; + char *pFirstItem; + TLBVarDesc **ppVarDesc = &pTI->varlist; + int num = 0; + WORD *pType; + char buf[300]; + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + + pFirstItem = (char*)(pMemHeader + 1); + for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1; + pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) { + if(pItem->magic != SLTG_RECORD_MAGIC) { + FIXME("record magic = %02x\n", pItem->magic); + return; + } + *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppVarDesc)); + (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable); + (*ppVarDesc)->vardesc.memid = pItem->memid; + (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs; + (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE; + + if(pItem->typepos == 0x02) + pType = &pItem->type; + else if(pItem->typepos == 0x00) + pType = (WORD*)(pFirstItem + pItem->type); + else { + FIXME("typepos = %02x\n", pItem->typepos); + break; + } + + SLTG_DoType(pType, pFirstItem, + &(*ppVarDesc)->vardesc.elemdescVar); + + /* FIXME("helpcontext, helpstring\n"); */ + + dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); + + ppVarDesc = &((*ppVarDesc)->next); + if(pItem->next == 0xffff) break; + } + pTI->TypeAttr.cVars = num; +} + +static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI, char *pNameTable) +{ + SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk; + SLTG_MemberHeader *pMemHeader; + SLTG_EnumItem *pItem; + char *pFirstItem; + TLBVarDesc **ppVarDesc = &pTI->varlist; + int num = 0; + + pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table); + + pFirstItem = (char*)(pMemHeader + 1); + for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1; + pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) { + if(pItem->magic != SLTG_ENUMITEM_MAGIC) { + FIXME("enumitem magic = %04x\n", pItem->magic); + return; + } + *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(**ppVarDesc)); + (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable); + (*ppVarDesc)->vardesc.memid = pItem->memid; + (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0, + sizeof(VARIANT)); + V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT; + V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) = + *(INT*)(pItem->value + pFirstItem); + (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4; + (*ppVarDesc)->vardesc.varkind = VAR_CONST; + /* FIXME("helpcontext, helpstring\n"); */ + + ppVarDesc = &((*ppVarDesc)->next); + if(pItem->next == 0xffff) break; + } + pTI->TypeAttr.cVars = num; +} + +/* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more + managable copy of it into this */ +typedef struct { + WORD small_no; + char *index_name; + char *other_name; + WORD res1a; + WORD name_offs; + WORD more_bytes; + char *extra; + WORD res20; + DWORD helpcontext; + WORD res26; + GUID uuid; +} SLTG_InternalOtherTypeInfo; + +/**************************************************************************** + * ITypeLib2_Constructor_SLTG + * + * loading a SLTG typelib from an in-memory image + */ +static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) +{ + ITypeLibImpl *pTypeLibImpl; + SLTG_Header *pHeader; + SLTG_BlkEntry *pBlkEntry; + SLTG_Magic *pMagic; + SLTG_Index *pIndex; + SLTG_Pad9 *pPad9; + LPVOID pBlk, pFirstBlk; + SLTG_LibBlk *pLibBlk; + SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks; + char *pAfterOTIBlks = NULL; + char *pNameTable, *ptr; + int i; + DWORD len, order; + ITypeInfoImpl **ppTypeInfoImpl; + + TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength); + + pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl)); + if (!pTypeLibImpl) return NULL; + + ICOM_VTBL(pTypeLibImpl) = &tlbvt; + pTypeLibImpl->ref = 1; + + pHeader = pLib; + + TRACE("header:\n"); + TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic, + pHeader->nrOfFileBlks ); + if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) { + FIXME("Header type magic 0x%08lx not supported.\n", + pHeader->SLTG_magic); + return NULL; + } + + /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */ + pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2; + + /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */ + pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1); + + /* Next we have a magic block */ + pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1); + + /* Let's see if we're still in sync */ + if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC, + sizeof(SLTG_COMPOBJ_MAGIC))) { + FIXME("CompObj magic = %s\n", pMagic->CompObj_magic); + return NULL; + } + if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC, + sizeof(SLTG_DIR_MAGIC))) { + FIXME("dir magic = %s\n", pMagic->dir_magic); + return NULL; + } + + pIndex = (SLTG_Index*)(pMagic+1); + + pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount); + + pFirstBlk = (LPVOID)(pPad9 + 1); + + /* We'll set up a ptr to the main library block, which is the last one. */ + + for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; + pBlkEntry[order].next != 0; + order = pBlkEntry[order].next - 1, i++) { + pBlk += pBlkEntry[order].len; + } + pLibBlk = pBlk; + + len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl); + + /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount + interspersed */ + + len += 0x40; + + /* And now TypeInfoCount of SLTG_OtherTypeInfo */ + + pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(*pOtherTypeInfoBlks) * + pTypeLibImpl->TypeInfoCount); + + + ptr = (char*)pLibBlk + len; + + for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) { + WORD w, extra; + len = 0; + + pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr; + + w = *(WORD*)(ptr + 2); + if(w != 0xffff) { + len += w; + pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0, + w+1); + memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w); + pOtherTypeInfoBlks[i].index_name[w] = '\0'; + } + w = *(WORD*)(ptr + 4 + len); + if(w != 0xffff) { + TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w)); + len += w; + pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0, + w+1); + memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w); + pOtherTypeInfoBlks[i].other_name[w] = '\0'; + } + pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6); + pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8); + extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len); + if(extra) { + pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0, + extra); + memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra); + len += extra; + } + pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len); + pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len); + pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len); + memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID)); + len += sizeof(SLTG_OtherTypeInfo); + ptr += len; + } + + pAfterOTIBlks = ptr; + + /* Skip this WORD and get the next DWORD */ + len = *(DWORD*)(pAfterOTIBlks + 2); + + /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a + magic dust and we should be pointing at the beginning of the name + table */ + + pNameTable = (char*)pLibBlk + len + 0x216; + + pNameTable += 2; + + TRACE("Library name is %s\n", pNameTable + pLibBlk->name); + + pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name); + + + /* Hopefully we now have enough ptrs set up to actually read in + some TypeInfos. It's not clear which order to do them in, so + I'll just follow the links along the BlkEntry chain and read + them in in the order in which they're in the file */ + + ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo); + + for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0; + pBlkEntry[order].next != 0; + order = pBlkEntry[order].next - 1, i++) { + + SLTG_TypeInfoHeader *pTIHeader; + + if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, + pOtherTypeInfoBlks[i].index_name)) { + FIXME("Index strings don't match\n"); + return NULL; + } + + pTIHeader = pBlk; + if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) { + FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic); + return NULL; + } + *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); + (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl; + (*ppTypeInfoImpl)->index = i; + (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR( + pOtherTypeInfoBlks[i].name_offs + + pNameTable); + (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext; + memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid, + sizeof(GUID)); + (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind; + (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version; + (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version; + (*ppTypeInfoImpl)->TypeAttr.wTypeFlags = + (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5); + + if((pTIHeader->typeflags1 & 7) != 2) + FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1); + if(pTIHeader->typeflags3 != 2) + FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3); + + TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n", + debugstr_w((*ppTypeInfoImpl)->Name), + typekind_desc[pTIHeader->typekind], + debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid), + (*ppTypeInfoImpl)->TypeAttr.wTypeFlags); + + switch(pTIHeader->typekind) { + case TKIND_ENUM: + SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable); + break; + + case TKIND_RECORD: + SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable); + break; + + case TKIND_INTERFACE: + SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable); + break; + + case TKIND_COCLASS: + SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable); + break; + + default: + FIXME("Not processing typekind %d\n", pTIHeader->typekind); + break; + + } + + ppTypeInfoImpl = &((*ppTypeInfoImpl)->next); + pBlk += pBlkEntry[order].len; + } + + if(i != pTypeLibImpl->TypeInfoCount) { + FIXME("Somehow processed %d TypeInfos\n", i); + return NULL; + } + + HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks); + return (ITypeLib2*)pTypeLibImpl; +} + /* ITypeLib::QueryInterface */ static HRESULT WINAPI ITypeLib2_fnQueryInterface( @@ -2667,7 +3580,7 @@ static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid, for(i=0; ifuncdesc.cParams; i++) { if(!i) - *rgBstrNames=SysAllocString(pFDesc->Name); + *rgBstrNames=SysAllocString(pFDesc->Name); else rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name); } @@ -2688,7 +3601,8 @@ static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid, /* recursive search */ ITypeInfo *pTInfo; HRESULT result; - result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo); + result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, + &pTInfo); if(SUCCEEDED(result)) { result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames); @@ -2724,7 +3638,7 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( { ICOM_THIS( ITypeInfoImpl, iface); int(i); - TLBRefType *pIref = This->impltypelist; + TLBImplType *pImpl = This->impltypelist; TRACE("(%p) index %d\n", This, index); dump_TypeInfo(This); @@ -2743,23 +3657,23 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType( } else { - if (!pIref) return TYPE_E_ELEMENTNOTFOUND; - *pRefType = pIref->reference; + if (!pImpl) return TYPE_E_ELEMENTNOTFOUND; + *pRefType = pImpl->hRef; } } else { /* get element n from linked list */ - for(i=0; pIref && inext; + pImpl = pImpl->next; } - if (!pIref) return TYPE_E_ELEMENTNOTFOUND; + if (!pImpl) return TYPE_E_ELEMENTNOTFOUND; - *pRefType = pIref->reference; + *pRefType = pImpl->hRef; - TRACE("-- 0x%08lx %s\n",pIref->reference, debugstr_guid(&pIref->guid) ); + TRACE("-- 0x%08lx\n", pImpl->hRef ); } return S_OK; @@ -2775,13 +3689,15 @@ static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface, UINT index, INT *pImplTypeFlags) { ICOM_THIS( ITypeInfoImpl, iface); - int(i); - TLBRefType *pIref; + int i; + TLBImplType *pImpl; + TRACE("(%p) index %d\n", This, index); - for(i=0, pIref=This->impltypelist; inext) + for(i=0, pImpl=This->impltypelist; inext) ; - if(i==index && pIref){ - *pImplTypeFlags=pIref->flags; + if(i==index && pImpl){ + *pImplTypeFlags=pImpl->implflags; return S_OK; } *pImplTypeFlags=0; @@ -2832,7 +3748,7 @@ static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface, /* recursive search */ ITypeInfo *pTInfo; ret=ITypeInfo_GetRefTypeInfo(iface, - This->impltypelist->reference, &pTInfo); + This->impltypelist->hRef, &pTInfo); if(SUCCEEDED(ret)){ ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId ); ITypeInfo_Release(pTInfo); @@ -3061,10 +3977,17 @@ static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface, }else {/* for a member */ for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) if(pFDesc->funcdesc.memid==memid){ - return S_OK; + if(pBstrName) + *pBstrName = SysAllocString(pFDesc->Name); + if(pBstrDocString) + *pBstrDocString=SysAllocString(pFDesc->HelpString); + if(pdwHelpContext) + *pdwHelpContext=pFDesc->helpcontext; + return S_OK; } for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) if(pVDesc->vardesc.memid==memid){ + FIXME("Not implemented\n"); return S_OK; } } @@ -3098,20 +4021,10 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( ICOM_THIS( ITypeInfoImpl, iface); HRESULT result = E_FAIL; - if(HREFTYPE_INTHISFILE(hRefType)) - { - ITypeLib *pTLib; - int Index; - result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index); - if(SUCCEEDED( result )) - { - result=ITypeLib2_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo); - ITypeLib2_Release(pTLib ); - } - } - else if (hRefType == -1 && - (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) && - (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) + + if (hRefType == -1 && + (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) && + (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) { /* when we meet a DUAL dispinterface, we must create the interface * version of it. @@ -3127,103 +4040,62 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( /* change the type to interface */ pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE; - - *ppTInfo = (ITypeInfo*) pTypeInfoImpl; + + *ppTInfo = (ITypeInfo*) pTypeInfoImpl; ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl); - result = S_OK; + result = S_OK; + + } else { + TLBRefType *pRefType; + for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) { + if(pRefType->reference == hRefType) + break; + } + if(!pRefType) + FIXME("Can't find pRefType for ref %lx\n", hRefType); + if(pRefType && hRefType != -1) { + ITypeLib *pTLib; + + if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) { + int Index; + result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index); + } else { + if(pRefType->pImpTLInfo->pImpTypeLib) { + TRACE("typeinfo in imported typelib that is already loaded\n"); + pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib; + ITypeLib2_AddRef((ITypeLib*) pTLib); + result = S_OK; + } else { + TRACE("typeinfo in imported typelib that isn't already loaded\n"); + result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid, + pRefType->pImpTLInfo->wVersionMajor, + pRefType->pImpTLInfo->wVersionMinor, + pRefType->pImpTLInfo->lcid, + &pTLib); + + if(!SUCCEEDED(result)) { + BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name); + result=LoadTypeLib(libnam, &pTLib); + SysFreeString(libnam); + } + if(SUCCEEDED(result)) { + pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib; + ITypeLib2_AddRef(pTLib); + } + } + } + if(SUCCEEDED(result)) { + if(pRefType->index == TLB_REF_USE_GUID) + result = ITypeLib2_GetTypeInfoOfGuid(pTLib, + &pRefType->guid, + ppTInfo); + else + result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index, + ppTInfo); + } } - else - { - /* imported type lib */ - TLBRefType *pRefType = NULL; - - /* search in implemented types */ - for( pRefType = This->impltypelist; - pRefType && (pRefType->reference != hRefType); - pRefType = pRefType->next); - - if(!pRefType) - { - TYPEATTR* pMyTypeAttr = &This->TypeAttr; - unsigned short cFuncs = pMyTypeAttr->cFuncs; - unsigned short cVars = pMyTypeAttr->cVars; - - /* search in arguments */ - if (cFuncs > 0) - { - unsigned short cFuncIndex = 0; - - TLBFuncDesc* pCurrFunc = This->funclist; - - for (cFuncIndex = 0; !pRefType && cFuncIndex < cFuncs ; ++cFuncIndex) - { - FUNCDESC* pCurrFuncDesc = &pCurrFunc->funcdesc; - - short cParams = pCurrFuncDesc->cParams; - short cParamIndex = 0; - - for (cParamIndex = 0 ; - !pRefType && cParamIndex < cParams ; - ++cParamIndex) - { - TLBParDesc* pCurrParamDesc = &(pCurrFunc->pParamDesc[cParamIndex]); - - if ( pCurrParamDesc->pRefType && pCurrParamDesc->pRefType->reference == hRefType) - { - pRefType = pCurrParamDesc->pRefType; - break; /* also break from outer loop since pRefType != 0 */ - } - } - - pCurrFunc = pCurrFunc->next; - } - } - /* search in variables */ - else if (cVars > 0) - { - FIXME("search hreftype in variables, if any\n"); - result = E_INVALIDARG; // FIXME : correct? - } - } - - /* href-referenced typeinfo found! */ - if (pRefType || hRefType == -1) - { - ITypeLibImpl *pTypeLib = pRefType->pImpTLInfo->pImpTypeLib; - - if(pTypeLib) - { - TRACE("typeinfo in imported typelib that is already loaded\n"); - - result = ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, - &pRefType->guid, - ppTInfo); - } - else - { - result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid, - pRefType->pImpTLInfo->wVersionMajor, - pRefType->pImpTLInfo->wVersionMinor, - pRefType->pImpTLInfo->lcid, - (LPTYPELIB *)&pTypeLib); - - if(!SUCCEEDED(result)) - { - BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name); - TRACE("typeinfo in imported typelib that isn't already loaded\n"); - result=LoadTypeLib(libnam, (LPTYPELIB *)&pTypeLib); - SysFreeString(libnam); - } - if(SUCCEEDED(result)) - { - result=ITypeLib2_GetTypeInfoOfGuid((LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo); - pRefType->pImpTLInfo->pImpTypeLib = pTypeLib; - ITypeLib2_AddRef((ITypeLib*) pTypeLib); - } - } - } } TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType, @@ -3501,7 +4373,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetParamCustData( return E_INVALIDARG; /* FIXME: correct? */ } -/* ITypeInfo2::GetVarcCustData +/* ITypeInfo2::GetVarCustData * * Gets the custom data */ @@ -3537,7 +4409,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetVarCustData( return E_INVALIDARG; /* FIXME: correct? */ } -/* ITypeInfo2::GetImplcCustData +/* ITypeInfo2::GetImplCustData * * Gets the custom data */ @@ -3549,7 +4421,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData( { ICOM_THIS( ITypeInfoImpl, iface); TLBCustData *pCData=NULL; - TLBRefType * pRDesc; + TLBImplType * pRDesc; int i; for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next); @@ -3787,7 +4659,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData( { ICOM_THIS( ITypeInfoImpl, iface); TLBCustData *pCData; - TLBRefType * pRDesc; + TLBImplType * pRDesc; int i; TRACE("(%p) index %d\n", This, index); for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, diff --git a/dlls/oleaut32/typelib.h b/dlls/oleaut32/typelib.h index bd1f0ebfc11..e78654c90df 100644 --- a/dlls/oleaut32/typelib.h +++ b/dlls/oleaut32/typelib.h @@ -16,18 +16,29 @@ #define HELPDLLFLAG (0x0100) #define DO_NOT_SEEK (-1) -#define HREFTYPE_INTHISFILE(href) (!((href) & 3)) -#define HREFTYPE_INDEX(href) ((href) /sizeof(TLBTypeInfoBase)) +#define MSFT_HREFTYPE_INTHISFILE(href) (!((href) & 3)) +#define MSFT_HREFTYPE_INDEX(href) ((href) /sizeof(MSFT_TypeInfoBase)) /*-------------------------FILE STRUCTURES-----------------------------------*/ +/* There are two known file formats, those created with ICreateTypeLib + * have the signature "SLGT" as their first four bytes, while those created + * with ICreateTypeLib2 have "MSFT". + */ + +/***************************************************** + * MSFT typelibs + * + * These are TypeLibs created with ICreateTypeLib2 + * + */ /* * structure of the typelib type2 header * it is at the beginning of a type lib file * */ -typedef struct tagTLB2Header { +typedef struct tagMSFT_Header { /*0x00*/INT magic1; /* 0x5446534D "MSFT" */ INT magic2; /* 0x00010002 version nr? */ INT posguid; /* position of libid in guid table */ @@ -36,7 +47,7 @@ typedef struct tagTLB2Header { /*0x10*/INT lcid2; INT varflags; /* (largely) unknown flags ,seems to be always 41 */ /* becomes 0x51 with a helpfile defined */ - /* if help dll defined its 0x151 */ + /* if help dll defined it's 0x151 */ /* update : the lower nibble is syskind */ INT version; /* set with SetVersion() */ INT flags; /* set with SetFlags() */ @@ -54,44 +65,45 @@ typedef struct tagTLB2Header { INT res48; /* unknown always: 0x80 */ INT dispatchpos; /* gets a value (1+n*0x0c) with Idispatch interfaces */ /*0x50*/INT res50; /* is zero becomes one when an interface is derived */ -} TLB2Header; +} MSFT_Header; /* segments in the type lib file have a structure like this: */ -typedef struct _tptag { +typedef struct tagMSFT_pSeg { INT offset; /* absolute offset in file */ INT length; /* length of segment */ INT res08; /* unknown always -1 */ INT res0c; /* unknown always 0x0f in the header */ /* 0x03 in the typeinfo_data */ -} pSeg; +} MSFT_pSeg; /* layout of the main segment directory */ -typedef struct tagTLBSegDir { -/*1*/pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */ - /* (25 ints) */ -/*2*/pSeg pImpInfo; /* table with info for imported types */ -/*3*/pSeg pImpFiles; /* import libaries */ -/*4*/pSeg pRefTab; /* References table */ -/*5*/pSeg pLibtab; /* always exists, alway same size (0x80) */ - /* hash table w offsets to guid????? */ -/*6*/pSeg pGuidTab; /* all guids are stored here together with */ - /* offset in some table???? */ -/*7*/pSeg res07; /* always created, alway same size (0x200) */ - /* purpose largely unknown */ -/*8*/pSeg pNametab; /* name tables */ -/*9*/pSeg pStringtab; /*string table */ -/*A*/pSeg pTypdescTab; /* table with type descriptors */ -/*B*/pSeg pArrayDescriptions; -/*C*/pSeg pCustData; /* data table, used for custom data and default */ - /* parameter values */ -/*D*/pSeg pCDGuids; /* table with offsets for the guids and into the customer data table */ -/*E*/pSeg res0e; /* unknown */ -/*F*/pSeg res0f; /* unknown */ -} TLBSegDir; +typedef struct tagMSFT_SegDir { +/*1*/MSFT_pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */ + /* (25 ints) */ +/*2*/MSFT_pSeg pImpInfo; /* table with info for imported types */ +/*3*/MSFT_pSeg pImpFiles; /* import libaries */ +/*4*/MSFT_pSeg pRefTab; /* References table */ +/*5*/MSFT_pSeg pLibtab; /* always exists, alway same size (0x80) */ + /* hash table w offsets to guid????? */ +/*6*/MSFT_pSeg pGuidTab; /* all guids are stored here together with */ + /* offset in some table???? */ +/*7*/MSFT_pSeg res07; /* always created, alway same size (0x200) */ + /* purpose largely unknown */ +/*8*/MSFT_pSeg pNametab; /* name tables */ +/*9*/MSFT_pSeg pStringtab; /* string table */ +/*A*/MSFT_pSeg pTypdescTab; /* table with type descriptors */ +/*B*/MSFT_pSeg pArrayDescriptions; +/*C*/MSFT_pSeg pCustData; /* data table, used for custom data and default */ + /* parameter values */ +/*D*/MSFT_pSeg pCDGuids; /* table with offsets for the guids and into */ + /* the customer data table */ +/*E*/MSFT_pSeg res0e; /* unknown */ +/*F*/MSFT_pSeg res0f; /* unknown */ +} MSFT_SegDir; /* base type info data */ -typedef struct tagTLBTypeInfoBase { +typedef struct tagMSFT_TypeInfoBase { /*000*/ INT typekind; /* it is the TKIND_xxx */ /* some byte alignment stuf */ INT memoffset; /* points past the file, if no elements */ @@ -125,14 +137,14 @@ typedef struct tagTLBTypeInfoBase { /* else it is zero? */ INT res18; /* always? 0 */ /*060*/ INT res19; /* always? -1 */ - } TLBTypeInfoBase; + } MSFT_TypeInfoBase; /* layout of an entry with information on imported types */ -typedef struct tagTLBImpInfo { +typedef struct tagMSFT_ImpInfo { INT res0; /* unknown */ INT oImpFile; /* offset inthe Import File table */ INT oGuid; /* offset in Guid table */ - } TLBImpInfo; + } MSFT_ImpInfo; /* function description data */ typedef struct { @@ -164,7 +176,7 @@ typedef struct { 6* INT oCustData; // custom data for function // 7* INT oArgCustData[1]; // custom data per argument // */ -} TLBFuncRecord; +} MSFT_FuncRecord; /* after this may follow an array with default value pointers if the * appropriate bit in the FKCCIC field has been set: @@ -176,7 +188,7 @@ typedef struct { INT DataType; INT oName; INT Flags; - } TLBParameterInfo; + } MSFT_ParameterInfo; /* Variable description data */ typedef struct { @@ -195,43 +207,314 @@ typedef struct { INT oCustData; /* custom data for variable */ INT HelpStringContext; -} TLBVarRecord; +} MSFT_VarRecord; /* Structure of the reference data */ typedef struct { - INT reftype; /* either offset in type info table, then its */ + INT reftype; /* either offset in type info table, then it's */ /* a multiple of 64 */ /* or offset in the external reference table */ /* with an offset of 1 */ INT flags; INT oCustData; /* custom data */ INT onext; /* next offset, -1 if last */ -} TLBRefRecord; +} MSFT_RefRecord; /* this is how a guid is stored */ typedef struct { GUID guid; INT unk10; /* differntiate with libid, classid etc? */ - /* its -2 for a libary */ + /* it's -2 for a libary */ /* it's 0 for an interface */ INT unk14; /* always? -1 */ -} TLBGuidEntry; +} MSFT_GuidEntry; /* some data preceding entries in the name table */ typedef struct { INT unk00; /* sometimes -1 (lib, parameter) , sometimes 0 (interface, func) */ INT unk10; /* sometimes -1 (lib) , sometimes 0 (interface, func), - sometime 0x10 (par) */ + sometimes 0x10 (par) */ INT namelen; /* only lower 8 bits are valid */ -} TLBNameIntro; +} MSFT_NameIntro; /* the custom data table directory has enties like this */ typedef struct { INT GuidOffset; INT DataOffset; - INT next; /* next offset in the table, -1 if its the last */ -} TLBCDGuid; + INT next; /* next offset in the table, -1 if it's the last */ +} MSFT_CDGuid; +/*********************************************************** + * + * SLTG typelibs. + * + * These are created with ICreateTypeLib + * + */ + +#include "pshpack1.h" + +typedef struct { +/*00*/ DWORD SLTG_magic; /* 0x47544c53 == "SLTG" */ +/*04*/ WORD nrOfFileBlks; /* no of SLTG_BlkEntry's + 1 */ +/*06*/ WORD res06; /* ?? always 9 */ +/*08*/ WORD res08; /* some kind of len/offset ?? */ +/*0a*/ WORD first_blk; /* 1 based index into blk entries that + corresponds to first block in file */ +/*0c*/ DWORD res0c; /* always 0x000204ff */ +/*10*/ DWORD res10; /* always 0x00000000 */ +/*14*/ DWORD res14; /* always 0x000000c0 */ +/*18*/ DWORD res18; /* always 0x46000000 */ +/*1c*/ DWORD res1c; /* always 0x00000044 */ +/*20*/ DWORD res20; /* always 0xffff0000 */ +} SLTG_Header; + +/* This gets followed by a list of block entries */ +typedef struct { +/*00*/ DWORD len; +/*04*/ WORD index_string; /* offs from start of SLTG_Magic to index string */ +/*06*/ WORD next; +} SLTG_BlkEntry; + +/* The order of the blocks in the file is given by starting at Block + entry firt_blk and stepping through using the next pointer */ + +/* These then get followed by this magic */ +typedef struct { +/*00*/ BYTE res00; /* always 0x01 */ +/*01*/ CHAR CompObj_magic[8]; /* always "CompObj" */ +/*09*/ CHAR dir_magic[4]; /* always "dir" */ +} SLTG_Magic; + +#define SLTG_COMPOBJ_MAGIC "CompObj" +#define SLTG_DIR_MAGIC "dir" + +/* Next we have SLTG_Header.nrOfFileBlks - 2 of Index strings. These +are persumbably unique to within the file and look something like +"AAAAAAAAAA" with the first character incremented from 'A' to ensure +uniqueness. I guess successive chars increment when we need to wrap +the first one. */ + +typedef struct { +/*00*/ CHAR string[11]; +} SLTG_Index; + + +/* This is followed by SLTG_pad9 */ +typedef struct { +/*00*/ CHAR pad[9]; /* 9 '\0's */ +} SLTG_Pad9; + + +/* Now we have the noOfFileBlks - 1 worth of blocks. The length of +each block is given by its entry in SLTG_BlkEntry. */ + +/* type SLTG_NAME in rather like a BSTR except that the length in +bytes is given by the first WORD and the string contains 8bit chars */ + +typedef WORD SLTG_Name; + +/* The main library block looks like this. This one seems to come last */ + +typedef struct { +/*00*/ WORD magic; /* 0x51cc */ +/*02*/ WORD res02; /* 0x0003, 0x0004 */ +/*04*/ WORD name; /* offset to name in name table */ +/*06*/ SLTG_Name res06; /* maybe this is just WORD == 0xffff */ + SLTG_Name helpstring; + SLTG_Name helpfile; + DWORD helpcontext; + WORD syskind; /* == 1 for win32, 0 for win16 */ + WORD lcid; /* == 0x409, 0x809 etc */ + DWORD res12; /* == 0 */ + WORD libflags; /* LIBFLAG_* */ + WORD maj_vers; + WORD min_vers; + GUID uuid; +} SLTG_LibBlk; + +#define SLTG_LIBBLK_MAGIC 0x51cc + +/* we then get 0x40 bytes worth of 0xffff or small numbers followed by + nrOfFileBlks - 2 of these */ +typedef struct { + WORD small_no; + SLTG_Name index_name; /* This refers to a name in the directory */ + SLTG_Name other_name; /* Another one of these weird names */ + WORD res1a; /* 0xffff */ + WORD name_offs; /* offset to name in name table */ + WORD more_bytes; /* if this is non-zero we get this many + bytes before the next element, which seem + to reference the docstring of the type ? */ + WORD res20; /* 0xffff */ + DWORD helpcontext; + WORD res26; /* 0xffff */ + GUID uuid; +} SLTG_OtherTypeInfo; + +/* Next we get WORD 0x0003 followed by a DWORD which if we add to +0x216 gives the offset to the name table from the start of the LibBlk +struct */ + +typedef struct { +/*00*/ WORD magic; /* 0x0501 */ +/*02*/ DWORD href_table; /* if not 0xffffffff, then byte offset from + beginning of struct to href table */ +/*06*/ DWORD res06; /* 0xffffffff */ +/*0a*/ DWORD elem_table; /* offset to members */ +/*0e*/ DWORD res0e; /* 0xffffffff */ +/*12*/ WORD major_version; /* major version number */ +/*14*/ WORD minor_version; /* minor version number */ +/*16*/ DWORD res16; /* 0xfffe0000 */ +/*1a*/ BYTE typeflags1;/* 0x02 | top 5 bits hold l5sbs of TYPEFLAGS */ +/*1b*/ BYTE typeflags2;/* TYPEFLAGS >> 5 */ +/*1c*/ BYTE typeflags3;/* 0x02*/ +/*1d*/ BYTE typekind; /* 0x03 == TKIND_INTERFACE etc. */ +/*1e*/ DWORD res1e; /* 0x00000000 or 0xffffffff */ +} SLTG_TypeInfoHeader; + +#define SLTG_TIHEADER_MAGIC 0x0501 + +typedef struct { +/*00*/ WORD res00; /* 0x0001 sometimes 0x0003 ?? */ +/*02*/ WORD res02; /* 0xffff */ +/*04*/ BYTE res04; /* 0x01 */ +/*05*/ DWORD cbExtra; /* No of bytes that follow */ +} SLTG_MemberHeader; + +typedef struct { +/*00*/ WORD magic; /* 0x120a */ +/*02*/ WORD next; /* offset in bytes to next block from start of block + group, 0xffff if last item */ +/*04*/ WORD name; /* offset to name within name table */ +/*06*/ WORD value; /* offset to value from start of block group */ +/*08*/ WORD res08; /* 0x56 */ +/*0a*/ DWORD memid; /* memid */ +/*0e*/ WORD helpcontext;/* 0xfffe == no context, 0x0001 == stored in EnumInfo struct, else offset + to value from start of block group */ +/*10*/ WORD helpstring;/* offset from start of block group to string offset */ +} SLTG_EnumItem; + +#define SLTG_ENUMITEM_MAGIC 0x120a + + +typedef struct { + BYTE magic; /* 0x4c or 0x6c */ + BYTE inv; /* high nibble is INVOKE_KIND, low nibble = 2 */ + WORD next; /* byte offset from beginning of group to next fn */ + WORD name; /* Offset within name table to name */ + DWORD dispid; /* dispid */ + WORD helpcontext; /* helpcontext (again 1 is special) */ + WORD helpstring;/* helpstring offset to offset */ + WORD arg_off; /* offset to args from start of block */ + BYTE nacc; /* lowest 3bits are CALLCONV, rest are no of args */ + BYTE retnextopt;/* if 0x80 bit set ret type follows else next WORD + is offset to ret type. No of optional args is + middle 6 bits */ + WORD rettype; /* return type VT_?? or offset to ret type */ + WORD vtblpos; /* position in vtbl? */ + WORD funcflags; /* present if magic == 0x6c */ +/* Param list starts, repeat next two as required */ +#if 0 + WORD name; /* offset to 2nd letter of name */ + WORD+ type; /* VT_ of param */ +#endif +} SLTG_Function; + +#define SLTG_FUNCTION_MAGIC 0x4c +#define SLTG_FUNCTION_WITH_FLAGS_MAGIC 0x6c + +typedef struct { +/*00*/ BYTE magic; /* 0xdf */ +/*01*/ BYTE res01; /* 0x00 */ +/*02*/ DWORD res02; /* 0xffffffff */ +/*06*/ DWORD res06; /* 0xffffffff */ +/*0a*/ DWORD res0a; /* 0xffffffff */ +/*0e*/ DWORD res0e; /* 0xffffffff */ +/*12*/ DWORD res12; /* 0xffffffff */ +/*16*/ DWORD res16; /* 0xffffffff */ +/*1a*/ DWORD res1a; /* 0xffffffff */ +/*1e*/ DWORD res1e; /* 0xffffffff */ +/*22*/ DWORD res22; /* 0xffffffff */ +/*26*/ DWORD res26; /* 0xffffffff */ +/*2a*/ DWORD res2a; /* 0xffffffff */ +/*2e*/ DWORD res2e; /* 0xffffffff */ +/*32*/ DWORD res32; /* 0xffffffff */ +/*36*/ DWORD res36; /* 0xffffffff */ +/*3a*/ DWORD res3a; /* 0xffffffff */ +/*3e*/ DWORD res3e; /* 0xffffffff */ +/*42*/ WORD res42; /* 0xffff */ +/*44*/ DWORD number; /* this is 8 times the number of refs */ +/*48*/ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ + +/*50*/ WORD res50; /* 0xffff */ +/*52*/ BYTE res52; /* 0x01 */ +/*53*/ DWORD res53; /* 0x00000000 */ +/*57*/ SLTG_Name names[1]; + /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii + * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the + * ref refers to the nth type listed in this library (0 based). Else + * the xxxx (which maybe fewer than 4 digits) is the offset into the name + * table to a string "*\G{}#1.0#0#C:\WINNT\System32\stdole32.tlb#" + * The guid is the typelib guid; the ref again refers to the nth type of + * the imported typelib. + */ + +/*xx*/ BYTE resxx; /* 0xdf */ + +} SLTG_RefInfo; + +#define SLTG_REF_MAGIC 0xdf + +typedef struct { + WORD res00; /* 0x0001 */ + BYTE res02; /* 0x02 */ + BYTE res03; /* 0x40 if internal ref, 0x00 if external ? */ + WORD res04; /* 0xffff */ + WORD res06; /* 0x0000, 0x0013 or 0xffff ?? */ +} SLTG_UnknownRefInfo; + +typedef struct { + WORD res00; /* 0x004a */ + WORD next; /* byte offs to next interface */ + WORD res04; /* 0xffff */ + BYTE impltypeflags; /* IMPLTYPEFLAG_* */ + BYTE res07; /* 0x80 */ + WORD res08; /* 0x0012, 0x0028 ?? */ + WORD ref; /* number in ref table ? */ + WORD res0c; /* 0x4000 */ + WORD res0e; /* 0xfffe */ + WORD res10; /* 0xffff */ + WORD res12; /* 0x001d */ + WORD pos_in_table; /* 0x0, 0x4, ? */ +} SLTG_ImplInfo; + +#define SLTG_IMPL_MAGIC 0x004a + +typedef struct { + BYTE magic; /* 0x0a */ + BYTE typepos; + WORD next; + WORD name; + WORD byte_offs; /* pos in struct */ + WORD type; /* if typepos == 0x02 this is the type, else offset to type */ + DWORD memid; + WORD helpcontext; /* ?? */ + WORD helpstring; /* ?? */ +} SLTG_RecordItem; + +#define SLTG_RECORD_MAGIC 0x0a + + +/* CARRAYs look like this +WORD type == VT_CARRAY +WORD offset from start of block to SAFEARRAY +WORD typeofarray +*/ + +#include "poppack.h" /*---------------------------END--------------------------------------------*/ #endif + +