/* * TYPELIB * * Copyright 1997 Marcus Meissner * 1999 Rein Klazes * there is much left to do here before it can be useful for real world * programs * know problems: * -. Only one format of typelibs is supported * -. All testing so far 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 entirety 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 stuff ignored * -. move stuff 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 #include #include #include #include "winerror.h" #include "winreg.h" /* for HKEY_LOCAL_MACHINE */ #include "winnls.h" /* for PRIMARYLANGID */ #include "wine/winbase16.h" /* for RegQueryValue16(HKEY,LPSTR,LPSTR,LPDWORD) */ #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" typedef struct tagTLBContext { unsigned int oStart; /* start of TLB in file */ unsigned int pos; /* current pos */ unsigned int length; /* total length */ void *mapping; /* memory mapping */ TLBSegDir * pTblDir; TLBLibInfo* pLibInfo; } TLBContext; DEFAULT_DEBUG_CHANNEL(ole); DECLARE_DEBUG_CHANNEL(typelib); /**************************************************************************** * QueryPathOfRegTypeLib16 [TYPELIB.14] * * the path is "Classes\Typelib\\.\\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,"",(DWORD)guid); FIXME("(%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("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,"",(DWORD)guid); FIXME("(%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("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( LPOLESTR szFile, /* [in] Name of file to load from */ void * *pptLib) /* [out] Pointer to pointer to loaded type library */ { FIXME("('%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 */ { return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib); } /****************************************************************************** * LoadTypeLibEx [OLEAUT32.183] * Loads and optionally registers a type library * * RETURNS * Success: S_OK * Failure: Status */ HRESULT WINAPI LoadTypeLibEx( LPOLESTR szFile, /* [in] Name of file to load from */ REGKIND regkind, /* specify kind of registration */ ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */ { LPSTR p; HRESULT res; TRACE("('%s',%d,%p)\n",debugstr_w(szFile), regkind, pptLib); p=HEAP_strdupWtoA(GetProcessHeap(),0,szFile); if(regkind != REGKIND_NONE) FIXME ("registration of typelibs not supported yet!\n"); res= TLB_ReadTypeLib(p, pptLib); /* XXX need to free p ?? */ TRACE(" 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("(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("(%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("(IID: %s): stub\n",xriid); return S_OK; /* FIXME: pretend everything is OK */ } /**************************************************************************** * OaBuildVersion (TYPELIB.15) * * known TYPELIB.DLL versions: * * OLE 2.01 no OaBuildVersion() avail 1993 -- --- * OLE 2.02 1993-94 02 3002 * OLE 2.03 23 730 * OLE 2.03 03 3025 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024 * OLE 2.1 NT 1993-95 ?? ??? * OLE 2.3.1 W95 23 700 */ DWORD WINAPI OaBuildVersion16(void) { FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n"); switch(VERSION_GetVersion()) { case WIN31: return MAKELONG(3027, 3); /* WfW 3.11 */ case WIN95: return MAKELONG(700, 23); /* Win95A */ case WIN98: return MAKELONG(3024, 10); /* W98 SE */ default: FIXME_(ole)("Version value not known yet. Please investigate it !"); return 0; } } /* 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 = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE 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 = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE 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() { DebugBreak(); } static void * TLB_Alloc(unsigned size) { void * ret; if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){ /* FIXME */ ERR("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("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 ) { if (where != DO_NOT_SEEK) { where += pcx->oStart; if (where > pcx->length) { /* FIXME */ ERR("seek beyond end (%ld/%d)\n", where, pcx->length ); TLB_abort(); } pcx->pos = where; } if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos; memcpy( buffer, (char *)pcx->mapping + pcx->pos, count ); pcx->pos += count; return count; } 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("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;iName=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(¶minfo,sizeof(paraminfo), pcx, recoffset+reclength - pFuncRec->nrargs * sizeof(TLBParameterInfo)); for(j=0;jnrargs;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(¶minfo,sizeof(TLBParameterInfo), pcx, DO_NOT_SEEK); } /* second time around */ for(j=0;jnrargs;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;iName=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("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;ipTblDir->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("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("type library format not (yet) implemented\n"); else ERR("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; HANDLE hFile, hMap; if((hFile=OpenFile(file, &ofStruct, OF_READ))==HFILE_ERROR) { ERR("cannot open %s error 0x%lx\n",file, GetLastError()); return E_FAIL; } cx.length = SetFilePointer( hFile, 0, NULL, FILE_END ); if (!(hMap = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL ))) { CloseHandle( hFile ); ERR("cannot map %s error 0x%lx\n",file, GetLastError()); return E_FAIL; } CloseHandle( hFile ); cx.mapping = MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 ); CloseHandle( hMap ); if (!cx.mapping) { ERR("cannot map view of %s error 0x%lx\n",file, GetLastError()); return E_FAIL; } /* get pointer to beginning of typelib data */ cx.pos = 0; cx.oStart=0; if((oStart=TLB_FindTlb(&cx))<0){ if(oStart==-1) ERR("cannot locate typelib in %s\n",file); else ERR("unsupported typelib format in %s\n",file); UnmapViewOfFile( cx.mapping ); return E_FAIL; } cx.oStart=oStart; pLibInfo=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TLBLibInfo)); if (!pLibInfo){ UnmapViewOfFile( cx.mapping ); 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("cannot find the table directory, ptr=0x%lx\n",lPSegDir); UnmapViewOfFile( cx.mapping ); 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;ipTypeDesc[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(++ipTypeDesc[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;jpTypeDesc[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("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)++; } } UnmapViewOfFile( cx.mapping ); *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("(%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){ ITypeLib_AddRef(This); TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); return S_OK; } TRACE("-- Interface: E_NOINTERFACE\n"); return E_NOINTERFACE; } /* ITypeLib::AddRef */ static ULONG WINAPI ITypeLib_fnAddRef( LPTYPELIB iface) { ICOM_THIS( TLBLibInfo, iface); TRACE("(%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("(%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("(%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("(%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("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo); return S_OK; } TRACE("-- 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("(%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("-- found Type (%p)->%d\n",pTKind,*pTKind); return S_OK; } TRACE("-- 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("(%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("-- found (%p)->(%p)\n",ppTLBTInfo,*ppTLBTInfo); return S_OK; } TRACE("-- 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("(%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("(%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("(%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;ifuncdesc.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("(%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;ifuncdesc.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("(%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("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("(%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("(%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("(%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("(%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(" 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("(%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){ ITypeInfo_AddRef(iface); TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject); return S_OK; } TRACE("-- Interface: E_NOINTERFACE\n"); return E_NOINTERFACE; } /* ITypeInfo::AddRef */ static ULONG WINAPI ITypeInfo_fnAddRef( LPTYPEINFO iface) { ICOM_THIS( TLBTypeInfo, iface); TRACE("(%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("(%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("(%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("(%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("(%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("(%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("(%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; ifuncdesc.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=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames); ITypeInfo_Release(pTInfo); return result; } WARN("Could not search inherited interface!\n"); } else WARN("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("(%p) index %d\n", This, index); for(i=0, pIref=This->impltypelist; inext) ; 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("(%p) index %d\n", This, index); for(i=0, pIref=This->impltypelist; inext) ; 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("(%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; jfuncdesc.cParams; j++) if(strcmp(aszPar,pFDesc->pParamDesc[j].Name)) break; if( jfuncdesc.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=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->reference, &pTInfo); if(SUCCEEDED(ret)){ ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId ); ITypeInfo_Release(pTInfo); return ret; } WARN("Could not search inherited interface!\n"); } else WARN("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("(%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("(%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("(%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=ITypeLib_GetTypeInfo(pTLib, HREFTYPE_INDEX(hRefType), ppTInfo); ITypeLib_Release(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=ITypeLib_GetTypeInfoOfGuid( (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=ITypeLib_GetTypeInfoOfGuid( (LPTYPELIB)pTypeLib, &pRefType->guid, ppTInfo); pRefType->pImpTLInfo->pImpTypeLib=pTypeLib; } } } TRACE("(%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("(%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("(%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("(%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; ITypeLib_AddRef(*ppTLib); TRACE("(%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("(%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("(%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("(%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("(%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("(%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("(%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("(%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("(%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("(%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 && indexParamfuncdesc.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("(%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("(%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("(%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("(%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("(%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(" 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("(%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(" 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("(%p) index %d\n", This, indexFunc); for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++, pFDesc=pFDesc->next) ; if(pFDesc && indexParam >=0 && indexParamfuncdesc.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(" 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("(%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(" 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("(%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(" OUT OF MEMORY! \n"); return E_OUTOFMEMORY; } return S_OK; } return TYPE_E_ELEMENTNOTFOUND; }