Commit e3b8640c authored by Juergen Schmied's avatar Juergen Schmied Committed by Alexandre Julliard

- better loading of *.tlb files

- seperated code for loading tlb resource into memory from code for parsing the tlb resource.
parent 4d678923
...@@ -160,7 +160,8 @@ HRESULT WINAPI LoadTypeLib16( ...@@ -160,7 +160,8 @@ HRESULT WINAPI LoadTypeLib16(
* Success: S_OK * Success: S_OK
* Failure: Status * Failure: Status
*/ */
int TLB_ReadTypeLib(PCHAR file, ITypeLib **ppTypelib); int TLB_ReadTypeLib(PCHAR file, ITypeLib2 **ppTypelib);
HRESULT WINAPI LoadTypeLib( HRESULT WINAPI LoadTypeLib(
OLECHAR *szFile, /* [in] Name of file to load from */ OLECHAR *szFile, /* [in] Name of file to load from */
ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */ ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
...@@ -191,7 +192,7 @@ HRESULT WINAPI LoadTypeLibEx( ...@@ -191,7 +192,7 @@ HRESULT WINAPI LoadTypeLibEx(
if(regkind != REGKIND_NONE) if(regkind != REGKIND_NONE)
FIXME ("registration of typelibs not supported yet!\n"); FIXME ("registration of typelibs not supported yet!\n");
res= TLB_ReadTypeLib(p, pptLib); res= TLB_ReadTypeLib(p, (ITypeLib2**)pptLib);
HeapFree(GetProcessHeap(),0,p); HeapFree(GetProcessHeap(),0,p);
TRACE(" returns %08lx\n",res); TRACE(" returns %08lx\n",res);
...@@ -351,7 +352,7 @@ typedef struct tagITypeLibImpl ...@@ -351,7 +352,7 @@ typedef struct tagITypeLibImpl
static struct ICOM_VTABLE(ITypeLib2) tlbvt; static struct ICOM_VTABLE(ITypeLib2) tlbvt;
/* ITypeLib methods */ /* ITypeLib methods */
static ITypeLib2* ITypeLib2_Constructor(); static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib);
/*======================= ITypeInfo implementation =======================*/ /*======================= ITypeInfo implementation =======================*/
...@@ -1072,231 +1073,263 @@ ITypeInfoImpl * TLB_DoTypeInfo( ...@@ -1072,231 +1073,263 @@ ITypeInfoImpl * TLB_DoTypeInfo(
return ptiRet; return ptiRet;
} }
int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib **ppTypeLib) /****************************************************************************
* TLB_ReadTypeLib
*
* find the type of the typelib file and map the typelib resource into
* the memory
*/
#define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
int TLB_ReadTypeLib(LPSTR pszFileName, ITypeLib2 **ppTypeLib)
{ {
TLBContext cx;
long lPSegDir;
ITypeLibImpl* pLibInfo=NULL;
TLB2Header tlbHeader;
TLBSegDir tlbSegDir;
HINSTANCE hinstDLL;
int ret = E_FAIL; int ret = E_FAIL;
HRSRC hrsrc; DWORD dwSignature = 0;
HGLOBAL hGlobal; HFILE hFile;
LPVOID pLib;
TRACE("%s\n", pszFileName); TRACE("%s\n", pszFileName);
/* find the typelibrary resource*/ *ppTypeLib = NULL;
hinstDLL = LoadLibraryExA(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hinstDLL)
{
ERR("error: couldn't load the DLL %s\n", pszFileName);
goto err1;
}
hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(1), "TYPELIB"); /* check the signature of the file */
if (!hrsrc) hFile = CreateFileA( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, -1 );
if (INVALID_HANDLE_VALUE != hFile)
{ {
ERR("error: couldn't find initial TLB data\n"); HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
goto err2; if (hMapping)
{
LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if(pBase)
{
/* first try to load as *.tlb */
dwSignature = *((DWORD*) pBase);
if ( dwSignature == MSFT_SIGNATURE)
{
*ppTypeLib = ITypeLib2_Constructor(pBase);
}
UnmapViewOfFile(pBase);
}
CloseHandle(hMapping);
}
CloseHandle(hFile);
} }
hGlobal = LoadResource(hinstDLL, hrsrc); if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
if (!hGlobal)
{ {
ERR("error: couldn't load TLB data from DLL\n"); /* find the typelibrary resource*/
goto err2; HINSTANCE hinstDLL = LoadLibraryExA(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
if (hinstDLL)
{
HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(1), "TYPELIB");
if (hrsrc)
{
HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
if (hGlobal)
{
LPVOID pBase = LockResource(hGlobal);
if (pBase)
{
*ppTypeLib = ITypeLib2_Constructor(pBase);
}
FreeResource( hGlobal );
}
}
FreeLibrary(hinstDLL);
}
} }
pLib = LockResource(hGlobal); if(*ppTypeLib)
if (! pLib) ret = S_OK;
{ else
goto err3; ERR("Loading of typelib %s failed with error 0x%08lx\n", pszFileName, GetLastError());
}
return ret;
}
/*================== ITypeLib(2) Methods ===================================*/
/****************************************************************************
* ITypeLib2_Constructor
*
* loading a typelib from a in-memory image
*/
static ITypeLib2* ITypeLib2_Constructor(LPVOID pLib)
{
TLBContext cx;
long lPSegDir;
TLB2Header tlbHeader;
TLBSegDir tlbSegDir;
ITypeLibImpl * pTypeLibImpl;
TRACE("found at %p\n", pLib); TRACE("%p\n", pLib);
pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
if (!pTypeLibImpl) return NULL;
ICOM_VTBL(pTypeLibImpl) = &tlbvt;
pTypeLibImpl->ref = 1;
/* get pointer to beginning of typelib data */ /* get pointer to beginning of typelib data */
cx.pos = 0; cx.pos = 0;
cx.oStart=0; cx.oStart=0;
cx.mapping = pLib; cx.mapping = pLib;
cx.pLibInfo = pTypeLibImpl;
pLibInfo = (ITypeLibImpl*) ITypeLib2_Constructor();
if (!pLibInfo)
{
ret = E_OUTOFMEMORY;
goto err3;
}
cx.pLibInfo=pLibInfo;
/* read header */ /* read header */
TRACE("read header\n");
TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0); TLB_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
TRACE("read header (0x%08x 0x%08x)\n",tlbHeader.magic1,tlbHeader.magic2 ); TRACE("read header (0x%08x 0x%08x)\n",tlbHeader.magic1,tlbHeader.magic2 );
/* there is a small number of information here until the next important /* there is a small number of information here until the next important
* part: * part:
* the segment directory . Try to calculate the amount of data */ * the segment directory . Try to calculate the amount of data */
lPSegDir=sizeof(tlbHeader)+ lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + (tlbHeader.varflags & HELPDLLFLAG? 4 :0);
(tlbHeader.nrtypeinfos)*4+
(tlbHeader.varflags & HELPDLLFLAG? 4 :0);
/* now read the segment directory */ /* now read the segment directory */
TRACE("read segment directory\n"); TRACE("read segment directory\n");
TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir); TLB_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
cx.pTblDir=&tlbSegDir; cx.pTblDir = &tlbSegDir;
/* just check two entries */ /* just check two entries */
if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
tlbSegDir.pImpInfo.res0c != 0x0F {
) {
ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir); ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
goto err3; HeapFree(GetProcessHeap(),0,pTypeLibImpl);
return NULL;
} }
/* now fill our internal data */ /* now fill our internal data */
/* TLIBATTR fields */ /* TLIBATTR fields */
TLB_ReadGuid(&pLibInfo->LibAttr.guid, tlbHeader.posguid, &cx); TLB_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
pLibInfo->LibAttr.lcid=tlbHeader.lcid; pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
pLibInfo->LibAttr.syskind=tlbHeader.varflags & 0x0f; /* check the mask */ pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
pLibInfo->LibAttr.wMajorVerNum=LOWORD(tlbHeader.version); pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
pLibInfo->LibAttr.wMinorVerNum=HIWORD(tlbHeader.version); pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
pLibInfo->LibAttr.wLibFlags=(WORD) tlbHeader.flags & 0xffff;/* check mask */ pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
/* name, eventually add to a hash table */ /* name, eventually add to a hash table */
pLibInfo->Name=TLB_ReadName(&cx, tlbHeader.NameOffset); pTypeLibImpl->Name = TLB_ReadName(&cx, tlbHeader.NameOffset);
/* help info */ /* help info */
pLibInfo->DocString=TLB_ReadString(&cx, tlbHeader.helpstring); pTypeLibImpl->DocString = TLB_ReadString(&cx, tlbHeader.helpstring);
pLibInfo->HelpFile=TLB_ReadString(&cx, tlbHeader.helpfile); pTypeLibImpl->HelpFile = TLB_ReadString(&cx, tlbHeader.helpfile);
if( tlbHeader.varflags & HELPDLLFLAG){
if( tlbHeader.varflags & HELPDLLFLAG)
{
int offset; int offset;
TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader)); TLB_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
pLibInfo->HelpStringDll=TLB_ReadString(&cx, offset); pTypeLibImpl->HelpStringDll = TLB_ReadString(&cx, offset);
} }
pLibInfo->dwHelpContext=tlbHeader.helpstringcontext; pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
/* custom data */ /* custom data */
if(tlbHeader.CustomDataOffset >= 0) { if(tlbHeader.CustomDataOffset >= 0)
pLibInfo->ctCustData= {
TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pLibInfo->pCustData); pTypeLibImpl->ctCustData = TLB_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
} }
/* fill in typedescriptions */ /* fill in typedescriptions */
if(tlbSegDir.pTypdescTab.length >0){ if(tlbSegDir.pTypdescTab.length > 0)
int i, j, cTD=tlbSegDir.pTypdescTab.length / (2*sizeof(INT)); {
int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
INT16 td[4]; INT16 td[4];
pLibInfo->pTypeDesc= pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
TLB_Alloc( cTD * sizeof(TYPEDESC));
TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset); TLB_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
for(i=0;i<cTD;){ for(i=0; i<cTD; )
{
/* FIXME: add several sanity checks here */ /* FIXME: add several sanity checks here */
pLibInfo->pTypeDesc[i].vt=td[0] & VT_TYPEMASK; pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
if(td[0]==VT_PTR ||td[0]==VT_SAFEARRAY){/* FIXME: check safearray */ if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
if(td[3]<0) {
V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)= /* FIXME: check safearray */
& stndTypeDesc[td[2]]; if(td[3] < 0)
V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & stndTypeDesc[td[2]];
else else
V_UNION(&(pLibInfo->pTypeDesc[i]),lptdesc)= V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lptdesc)= & pTypeLibImpl->pTypeDesc[td[3]/8];
& pLibInfo->pTypeDesc[td[3]/8]; }
}else if(td[0]==VT_CARRAY) else if(td[0] == VT_CARRAY)
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)= {
(void *)((int) td[2]); /* temp store offset in*/ /* array descr table here */
/* array descr table here */ V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = (void *)((int) td[2]); /* temp store offset in*/
else if(td[0]==VT_USERDEFINED) }
V_UNION(&(pLibInfo->pTypeDesc[i]),hreftype)=MAKELONG(td[2],td[3]); else if(td[0] == VT_USERDEFINED)
if(++i<cTD) TLB_Read(td, sizeof(td), &cx, DO_NOT_SEEK); {
V_UNION(&(pTypeLibImpl->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 */ /* second time around to fill the array subscript info */
for(i=0;i<cTD;i++){ for(i=0;i<cTD;i++)
if(pLibInfo->pTypeDesc[i].vt != VT_CARRAY) continue; {
if(tlbSegDir.pArrayDescriptions.offset>0){ if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + if(tlbSegDir.pArrayDescriptions.offset>0)
(int) V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)); {
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)= TLB_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc));
TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1)); V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
if(td[1]<0) if(td[1]<0)
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem.vt=td[0] & VT_TYPEMASK; V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem.vt = td[0] & VT_TYPEMASK;
else else
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->tdescElem=stndTypeDesc[td[0]/8]; V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->tdescElem = stndTypeDesc[td[0]/8];
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->cDims=td[2];
for(j=0;j<td[2];j++){ V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->cDims = td[2];
TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements,
for(j = 0; j<td[2]; j++)
{
TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].cElements,
sizeof(INT), &cx, DO_NOT_SEEK); sizeof(INT), &cx, DO_NOT_SEEK);
TLB_Read(& V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc) TLB_Read(& V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc)->rgbounds[j].lLbound,
->rgbounds[j].lLbound,
sizeof(INT), &cx, DO_NOT_SEEK); sizeof(INT), &cx, DO_NOT_SEEK);
} }
}else{ }
V_UNION(&(pLibInfo->pTypeDesc[i]),lpadesc)=NULL; else
{
V_UNION(&(pTypeLibImpl->pTypeDesc[i]),lpadesc) = NULL;
ERR("didn't find array description data\n"); ERR("didn't find array description data\n");
} }
} }
} }
/* imported type libs */ /* imported type libs */
if(tlbSegDir.pImpFiles.offset>0){ if(tlbSegDir.pImpFiles.offset>0)
TLBImpLib **ppImpLib=&(pLibInfo->pImpLibs); {
int offset=tlbSegDir.pImpFiles.offset; TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
int oGuid; int oGuid, offset = tlbSegDir.pImpFiles.offset;
UINT16 size; UINT16 size;
while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length){
*ppImpLib=TLB_Alloc(sizeof(TLBImpLib)); while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
(*ppImpLib)->offset=offset - tlbSegDir.pImpFiles.offset; {
*ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
(*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
TLB_Read(&oGuid, sizeof(INT), &cx, offset); TLB_Read(&oGuid, sizeof(INT), &cx, offset);
TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx); TLB_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
/* we are skipping some unknown info here */ /* we are skipping some unknown info here */
TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT))); TLB_Read(& size,sizeof(UINT16), &cx, offset+3*(sizeof(INT)));
size >>=2; size >>= 2;
(*ppImpLib)->name=TLB_Alloc(size+1); (*ppImpLib)->name = TLB_Alloc(size+1);
TLB_Read((*ppImpLib)->name,size, &cx, DO_NOT_SEEK); TLB_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
offset=(offset+3*(sizeof(INT))+sizeof(UINT16)+size+3) & 0xfffffffc; offset = (offset + 3 * (sizeof(INT)) + sizeof(UINT16) + size + 3) & 0xfffffffc;
ppImpLib=&(*ppImpLib)->next; ppImpLib = &(*ppImpLib)->next;
} }
} }
/* type info's */ /* type info's */
if(tlbHeader.nrtypeinfos >=0 ) if(tlbHeader.nrtypeinfos >= 0 )
{ {
/*pLibInfo->TypeInfoCount=tlbHeader.nrtypeinfos; */ /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
ITypeInfoImpl **ppTI = &(pLibInfo->pTypeInfo); ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
int i; int i;
for(i=0;i<(int)tlbHeader.nrtypeinfos;i++) for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
{ {
*ppTI = TLB_DoTypeInfo(&cx, i, pLibInfo); *ppTI = TLB_DoTypeInfo(&cx, i, pTypeLibImpl);
ppTI = &((*ppTI)->next); ppTI = &((*ppTI)->next);
(pLibInfo->TypeInfoCount)++; (pTypeLibImpl->TypeInfoCount)++;
} }
} }
*ppTypeLib=(LPTYPELIB)pLibInfo;
ret = S_OK;
err3:
FreeResource( hGlobal );
err2:
FreeLibrary(hinstDLL);
err1:
return ret;
}
/*================== ITypeLib(2) Methods ===================================*/
static ITypeLib2* ITypeLib2_Constructor()
{
ITypeLibImpl * pTypeLibImpl;
pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
if (pTypeLibImpl)
{
ICOM_VTBL(pTypeLibImpl) = &tlbvt;
pTypeLibImpl->ref = 1;
}
TRACE("(%p)\n", pTypeLibImpl); TRACE("(%p)\n", pTypeLibImpl);
return (ITypeLib2*) pTypeLibImpl; return (ITypeLib2*) pTypeLibImpl;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment