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