Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

5256 lines
164 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999.
//
// File: tlgen.cxx
//
// Contents: type library generation methods
//
// Classes: various
//
// Functions: various
//
// History: 4-10-95 stevebl Created
//
//----------------------------------------------------------------------------
#pragma warning ( disable : 4514 4706 )
#include "tlcommon.hxx"
#include "tlgen.hxx"
#include "tllist.hxx"
#include "becls.hxx"
#include "walkctxt.hxx"
#include "ilxlat.hxx"
#include "midlvers.h"
#include <time.h>
#define SHOW_ERROR_CODES 1
extern "C"
BOOL
Is64BitEnv()
{
return pCommand->Is64BitEnv();
}
//+---------------------------------------------------------------------------
//
// Notes on CG_STATUS return types:
//
// CG_STATUS is an enumeration which can have the following values:
// CG_OK, CG_NOT_LAYED_OUT, and CG_REF_NOT_LAYED_OUT. The type generation
// methods assign the following meanings to these values:
//
// CG_OK => success
// CG_NOT_LAYED_OUT => the type info was created but (due to cyclic
// dependencies) LayOut() could not be called on it.
// CG_REF_NOT_LAYED_OUT => same as CG_NOT_LAYED_OUT except that the type
// is a referenced type: in other words, it is a
// pointer type or an array type.
//
// The methods in this file use the CG_STATUS value to help detect and
// correct errors that occur due to cyclic dependencies like this one:
//
// struct foo {
// int x;
// union bar * pBar; // the type (union bar *) is a referenced type
// };
//
// union bar {
// struct foo;
// }
//
// This creates a problem because ICreateTypeInfo::LayOut() will fail on any
// structure or union which contains another structure or union which has not
// already been layed out.
//
// If a structure (or union) receives a CG_STATUS value of CG_NOT_LAYED_OUT
// from any of its members, then it knows that it will not be able to call
// LayOut on itself and it will have to return CG_NOT_LAYED_OUT to tell
// its dependents that it hasn't been layed out.
//
// If (on the other hand) the structure (or union) receives
// CG_REF_NOT_LAYED_OUT from one or more of its members and CG_OK from all
// the others then it knows that there is a cyclic dependency somewhere,
// but that it WILL be able to call LayOut() because all of the members that
// encountered difficulty were references (pointers or arrays) to a cyclicly
// dependent type. Calling LayOut() may break the dependency (they may be
// waiting on this structure) and so LayOut must be called, and then all of
// the structure's members should be told to try again.
//
// If the structure receives CG_OK from all of its members, then there is
// no cyclic depency (or the cycle has already been broken), LayOut()
// may be called and CG_OK may be returned to the caller.
//
// Note that it is impossible to get in an unbreakable cyclic dependency
// because at some point in the cycle one of the members must be a
// referenced type.
//
//----------------------------------------------------------------------------
// Maintain a global pointer to the list of open ICreateTypeInfo pointers.
CObjHolder * gpobjholder;
// global pointer to the root ICreateTypeLibrary
ICreateTypeLib * pMainCTL = NULL;
char* szErrTypeFlags = "Could not set type flags";
char* szErrHelpString = "Could not set help string";
char* szErrHelpContext = "Could not set help context";
char* szErrVersion = "Could not set version";
char* szErrUUID = "Could not set UUID";
//+---------------------------------------------------------------------------
//
// Function: ReportTLGenError
//
// Synopsis: Generic routine for reporting typelib generation errors.
// Reports typelib generation error and then exits.
//
// Arguments: [szText] - description of failure
// [error_code] - typically an HRESULT
//
// History: 6-13-95 stevebl Commented
//
// Notes: The error code is only displayed if the
// SHOW_ERROR_CODES macro is defined.
//
// It is assumed that szText will never exceed 100 characters
// (minus space for the string representation of error_code).
// Since this is a local function, this is a safe assumption.
//
//----------------------------------------------------------------------------
void ReportTLGenError( char * szText, char * szName, long error_code)
{
char szBuffer [512];
// there are places we don't have an error_code, and pass in 0.
if ( error_code != 0 )
sprintf(szBuffer, ": %s : %s (0x%0X)", szText, szName, error_code);
else
sprintf(szBuffer, ": %s : %s", szText, szName);
RpcError("midl\\oleaut32.dll", 0, ERR_TYPELIB_GENERATION, szBuffer);
delete gpobjholder;
if (pMainCTL)
pMainCTL->Release();
exit(ERR_TYPELIB_GENERATION);
}
void ReportTLGenWarning( char * szText, char * szName, long error_code )
{
char szBuffer [512];
#ifdef SHOW_ERROR_CODES
sprintf(szBuffer, ": %s : %s (0x%0X)", szText, szName, error_code);
#else
sprintf(szBuffer, ": %s : %s", szText, szName);
#endif
RpcError("midl\\oleaut32.dll", 0, WARN_TYPELIB_GENERATION, szBuffer);
}
OLECHAR wszScratch [MAX_PATH];
extern CTypeLibraryList gtllist;
extern BOOL IsTempName( char * );
void GetValueFromExpression(VARIANT & var, TYPEDESC tdesc, expr_node * pExpr, LCID lcid, char * szSymName);
void ConvertToVariant(VARIANT & var, expr_node * pExpr, LCID lcid);
BOOL IsVariantBasedType(TYPEDESC tdesc)
{
while (tdesc.vt >= VT_PTR && tdesc.vt <= VT_CARRAY)
{
// This simplification works for VT_CARRAY as well as VT_PTR because
// the ARRAYDESC structure's first member is a TYPEDESC.
tdesc = *tdesc.lptdesc;
};
return tdesc.vt == VT_VARIANT;
}
//+---------------------------------------------------------------------------
//
// Function: DeleteTypedescChildren
//
// Synopsis: deletes all structures pointed to by a TYPEDESC so that the
// TYPEDESC can be safely deleted.
//
// Arguments: [ptd] - pointer to a TYEPDESC
//
// History: 6-13-95 stevebl Commented
//
// Notes: ptd is not deleted
//
//----------------------------------------------------------------------------
void DeleteTypedescChildren(TYPEDESC * ptd)
{
if (VT_CARRAY == ptd->vt)
{
DeleteTypedescChildren(&ptd->lpadesc->tdescElem);
delete ptd->lpadesc;
}
else if (VT_PTR == ptd->vt)
{
DeleteTypedescChildren(ptd->lptdesc);
delete ptd->lptdesc;
}
}
//+---------------------------------------------------------------------------
//
// Function: GetTypeFlags
//
// Synopsis: extracts TYPEFLAGS from a context
//
// Arguments: [pctxt] - pointer to the context
//
// Returns: TYPEFLAGS built from attributes found in the context
//
// Modifies: ATTR_TYPEDESCATTR, all ATTR_TYPE and all ATTR_MEMBER
// attributes are consumed from the context.
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
UINT GetTypeFlags(WALK_CTXT * pctxt)
{
UINT rVal = 0;
node_constant_attr * pTdescAttr = (node_constant_attr *) pctxt->ExtractAttribute(ATTR_TYPEDESCATTR);
if (pTdescAttr)
rVal = (short) pTdescAttr->GetExpr()->GetValue();
node_type_attr * pTA;
while (pTA = (node_type_attr *)pctxt->ExtractAttribute(ATTR_TYPE))
{
switch (pTA->GetAttr())
{
case TATTR_LICENSED:
rVal |= TYPEFLAG_FLICENSED;
break;
case TATTR_APPOBJECT:
rVal |= TYPEFLAG_FAPPOBJECT;
break;
case TATTR_CONTROL:
rVal |= TYPEFLAG_FCONTROL;
break;
case TATTR_DUAL:
rVal |= TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION;
break;
case TATTR_PROXY:
rVal |= TYPEFLAG_FPROXY;
break;
case TATTR_NONEXTENSIBLE:
rVal |= TYPEFLAG_FNONEXTENSIBLE;
break;
case TATTR_OLEAUTOMATION:
rVal |= TYPEFLAG_FOLEAUTOMATION;
break;
case TATTR_AGGREGATABLE:
rVal |= TYPEFLAG_FAGGREGATABLE;
break;
case TATTR_PUBLIC:
default:
break;
}
}
node_member_attr * pMA;
while (pMA = (node_member_attr *)pctxt->ExtractAttribute(ATTR_MEMBER))
{
switch (pMA->GetAttr())
{
case MATTR_RESTRICTED:
rVal |= TYPEFLAG_FRESTRICTED;
break;
case MATTR_PREDECLID:
rVal |= TYPEFLAG_FPREDECLID;
break;
case MATTR_REPLACEABLE:
rVal |= TYPEFLAG_FREPLACEABLE;
break;
default:
break;
}
}
if (pctxt->AttrInSummary(ATTR_HIDDEN))
{
rVal |= TYPEFLAG_FHIDDEN;
}
return rVal;
}
//+---------------------------------------------------------------------------
//
// Function: GetImplTypeFlags
//
// Synopsis: extracts IMPLTYPEFLAGS from a context
//
// Arguments: [pctxt] - pointer to the context
//
// Returns: IMPLTYPEFLAGS build from attributes found in the context
//
// Modifies: ATTR_DEFAULT, and all ATTR_MEMBER attributes are consumed from
// the context.
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
unsigned short GetImplTypeFlags(WALK_CTXT * pctxt)
{
unsigned short rVal = 0;
if (pctxt->ExtractAttribute(ATTR_DEFAULT))
rVal |= IMPLTYPEFLAG_FDEFAULT;
node_member_attr * pMA;
while (pMA = (node_member_attr *)pctxt->ExtractAttribute(ATTR_MEMBER))
{
switch(pMA->GetAttr())
{
case MATTR_SOURCE:
rVal |= IMPLTYPEFLAG_FSOURCE;
break;
case MATTR_RESTRICTED:
rVal |= IMPLTYPEFLAG_FRESTRICTED;
break;
case MATTR_DEFAULTVTABLE:
rVal |= IMPLTYPEFLAG_FDEFAULTVTABLE;
break;
default:
break;
}
}
return rVal;
}
//+---------------------------------------------------------------------------
//
// Function: GetIDLFlags
//
// Synopsis: extracts IDLFLAGS from a context
//
// Arguments: [pctxt] - pointer to a context
//
// Returns: IDLFLAGS built from attributes found in the context
//
// Modifies: ATTR_IDLDESCATTR, ATTR_OUT, and ATTR_IN attributes are
// consumed from the context.
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
unsigned short GetIDLFlags(WALK_CTXT * pctxt)
{
unsigned short rVal = 0;
node_constant_attr * pIDLDescAttr = (node_constant_attr *) pctxt->ExtractAttribute(ATTR_IDLDESCATTR);
if (pIDLDescAttr)
rVal = (short) pIDLDescAttr->GetExpr()->GetValue();
if (pctxt->AttrInSummary(ATTR_OUT))
rVal |= IDLFLAG_FOUT;
if (pctxt->AttrInSummary(ATTR_IN))
rVal |= IDLFLAG_FIN;
if (pctxt->AttrInSummary(ATTR_FLCID))
rVal |= IDLFLAG_FLCID;
return rVal;
}
//+---------------------------------------------------------------------------
//
// Function: GetVarFlags
//
// Synopsis: extracts VARFLAGS from a context
//
// Arguments: [pctxt] - pointer to a context
//
// Returns: VARFLAGS built from attributes found in the context
//
// Modifies: ATTR_VDESCATTR, ATTR_HIDDEN and all ATTR_MEMBER attributes
// are consumed from the context.
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
UINT GetVarFlags(WALK_CTXT * pctxt)
{
unsigned short rVal = 0;
node_constant_attr * pVdescAttr = (node_constant_attr *) pctxt->ExtractAttribute(ATTR_VARDESCATTR);
if (pVdescAttr)
rVal = (short) pVdescAttr->GetExpr()->GetValue();
node_member_attr * pMA;
while (pMA = (node_member_attr *)pctxt->ExtractAttribute(ATTR_MEMBER))
{
switch (pMA->GetAttr())
{
case MATTR_READONLY:
rVal |= VARFLAG_FREADONLY;
break;
case MATTR_SOURCE:
rVal |= VARFLAG_FSOURCE;
break;
case MATTR_BINDABLE:
rVal |= VARFLAG_FBINDABLE;
break;
case MATTR_DISPLAYBIND:
rVal |= VARFLAG_FDISPLAYBIND;
break;
case MATTR_DEFAULTBIND:
rVal |= VARFLAG_FDEFAULTBIND;
break;
case MATTR_REQUESTEDIT:
rVal |= VARFLAG_FREQUESTEDIT;
break;
case MATTR_UIDEFAULT:
rVal |= VARFLAG_FUIDEFAULT;
break;
case MATTR_NONBROWSABLE:
rVal |= VARFLAG_FNONBROWSABLE;
break;
case MATTR_DEFAULTCOLLELEM:
rVal |= VARFLAG_FDEFAULTCOLLELEM;
break;
case MATTR_IMMEDIATEBIND:
rVal |= VARFLAG_FIMMEDIATEBIND;
break;
case MATTR_REPLACEABLE:
rVal |= VARFLAG_FREPLACEABLE;
break;
case MATTR_RESTRICTED:
rVal |= VARFLAG_FRESTRICTED;
break;
default:
break;
}
}
if (pctxt->AttrInSummary(ATTR_HIDDEN))
{
rVal |= VARFLAG_FHIDDEN;
}
return rVal;
}
//+---------------------------------------------------------------------------
//
// Function: GetFuncFlags
//
// Synopsis: extracts FUNCFLAGS from a context
//
// Arguments: [pctxt] - pointer to a context
//
// Returns: FUNCFLAGS built from attributes found in the context
//
// Modifies: ATTR_FUNCDESCATTR, ATTR_HIDDEN and all ATTR_MEMBER attributes
// are consumed from the context.
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
UINT GetFuncFlags(WALK_CTXT * pctxt, BOOL * pfPropGet, BOOL * pfPropPut, BOOL * pfPropPutRef, BOOL * pfVararg)
{
unsigned short rVal = 0;
node_constant_attr * pVdescAttr = (node_constant_attr *) pctxt->ExtractAttribute(ATTR_FUNCDESCATTR);
if (pVdescAttr)
rVal = (short) pVdescAttr->GetExpr()->GetValue();
* pfPropGet = * pfPropPut = * pfPropPutRef = * pfVararg = FALSE;
node_member_attr * pMA;
while (pMA = (node_member_attr *)pctxt->ExtractAttribute(ATTR_MEMBER))
{
switch (pMA->GetAttr())
{
case MATTR_RESTRICTED:
rVal |= FUNCFLAG_FRESTRICTED;
break;
case MATTR_SOURCE:
rVal |= FUNCFLAG_FSOURCE;
break;
case MATTR_BINDABLE:
rVal |= FUNCFLAG_FBINDABLE;
break;
case MATTR_REQUESTEDIT:
rVal |= FUNCFLAG_FREQUESTEDIT;
break;
case MATTR_DISPLAYBIND:
rVal |= FUNCFLAG_FDISPLAYBIND;
break;
case MATTR_DEFAULTBIND:
rVal |= FUNCFLAG_FDEFAULTBIND;
break;
case MATTR_UIDEFAULT:
rVal |= FUNCFLAG_FUIDEFAULT;
break;
case MATTR_NONBROWSABLE:
rVal |= FUNCFLAG_FNONBROWSABLE;
break;
case MATTR_DEFAULTCOLLELEM:
rVal |= FUNCFLAG_FDEFAULTCOLLELEM;
break;
case MATTR_PROPGET:
*pfPropGet = TRUE;
break;
case MATTR_PROPPUT:
*pfPropPut = TRUE;
break;
case MATTR_PROPPUTREF:
*pfPropPutRef = TRUE;
break;
case MATTR_VARARG:
*pfVararg = TRUE;
break;
case MATTR_IMMEDIATEBIND:
rVal |= FUNCFLAG_FIMMEDIATEBIND;
break;
case MATTR_USESGETLASTERROR:
rVal |= FUNCFLAG_FUSESGETLASTERROR;
break;
case MATTR_REPLACEABLE:
rVal |= FUNCFLAG_FREPLACEABLE;
break;
default:
break;
}
}
// What about FUNCFLAG_FUSEGETLASTERROR?
if (pctxt->AttrInSummary(ATTR_HIDDEN))
{
rVal |= FUNCFLAG_FHIDDEN;
}
return rVal;
}
//+---------------------------------------------------------------------------
//
// Member: node_guid::GetGuid
//
// Synopsis: method to retrieve a GUID from a node_guid
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
void node_guid::GetGuid(_GUID & guid)
{
guid.Data1 = cStrs.Value.Data1;
guid.Data2 = cStrs.Value.Data2;
guid.Data3 = cStrs.Value.Data3;
memmove(guid.Data4, cStrs.Value.Data4, 8);
}
//+---------------------------------------------------------------------------
//
// Member: CG_NDR::CheckImportLib
//
// Synopsis: Checks to see if a particular CG node has a definition in
// an imported type libaray.
//
// Returns: NULL => the node has no imported definition
// !NULL => ITypeInfo pointer for the imported type definition
//
// History: 6-13-95 stevebl Commented
//
// Notes: It is possible that the CG node may have been created from
// an IDL file and yet this routine may stil return a pointer to
// an imported ITypeInfo.
//
// This is desirable.
//
// Because type libraries cannot represent as rich a set of
// information as IDL files can, the user may wish to directly
// include an IDL file containing a definintion of the type,
// thereby making the full IDL definition available for reference
// by other types. At the same time the user may wish to
// IMPORTLIB a type library describing the same type so that the
// new type library will be able to link directly to the imported
// ODL definition, rather than forcing the new type library to
// contain a definition of the imported type.
//
// This makes the assumption that although two definitions with
// the same name may exist in the global namespace, they will
// both refer to the same type.
//
//----------------------------------------------------------------------------
void * CG_NDR::CheckImportLib()
{
node_skl * pn = GetType();
node_file * pf = NULL;
void * pReturn;
for(;;)
{
if (pn->GetMyInterfaceNode())
{
pf = pn->GetDefiningFile();
}
else
{
pf = pn->GetDefiningTLB();
}
if (pf)
{
if (pf->GetImportLevel() > 0)
{
A2O(wszScratch, pn->GetSymName(), MAX_PATH);
pReturn = gtllist.FindName(pf->GetFileName(), wszScratch);
if (pReturn)
return pReturn;
}
else
return NULL;
}
NODE_T kind = pn->NodeKind();
if (kind != NODE_DEF && kind != NODE_HREF)
return NULL;
pn = pn->GetChild();
}
}
void * CG_TYPEDEF::CheckImportLib()
{
node_skl * pn = GetType();
node_file * pf = NULL;
void * pReturn;
if (pn->GetMyInterfaceNode())
{
pf = pn->GetDefiningFile();
}
else
{
pf = pn->GetDefiningTLB();
}
if (pf)
{
if (pf->GetImportLevel() > 0)
{
A2O(wszScratch, pn->GetSymName(), MAX_PATH);
pReturn = gtllist.FindName(pf->GetFileName(), wszScratch);
if (pReturn)
return pReturn;
}
}
return NULL;
}
typedef struct tagINTRINSIC
{
char * szType;
VARTYPE vt;
} INTRINSIC;
INTRINSIC rgIntrinsic [] =
{
"DATE", VT_DATE,
"HRESULT", VT_HRESULT,
"LPSTR", VT_LPSTR,
"LPWSTR", VT_LPWSTR,
"SCODE", VT_ERROR,
"VARIANT_BOOL", VT_BOOL,
"wireBSTR", VT_BSTR,
"BSTR", VT_BSTR,
"VARIANT", VT_VARIANT,
"wireVARIANT", VT_VARIANT,
"CURRENCY", VT_CY,
"CY", VT_CY,
"DATE", VT_DATE,
"DECIMAL", VT_DECIMAL,
};
//+---------------------------------------------------------------------------
//
// Member: CG_CLASS::GetTypeDesc
//
// Synopsis: Default implementation of GetTypeDesc.
// Creates a TYPEDESC from a CG node.
//
// Arguments: [ptd] - reference of a pointer to a TYPEDESC
// [pCCB] - CG control block pointer
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
//
// Modifies: ptd points to a new TYPEDESC
//
// History: 6-13-95 stevebl Commented
//
// Notes: Except for the special cases listed below, this method
// calls GenTypeInfo to generate an ICreateTypeInfo for this
// node. Then it creates a TYPEDESC of type VT_USERDEFINED
// which contains an HREFTYPE to the new type info.
//
// The special casses are the ODL base types: CURRENCY, and
// VARIANT, which simply generate the appropriate TYPEDESC and
// do not need to create any additional type infos.
//
//----------------------------------------------------------------------------
CG_STATUS CG_CLASS::GetTypeDesc(TYPEDESC * &ptd, CCB *pCCB)
{
node_skl * pskl = GetType();
char * szName;
int iIntrinsicType;
if (ID_CG_TYPEDEF != GetCGID())
{
while (NODE_DEF == pskl->NodeKind())
{
szName = pskl->GetSymName();
iIntrinsicType = 0;
if ( szName )
{
while (iIntrinsicType < (sizeof(rgIntrinsic) / sizeof(INTRINSIC)))
{
int i = _stricmp(szName, rgIntrinsic[iIntrinsicType].szType);
if (i == 0)
{
ptd = new TYPEDESC;
ptd->lptdesc = NULL;
ptd->vt = rgIntrinsic[iIntrinsicType].vt;
return CG_OK;
}
iIntrinsicType++;
}
}
pskl = pskl->GetChild();
}
}
szName = pskl->GetSymName();
iIntrinsicType = 0;
if ( szName )
while (iIntrinsicType < (sizeof(rgIntrinsic) / sizeof(INTRINSIC)))
{
int i = _stricmp(szName, rgIntrinsic[iIntrinsicType].szType);
if (i == 0)
{
ptd = new TYPEDESC;
ptd->lptdesc = NULL;
ptd->vt = rgIntrinsic[iIntrinsicType].vt;
return CG_OK;
}
iIntrinsicType++;
}
// remember the current ICreateTypeInfo
ICreateTypeInfo * pCTI = pCCB->GetCreateTypeInfo();
MIDL_ASSERT(NULL != pCTI);
ITypeInfo * pTI;
HRESULT hr;
CG_STATUS cgs = CG_OK;
// make sure this typedef has been generated
if (NULL == (pTI = (ITypeInfo *)CheckImportLib()))
{
BOOL fRemember = pCCB->IsInDispinterface();
pCCB->SetInDispinterface(FALSE);
cgs = GenTypeInfo(pCCB);
pCCB->SetInDispinterface(fRemember);
ICreateTypeInfo * pNewCTI = pCCB->GetCreateTypeInfo();
MIDL_ASSERT(NULL != pNewCTI);
// get an ITypeInfo so we can create a reference to it
hr = pNewCTI->QueryInterface(IID_ITypeInfo, (void **)&pTI);
if FAILED(hr)
{
ReportTLGenError( "QueryInterface failed", szName, hr);
}
}
// restore the current ICreateTypeInfo pointer
pCCB->SetCreateTypeInfo(pCTI);
// get an HREFTYPE for it
HREFTYPE hrt = 0;
hr = pCTI->AddRefTypeInfo(pTI, &hrt);
// DO NOT CHECK THIS HRESULT FOR ERRORS
// If we get here after pCTI has been layed out (which is possible on
// structures or unions with circular references) then this will fail.
// TYPE_E_TYPEMISMATCH will be returned if pTI is TKIND_MODULE
// the above comment is in @v1, and I don't want to get rid of it, even
// though oleaut32 is not reporting error in above scenario now.
if ( TYPE_E_TYPEMISMATCH == hr )
{
ReportTLGenError("AddRefTypeInfo failed", szName, hr );
}
// release the ITypeInfo.
pTI->Release();
ptd = new TYPEDESC;
ptd->vt = VT_USERDEFINED;
ptd->hreftype = hrt;
return cgs;
}
//+---------------------------------------------------------------------------
//
// Member: CG_TYPELIBRARY_FILE::GenCode
//
// Synopsis: generates the type library file
//
// Arguments: [pCCB] - CG controller block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_TYPELIBRARY_FILE::GenCode(CCB * pCCB)
{
CG_ITERATOR I;
CG_INTERFACE * pCG;
//
// Create the ICreateTypeLibrary
//
char * szName = GetFileName();
// don't generate tlb if /notlb is specified (don't have a filename)
if (NULL == szName)
return CG_OK;
A2O(wszScratch, szName, MAX_PATH);
//
// initialize the open ICreateTypeInfo list
//
gpobjholder = new CObjHolder;
SYSKIND syskind;
switch(pCommand->GetEnv())
{
case ENV_WIN64:
syskind = ( SYSKIND ) SYS_WIN64;
break;
case ENV_WIN32:
syskind = SYS_WIN32;
break;
default:
syskind = SYS_WIN32;
ReportTLGenError( "invalid syskind", szName, 0);
break;
}
HRESULT hr = LateBound_CreateTypeLib(syskind, wszScratch, &pMainCTL);
if FAILED(hr)
{
ReportTLGenError( "CreateTypeLibFailed", szName, hr);
}
else
{
pCCB->SetCreateTypeLib(pMainCTL);
//
// Find the CG_LIBRARY node and use it to populate the type library
//
GetMembers( I );
I.Init();
while( ITERATOR_GETNEXT( I, pCG ) )
{
switch(pCG->GetCGID())
{
case ID_CG_LIBRARY:
pCG->GenTypeInfo(pCCB);
break;
default:
break;
}
}
hr = pMainCTL->SaveAllChanges();
if FAILED(hr)
{
ReportTLGenError( "SaveAllChanges Failed", szName, hr);
}
//
// free all the object pointers in the object holder
//
delete gpobjholder;
pMainCTL->Release();
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_LIBRARY::GenTypeInfo
//
// Synopsis: sets a type library's attributes and generates its type infos
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_LIBRARY::GenTypeInfo(CCB * pCCB)
{
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
// Set the type library attributes
node_library * pType = (node_library *) GetType();
char * szName = pType->GetSymName();
if (szName)
{
A2O(wszScratch, szName, MAX_PATH);
pCTL->SetName(wszScratch);
}
node_guid * pGuid = (node_guid *) pType->GetAttribute( ATTR_GUID );
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
pCTL->SetGuid(guid);
}
node_text_attr * pTA;
if (pTA = (node_text_attr *) pType->GetAttribute(ATTR_HELPFILE))
{
char * szHelpFile = pTA->GetText();
A2O(wszScratch, szHelpFile, MAX_PATH);
pCTL->SetHelpFileName(wszScratch);
}
if (pTA = (node_text_attr *)pType->GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
pCTL->SetDocString(wszScratch);
}
HRESULT hr = ResultFromScode(S_OK);
if (pTA = (node_text_attr *)pType->GetAttribute(ATTR_HELPSTRINGDLL))
{
char * szHelpStringDll = pTA->GetText();
A2O(wszScratch, szHelpStringDll, MAX_PATH);
hr = ((ICreateTypeLib2*)pCTL)->SetHelpStringDll(wszScratch);
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) pType->GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
pCTL->SetHelpContext(hc);
}
if (pCA = (node_constant_attr *) pType->GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeLib2 *)pCTL)->SetHelpStringContext(hc);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeLib2 *)pCTL)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
// set compiler version and time stamp
if ( !pCommand->IsSwitchDefined( SWITCH_NO_STAMP ) )
{
CHAR szBuffer[MAX_PATH]; // long enough for the readable data
// {DE77BA63-517C-11d1-A2DA-0000F8773CE9}
const GUID TimeStampGuid =
{ 0xde77ba63, 0x517c, 0x11d1, { 0xa2, 0xda, 0x0, 0x0, 0xf8, 0x77, 0x3c, 0xe9 } };
// {DE77BA64-517C-11d1-A2DA-0000F8773CE9}
const GUID CompilerVersionGuid =
{ 0xde77ba64, 0x517c, 0x11d1, { 0xa2, 0xda, 0x0, 0x0, 0xf8, 0x77, 0x3c, 0xe9 } };
// {DE77BA65-517C-11d1-A2DA-0000F8773CE9}
const GUID ReadableMIDLInfoGuid = { 0xde77ba65, 0x517c, 0x11d1, { 0xa2, 0xda, 0x0, 0x0, 0xf8, 0x77, 0x3c, 0xe9 } };
strcpy(szBuffer, "Created by MIDL version ");
strcat(szBuffer,pCommand->GetCompilerVersion());
strcat(szBuffer, " at ");
strcat(szBuffer,pCommand->GetCompileTime() );
A2O(wszScratch, szBuffer, MAX_PATH);
var.vt = VT_BSTR;
var.bstrVal = LateBound_SysAllocString( wszScratch );
( ( ICreateTypeLib2* ) pCTL )->SetCustData( ReadableMIDLInfoGuid, &var );
LateBound_SysFreeString( var.bstrVal );
ZeroMemory( &var, sizeof( VARIANT ) );
time( ( time_t* ) &var.lVal );
var.vt = VT_UI4;
( ( ICreateTypeLib2* ) pCTL )->SetCustData( TimeStampGuid, &var );
var.lVal = ( rmj << 24 ) + ( rmm << 16 ) + rup;
( ( ICreateTypeLib2* ) pCTL )->SetCustData( CompilerVersionGuid, &var );
}
unsigned short Maj;
unsigned short Min;
pType->GetVersionDetails(&Maj, &Min);
pCTL->SetVersion(Maj, Min);
if (pCA = (node_constant_attr *) pType->GetAttribute(ATTR_LCID))
{
DWORD lcid = (DWORD) pCA->GetExpr()->GetValue();
pCTL->SetLcid(pCCB->SetLcid(lcid));
}
else
{
pCTL->SetLcid(pCCB->SetLcid(0));
}
UINT libflags = 0;
if (pType->FMATTRInSummary(MATTR_RESTRICTED))
libflags |= LIBFLAG_FRESTRICTED;
if (pType->FTATTRInSummary(TATTR_CONTROL))
libflags |= LIBFLAG_FCONTROL;
if (pType->FInSummary(ATTR_HIDDEN))
libflags |= LIBFLAG_FHIDDEN;
pCTL->SetLibFlags(libflags);
CG_ITERATOR I;
CG_INTERFACE * pCG;
GetMembers( I );
I.Init();
while( ITERATOR_GETNEXT( I, pCG ) )
{
ITypeInfo * pTI;
char* sz = pCG->GetSymName();
if (0 != _stricmp(sz, "IDispatch") &&
0 != _stricmp(sz, "IUnknown"))
{
if (!(pTI = (ITypeInfo *)pCG->CheckImportLib()))
{
// we postpone the creation of typeinfo for interface reference
// (which actually results in the creation of typeinfo for an
// interface) to maintain the equivalence in the order of
// definition in the source file and the resulting type library.
ID_CG cgId = pCG->GetCGID();
if ( cgId != ID_CG_INTERFACE_REFERENCE )
{
pCG->GenTypeInfo(pCCB);
}
}
else
{
pTI->Release();
}
}
}
I.Init();
while( ITERATOR_GETNEXT( I, pCG ) )
{
ITypeInfo * pTI;
char* sz = pCG->GetSymName();
if (0 != _stricmp(sz, "IDispatch") &&
0 != _stricmp(sz, "IUnknown"))
{
if (!(pTI = (ITypeInfo *)pCG->CheckImportLib()))
{
// this trict ensures that type info for the base interface is created
// before the typeinfo for the derived interface. This is important for
// utilities that generate .H .TLH and .TLI from the .TLB
ID_CG cgId = pCG->GetCGID();
if ( cgId == ID_CG_INTERFACE_REFERENCE )
{
pCG->GenTypeInfo(pCCB);
}
}
else
{
pTI->Release();
}
}
}
CG_CLASS* pCGI = 0;
ICreateTypeInfo* pCTI = 0;
pCCB->InitVTableLayOutList();
while (pCCB->GetNextVTableLayOutInfo(&pCGI, &pCTI))
{
szName = pCGI->GetType()->GetSymName();
if (pCGI && pCTI)
{
HRESULT hr = (HRESULT)pCGI->LayOut();
if FAILED(hr)
{
ReportTLGenError( "LayOut failed", szName, hr);
}
pCTI->Release();
}
else
{
ReportTLGenError( "LayOut failed", szName, hr);
}
}
pCCB->DiscardVTableLayOutList();
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_LIBRARY::GenHeader
//
// Synopsis: generates header file information for a type library
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_LIBRARY::GenHeader(CCB * pCCB)
{
CG_ITERATOR I;
CG_NDR * pCG;
node_library * pLibrary = (node_library *) GetType();
char * szName = pLibrary->GetSymName();
ISTREAM * pStream = pCCB->GetStream();
pStream->Write("\n\n#ifndef __");
pStream->Write(szName);
pStream->Write("_LIBRARY_DEFINED__\n");
pStream->Write("#define __");
pStream->Write(szName);
pStream->Write("_LIBRARY_DEFINED__\n");
GetMembers( I );
// dump all of the types
pStream->NewLine();
pLibrary->PrintType((PRT_INTERFACE | PRT_BOTH_PREFIX), pStream, 0);
pStream->NewLine();
if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
{
node_guid * pGuid = (node_guid *) pLibrary->GetAttribute( ATTR_GUID );
if (pGuid)
Out_MKTYPLIB_Guid(pCCB, pGuid->GetStrs(), "LIBID_", szName);
}
else
{
pStream->Write("EXTERN_C const IID LIBID_");
pStream->Write(szName);
pStream->Write(';');
pStream->NewLine();
}
// now dump all of the interfaces, dispinterfaces, etc.
I.Init();
while( ITERATOR_GETNEXT( I, pCG ) )
{
pCG->GenHeader(pCCB);
}
pStream->Write("#endif /* __");
pStream->Write(szName);
pStream->Write("_LIBRARY_DEFINED__ */\n");
return CG_OK;
}
// create the typeinfo but do not populate it.
// helps preserve the order or interface declaration.
CG_STATUS CG_INTERFACE::CreateTypeInfo( CCB * pCCB )
{
ICreateTypeLib* pCTL = pCCB->GetCreateTypeLib();
char* szName = GetType()->GetSymName();
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_INTERFACE, ( ICreateTypeInfo ** )&_pCTI);
if (SUCCEEDED(hr))
{
gpobjholder->Add( ( IUnknown* ) _pCTI);
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE::GenTypeInfo
//
// Synopsis: generates a type info for an interface
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_INTERFACE::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been initialized.
if ( fTypeInfoInitialized )
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
return CG_OK;
}
// if typeinfo was not created, create it.
if ( _pCTI == 0 )
{
CreateTypeInfo( pCCB );
if ( _pCTI == 0 )
{
return CG_OK;
}
}
fTypeInfoInitialized = TRUE;
HRESULT hr = S_OK;
node_interface* pItf = (node_interface *) GetType();
char* szName = pItf->GetSymName();
ICreateTypeInfo* pCTI = ( ICreateTypeInfo * ) _pCTI;
pCCB->SetCreateTypeInfo(pCTI);
BOOL fRemember = pCCB->IsInDispinterface();
pCCB->SetInDispinterface(FALSE);
WALK_CTXT ctxt(GetType());
UINT uTypeFlags = GetTypeFlags(&ctxt);
if (FNewTypeLib())
{
if ( IsDispatchable(TRUE) )
{
uTypeFlags |= TYPEFLAG_FDISPATCHABLE;
}
}
hr = pCTI->SetTypeFlags(uTypeFlags);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
node_guid * pGuid = (node_guid *) ctxt.GetAttribute( ATTR_GUID );
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenError( "Could not add UUID, STDOLE2.TLB probably needs to be imported", szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
unsigned short Maj;
unsigned short Min;
pItf->GetVersionDetails(&Maj, &Min);
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
// CONSIDER - may still need to check for MATTR_RESTRICTED
CG_CLASS * pCG;
named_node * pBaseIntf;
node_skl * pType = GetType();
if (pBaseIntf = ((node_interface *)(pType))->GetMyBaseInterfaceReference())
{
node_interface_reference * pRef = (node_interface_reference *)pBaseIntf;
// skip forward reference if necessary
if (pRef->NodeKind() == NODE_FORWARD)
{
pRef = (node_interface_reference *)pRef->GetChild();
}
pCG = ((node_interface *)(pRef->GetChild()))->GetCG( TRUE);
ITypeInfo * pTI;
if (NULL == (pTI = (ITypeInfo *)pCG->CheckImportLib()))
{
pCG->GenTypeInfo(pCCB);
ICreateTypeInfo * pNewCTI = pCCB->GetCreateTypeInfo();
hr = pNewCTI->QueryInterface(IID_ITypeInfo, (void **)&pTI);
if FAILED(hr)
{
ReportTLGenError( "QueryInterface failed", szName, hr);
}
}
// get an HREFTYPE for it
HREFTYPE hrt;
hr = pCTI->AddRefTypeInfo(pTI, &hrt);
if FAILED(hr)
{
ReportTLGenError( "AddRefTypeInfo failed", szName, hr);
}
// release the ITypeInfo.
pTI->Release();
// add the impltype
hr = pCTI->AddImplType(0, hrt);
if FAILED(hr)
{
ReportTLGenError( "AddImplType failed", szName, hr);
}
/*
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
*/
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
}
// restore current type info pointer
pCCB->SetCreateTypeInfo(pCTI);
CG_ITERATOR I;
GetMembers( I );
I.Init();
unsigned uRememberPreviousFuncNum = pCCB->GetProcNum();
unsigned uRememberPreviousVarNum = pCCB->GetVarNum();
pCCB->SetProcNum(0);
pCCB->SetVarNum(0);
// walk members, adding them to the type info
while (ITERATOR_GETNEXT(I, pCG))
{
pCG->GenTypeInfo(pCCB);
}
pCCB->SetInDispinterface(fRemember);
pCCB->SetProcNum((unsigned short)uRememberPreviousFuncNum);
pCCB->SetVarNum((unsigned short)uRememberPreviousVarNum);
// the complementary Release() is called in CG_LIBRARY::GenTypeInfo()
pCTI->AddRef();
// add this node to the list of nodes to be laid out.
pCCB->SaveVTableLayOutInfo(this, pCTI);
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE_REFERENCE::GenTypeInfo
//
// Synopsis: generates type info for an interface reference
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_INTERFACE_REFERENCE::GenTypeInfo(CCB *pCCB)
{
CG_INTERFACE * pCG = (CG_INTERFACE *)((node_interface_reference *)GetType())->GetRealInterface()->GetCG(TRUE);
return pCG->GenTypeInfo(pCCB);
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE_REFERENCE::GenHeader
//
// Synopsis: generates header information for an interface reference
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_INTERFACE_REFERENCE::GenHeader(CCB * pCCB)
{
CG_INTERFACE * pCG = (CG_INTERFACE *)((node_interface_reference *)GetType())->GetRealInterface()->GetCG(TRUE);
return pCG->GenHeader(pCCB);
}
#if 0 // code disabled but retained in case it's ever needed again
//+---------------------------------------------------------------------------
//
// Function: AddInheritedMembers
//
// Synopsis: helper function used by a dispinterface to add entries for all
// of the members in all of the interfaces from which it inherits
//
// Arguments: [pcgInterface] - pointer to an inherited interface
// [pCCB] - CG control block
//
// History: 6-13-95 stevebl Commented
//
// Notes: Members are added to the current ICreateTypeInfo which is
// found in the CG control block.
//
//----------------------------------------------------------------------------
void AddInheritedMembers(CG_INTERFACE * pcgInterface, CCB * pCCB)
{
// do any base interfaces first
named_node * pBase = ((node_interface *)(pcgInterface->GetType()))->GetMyBaseInterfaceReference();
if (pBase)
{
node_interface_reference * pRef = (node_interface_reference *) pBase;
if (pRef->NodeKind() == NODE_FORWARD)
{
pRef = (node_interface_reference *)pRef->GetChild();
}
AddInheritedMembers((CG_INTERFACE *)((node_interface *)(pRef->GetChild()))->GetCG(TRUE), pCCB);
}
CG_CLASS * pCG;
CG_ITERATOR I;
pcgInterface->GetMembers(I);
I.Init();
while (ITERATOR_GETNEXT(I,pCG))
{
// add this interface's members to the type info
pCG->GenTypeInfo(pCCB);
}
}
#endif // end of disabled code
//+---------------------------------------------------------------------------
//
// Member: CG_DISPINTERFACE::GenTypeInfo
//
// Synopsis: generates a type info for a dispinterface
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_DISPINTERFACE::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been created
if (NULL != _pCTI)
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
return CG_OK;
}
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
node_dispinterface * pDispItf = (node_dispinterface *) GetType();
char * szName = pDispItf->GetSymName();
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_DISPATCH, &pCTI);
if (SUCCEEDED(hr))
{
_pCTI = pCTI;
pCCB->SetCreateTypeInfo(pCTI);
gpobjholder->Add(pCTI);
WALK_CTXT ctxt(GetType());
UINT uTypeFlags = GetTypeFlags(&ctxt);
if (FNewTypeLib())
{
uTypeFlags |= TYPEFLAG_FDISPATCHABLE;
}
hr = pCTI->SetTypeFlags(uTypeFlags);
if ( FAILED( hr ) )
{
ReportTLGenError( "SetTypeFlags() failed", szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *) ctxt.GetAttribute( ATTR_GUID );
if (pGuid)
{
GUID guid1;
pGuid->GetGuid(guid1);
hr = pCTI->SetGuid(guid1);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
pDispItf->GetVersionDetails(&Maj, &Min);
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
// CONSIDER - may still need to check for MATTR_RESTRICTED
CG_CLASS * pCG;
// Put in the impltype to IDispatch
pCG = GetCGDispatch();
ITypeInfo * pTI;
if (NULL == (pTI = (ITypeInfo *)pCG->CheckImportLib()))
{
pCG->GenTypeInfo(pCCB);
ICreateTypeInfo * pNewCTI = pCCB->GetCreateTypeInfo();
hr = pNewCTI->QueryInterface(IID_ITypeInfo, (void **)&pTI);
if FAILED(hr)
{
ReportTLGenError( "QueryInterface failed", szName, hr);
}
}
// get an HREFTYPE for it
HREFTYPE hrt;
hr = pCTI->AddRefTypeInfo(pTI, &hrt);
if FAILED(hr)
{
ReportTLGenError( "AddRefTypeInfo failed", szName, hr);
}
// release the ITypeInfo.
pTI->Release();
// add the impltype
hr = pCTI->AddImplType(0, hrt);
if FAILED(hr)
{
ReportTLGenError( "AddImplType failed", szName, hr);
}
// restore current type info pointer
pCCB->SetCreateTypeInfo(pCTI);
CG_ITERATOR I;
GetMembers( I );
I.Init();
unsigned uRememberPreviousFuncNum = pCCB->GetProcNum();
unsigned uRememberPreviousVarNum = pCCB->GetVarNum();
pCCB->SetProcNum(0);
pCCB->SetVarNum(0);
BOOL fRemember = pCCB->IsInDispinterface();
pCCB->SetInDispinterface(TRUE);
BOOL fContinue = ITERATOR_GETNEXT(I,pCG);
if (fContinue)
{
if (ID_CG_INTERFACE_PTR == pCG->GetCGID())
{
// syntax 1
// get the first base interface
node_interface * pI = (node_interface *)((CG_INTERFACE_POINTER *)pCG)->GetTheInterface();
CG_INTERFACE * pcgInterface = (CG_INTERFACE *)(pI->GetCG(TRUE));
// Put in the impltype to inherited interface
ITypeInfo * pTI1;
if (NULL == pcgInterface)
{
// This must be an imported definition.
// Call ILxlate to manufacture a CG node for it
XLAT_CTXT ctxt1(GetType());
ctxt1.SetAncestorBits(IL_IN_LIBRARY);
pcgInterface = (CG_INTERFACE *)(pI->ILxlate(&ctxt1));
// make sure we get the right CG node
if (pI->GetCG(TRUE))
pcgInterface = (CG_INTERFACE *)(pI->GetCG(TRUE));
}
if (NULL == (pTI1 = (ITypeInfo *)pcgInterface->CheckImportLib()))
{
pcgInterface->GenTypeInfo(pCCB);
ICreateTypeInfo * pNewCTI = pCCB->GetCreateTypeInfo();
hr = pNewCTI->QueryInterface(IID_ITypeInfo, (void **)&pTI1);
if FAILED(hr)
{
ReportTLGenError( "QueryInterface failed", szName, hr);
}
}
// get an HREFTYPE for it
HREFTYPE hrt1;
hr = pCTI->AddRefTypeInfo(pTI1, &hrt1);
if FAILED(hr)
{
ReportTLGenError( "AddRefTypeInfo failed", szName, hr);
}
// release the ITypeInfo.
pTI1->Release();
// add the impltype
hr = pCTI->AddImplType(1, hrt1);
if FAILED(hr)
{
ReportTLGenError( "AddImplType failed", szName, hr);
}
// restore current type info pointer
pCCB->SetCreateTypeInfo(pCTI);
}
else
{
// syntax 2
// walk members, adding them to the type info
while (fContinue)
{
pCG->GenTypeInfo(pCCB);
fContinue = ITERATOR_GETNEXT(I,pCG);
}
}
}
pCCB->SetProcNum((unsigned short)uRememberPreviousFuncNum);
pCCB->SetVarNum((unsigned short)uRememberPreviousVarNum);
pCCB->SetInDispinterface(fRemember);
// the complementary Release() is called in CG_LIBRARY::GenTypeInfo()
pCTI->AddRef();
// add this node to the list of nodes to be laid out.
pCCB->SaveVTableLayOutInfo(this, pCTI);
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_DISPINTERFACE::GenHeader
//
// Synopsis: generates header file information for a dispinterface
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_DISPINTERFACE::GenHeader(CCB * pCCB)
{
node_interface * pInterface = (node_interface *) GetType();
ISTREAM * pStream = pCCB->GetStream();
char * pName = pInterface->GetSymName();
CG_OBJECT_INTERFACE * pCGDispatch = (CG_OBJECT_INTERFACE *)GetCGDispatch();
//Initialize the CCB for this interface.
InitializeCCB(pCCB);
// put out the interface guards
pStream->Write("\n#ifndef __");
pStream->Write( pName );
pStream->Write( "_DISPINTERFACE_DEFINED__\n" );
pStream->Write( "#define __");
pStream->Write( pName );
pStream->Write( "_DISPINTERFACE_DEFINED__\n" );
// Print out the declarations of the types
pStream->NewLine();
pInterface->PrintType( PRT_INTERFACE | PRT_OMIT_PROTOTYPE, pStream, 0);
pStream->NewLine();
if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
{
node_guid * pGuid = (node_guid *) pInterface->GetAttribute( ATTR_GUID );
if (pGuid)
Out_MKTYPLIB_Guid(pCCB, pGuid->GetStrs(), "DIID_", pName);
}
else
{
pStream->Write("EXTERN_C const IID DIID_");
pStream->Write(pName);
pStream->Write(';');
pStream->NewLine();
}
// print out the vtable/class definitions
pStream->NewLine();
pStream->Write("#if defined(__cplusplus) && !defined(CINTERFACE)");
pStream->IndentInc();
pStream->NewLine(2);
// put out the declspec for the uuid
if ( pCommand->GetMSCVer() >= 1100 )
{
pStream->Write("MIDL_INTERFACE(\"");
pStream->Write(GuidStrs.str1);
pStream->Write('-');
pStream->Write(GuidStrs.str2);
pStream->Write('-');
pStream->Write(GuidStrs.str3);
pStream->Write('-');
pStream->Write(GuidStrs.str4);
pStream->Write('-');
pStream->Write(GuidStrs.str5);
pStream->Write("\")");
}
else
{
pStream->Write(" struct ");
}
pStream->NewLine();
pStream->Write(pName);
pStream->Write(" : public IDispatch");
pStream->NewLine();
pStream->Write('{');
pStream->NewLine();
pStream->Write("};");
pStream->NewLine();
pStream->IndentDec();
pStream->NewLine();
pStream->Write("#else \t/* C style interface */");
pStream->IndentInc();
pCGDispatch->CLanguageBinding(pCCB);
pStream->IndentDec();
// print out the C Macros
pCGDispatch->CLanguageMacros( pCCB );
pStream->NewLine( 2 );
pStream->Write("#endif \t/* C style interface */");
pStream->NewLine( 2 );
// print out the commented prototypes for the dispatch methods and procedures
// put out the trailing interface guard
pStream->Write( "\n#endif \t/* __");
pStream->Write( pName );
pStream->Write( "_DISPINTERFACE_DEFINED__ */\n" );
pStream->NewLine();
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_MODULE::GenTypeInfo
//
// Synopsis: generates a type info for a module
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_MODULE::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been created
if (NULL != _pCTI)
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
return CG_OK;
}
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
node_coclass * pCC = (node_coclass *) GetType();
char * szName = pCC->GetSymName();
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_MODULE, &pCTI);
if (SUCCEEDED(hr))
{
_pCTI = pCTI;
pCCB->SetCreateTypeInfo(pCTI);
gpobjholder->Add(pCTI);
WALK_CTXT ctxt(GetType());
hr = pCTI->SetTypeFlags(GetTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *) ctxt.GetAttribute( ATTR_GUID );
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_DLLNAME))
{
pCCB->SetDllName(pTA->GetText());
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
pCC->GetVersionDetails(&Maj, &Min);
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
// CONSIDER - may still need to check for MATTR_RESTRICTED
CG_CLASS * pCG;
CG_ITERATOR I;
GetMembers( I );
I.Init();
unsigned uRememberPreviousFuncNum = pCCB->GetProcNum();
unsigned uRememberPreviousVarNum = pCCB->GetVarNum();
pCCB->SetProcNum(0);
pCCB->SetVarNum(0);
// walk members, adding them to the type info
while (ITERATOR_GETNEXT(I, pCG))
{
pCG->GenTypeInfo(pCCB);
}
pCCB->SetProcNum((unsigned short)uRememberPreviousFuncNum);
pCCB->SetVarNum((unsigned short)uRememberPreviousVarNum);
// the complementary Release() is called in CG_LIBRARY::GenTypeInfo()
pCTI->AddRef();
// add this node to the list of nodes to be laid out.
pCCB->SaveVTableLayOutInfo(this, pCTI);
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_MODULE::GenHeader
//
// Synopsis: generates header information for a module
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_MODULE::GenHeader(CCB * pCCB)
{
CG_ITERATOR I;
node_module * pModule = (node_module *) GetType();
char * szName = pModule->GetSymName();
ISTREAM * pStream = pCCB->GetStream();
pStream->Write("\n\n#ifndef __");
pStream->Write(szName);
pStream->Write("_MODULE_DEFINED__\n");
pStream->Write("#define __");
pStream->Write(szName);
pStream->Write("_MODULE_DEFINED__\n");
pStream->NewLine();
// Print out the declarations of the types
pStream->NewLine();
pModule->PrintType( PRT_DECLARATION , pStream, 0);
pStream->Write("#endif /* __");
pStream->Write(szName);
pStream->Write("_MODULE_DEFINED__ */\n");
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_COCLASS::GenTypeInfo
//
// Synopsis: generates a type info for a coclass
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_COCLASS::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been created
if (NULL != _pCTI)
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
return CG_OK;
}
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
node_coclass * pCC = (node_coclass *) GetType();
char * szName = pCC->GetSymName();
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_COCLASS, &pCTI);
if (SUCCEEDED(hr))
{
_pCTI = pCTI;
pCCB->SetCreateTypeInfo(pCTI);
gpobjholder->Add(pCTI);
WALK_CTXT ctxt(GetType());
UINT uTypeFlags = GetTypeFlags(&ctxt);
if (!pCC->IsNotCreatable())
{
uTypeFlags |= TYPEFLAG_FCANCREATE;
}
hr = pCTI->SetTypeFlags(uTypeFlags);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *) ctxt.GetAttribute( ATTR_GUID );
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
pCC->GetVersionDetails(&Maj, &Min);
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( "SetTypeFlags() failed", szName, hr);
}
// CONSIDER - may still need to check for MATTR_RESTRICTED
CG_CLASS * pCG;
CG_ITERATOR I;
GetMembers( I );
I.Init();
MEM_ITER MemIter(pCC);
unsigned nImpltype = 0;
// walk members, adding them to the type info
while (ITERATOR_GETNEXT(I, pCG))
{
ITypeInfo * pTI;
// if (ID_CG_INTERFACE_POINTER == pCG->GetCGID())
// pCG= pCG->GetChild();
if (NULL == (pTI = (ITypeInfo *)pCG->CheckImportLib()))
{
pCG->GenTypeInfo(pCCB);
ICreateTypeInfo * pNewCTI = pCCB->GetCreateTypeInfo();
hr = pNewCTI->QueryInterface(IID_ITypeInfo, (void **)&pTI);
if FAILED(hr)
{
ReportTLGenError( "QueryInterface failed", szName, hr);
}
}
// get an HREFTYPE for it
HREFTYPE hrt;
hr = pCTI->AddRefTypeInfo(pTI, &hrt);
if FAILED(hr)
{
ReportTLGenError( "AddRefTypeInfo failed", szName, hr);
}
// release the ITypeInfo.
pTI->Release();
// add the impltype
hr = pCTI->AddImplType(nImpltype, hrt);
if FAILED(hr)
{
ReportTLGenError( "AddImplType failed", szName, hr);
}
// Get the ipltype attributes from the node_forward
WALK_CTXT ctxt(MemIter.GetNext());
hr = pCTI->SetImplTypeFlags(nImpltype, GetImplTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
node_custom_attr * pC;
if (pC = (node_custom_attr *) ctxt.GetAttribute(ATTR_CUSTOM))
{
VARIANT var;
memset(&var, 0, sizeof(VARIANT));
ConvertToVariant(var, pC->GetVal(), pCCB->GetLcid());
GUID guid;
pC->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetImplTypeCustData(nImpltype, guid, &var);
}
pCCB->SetCreateTypeInfo(pCTI);
nImpltype++;
}
// the complementary Release() is called in CG_LIBRARY::GenTypeInfo()
pCTI->AddRef();
// add this node to the list of nodes to be laid out.
pCCB->SaveVTableLayOutInfo(this, pCTI);
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_COCLASS::GenHeader
//
// Synopsis: generates header information for a coclass
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_COCLASS::GenHeader(CCB * pCCB)
{
node_coclass * pCoclass = (node_coclass *) GetType();
ISTREAM * pStream = pCCB->GetStream();
char * pName = pCoclass->GetSymName();
node_guid * pGuid = (node_guid *) pCoclass->GetAttribute(ATTR_GUID);
pStream->NewLine();
if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
{
if (pGuid)
Out_MKTYPLIB_Guid(pCCB, pGuid->GetStrs(), "CLSID_", pName);
}
else
{
pStream->Write("EXTERN_C const CLSID CLSID_");
pStream->Write(pName);
pStream->Write(';');
pStream->NewLine();
}
pStream->Write("\n#ifdef __cplusplus");
pStream->NewLine();
pStream->Write("\nclass ");
if (pGuid)
{
GUID_STRS GuidStrs = pGuid->GetStrs();
// put out the declspec for the uuid
pStream->Write("DECLSPEC_UUID(\"");
pStream->Write(GuidStrs.str1);
pStream->Write('-');
pStream->Write(GuidStrs.str2);
pStream->Write('-');
pStream->Write(GuidStrs.str3);
pStream->Write('-');
pStream->Write(GuidStrs.str4);
pStream->Write('-');
pStream->Write(GuidStrs.str5);
pStream->Write("\")");
}
pStream->NewLine();
pStream->Write(pName);
pStream->Write(";\n#endif");
pStream->NewLine();
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_ID::GenTypeInfo
//
// Synopsis: adds a constant variable to a type info
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Created
//
// Notes: Because of the way the CG tree is constructed, this method
// can only be called from within a module.
//
// CONSIDER - might want to add an assert to check this
//
//----------------------------------------------------------------------------
CG_STATUS CG_ID::GenTypeInfo(CCB *pCCB)
{
VARDESC vdesc;
memset(&vdesc, 0, sizeof(VARDESC));
vdesc.memid = DISPID_UNKNOWN;
TYPEDESC * ptdesc;
GetChild()->GetTypeDesc(ptdesc, pCCB);
memcpy(&vdesc.elemdescVar.tdesc, ptdesc, sizeof(TYPEDESC));
vdesc.varkind = VAR_CONST;
WALK_CTXT ctxt(GetType());
vdesc.elemdescVar.idldesc.wIDLFlags = GetIDLFlags(&ctxt);
vdesc.wVarFlags = (unsigned short)GetVarFlags(&ctxt);
VARIANT var;
memset(&var, 0, sizeof(VARIANT));
vdesc.lpvarValue = &var;
node_id * pId = (node_id *) GetType();
GetValueFromExpression(var, vdesc.elemdescVar.tdesc, pId->GetExpr(), pCCB->GetLcid(), GetSymName());
ICreateTypeInfo * pCTI = pCCB->GetCreateTypeInfo();
char * szName = GetSymName();
unsigned uVar = pCCB->GetVarNum();
HRESULT hr = pCTI->AddVarDesc(uVar, &vdesc);
if (FAILED(hr))
{
ReportTLGenError( "AddVarDesc failed", szName, hr);
}
DeleteTypedescChildren(ptdesc);
delete ptdesc;
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetVarCustData( uVar,
guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
if (szName)
{
A2O(wszScratch, szName, MAX_PATH);
hr = pCTI->SetVarName(uVar, wszScratch);
if (FAILED(hr))
{
ReportTLGenError( "SetVarName failed", szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetVarDocString(uVar,wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetVarHelpContext(uVar, hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetVarHelpStringContext( uVar, hc );
}
// bump the variable number
pCCB->SetVarNum(unsigned short(uVar + 1));
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_ENUM::GenTypeInfo
//
// Synopsis: generates a type info for an ENUM
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_ENUM::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been created
if (NULL != _pCTI)
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
return CG_OK;
}
char * szName = ((node_su_base *)GetBasicType())->GetTypeInfoName();
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_ENUM, &pCTI);
if SUCCEEDED(hr)
{
_pCTI = pCTI;
gpobjholder->Add(pCTI, szName);
pCCB->SetCreateTypeInfo(pCTI);
node_enum * pEnum = (node_enum *) GetType()->GetBasicType();
// walk members, adding them to the type info
MEM_ITER MemIter( pEnum );
node_label * pLabel;
unsigned uIndex = 0;
VARDESC vdElem;
memset(&vdElem, 0, sizeof(VARDESC));
vdElem.memid = DISPID_UNKNOWN;
vdElem.varkind = VAR_CONST;
VARIANT var;
memset(&var, 0, sizeof(VARIANT));
/*
* It appears that MKTYPLIB always uses the VT_INT/VT_I4 combination
* regardless of the target platform. For now I'll duplicate this
* behavior but the commented out code below is what I
* would have expected to be correct.
unsigned uSize = pEnum->GetSize(0, 0);
switch (uSize)
{
case 2:
vdElem.elemdescVar.tdesc.vt = VT_I2;
var.vt = VT_I2;
break;
case 4:
vdElem.elemdescVar.tdesc.vt = VT_I4;
var.vt = VT_I4;
break;
default:
vdElem.elemdescVar.tdesc.vt = VT_I2;
var.vt = VT_I2;
break;
}
*/
vdElem.elemdescVar.tdesc.vt = VT_INT;
var.vt = VT_I4;
vdElem.lpvarValue = &var;
while ( pLabel = (node_label *) MemIter.GetNext() )
{
WALK_CTXT ctxt(pLabel);
vdElem.wVarFlags = (unsigned short)GetVarFlags(&ctxt);
vdElem.elemdescVar.idldesc.wIDLFlags = GetIDLFlags(&ctxt);
/* see previous comment
switch (uSize)
{
case 2:
vdElem.lpvarValue->iVal = (short) pLabel->GetValue();
break;
case 4:
*/
vdElem.lpvarValue->lVal = (long) pLabel->GetValue();
/*
break;
default:
vdElem.lpvarValue->iVal = (short) pLabel->GetValue();
break;
}
*/
hr = pCTI->AddVarDesc(uIndex, &vdElem);
if (FAILED(hr))
{
ReportTLGenError( "AddVarDesc failed", szName, hr);
}
szName = pLabel->GetSymName();
A2O(wszScratch, szName, MAX_PATH);
hr = pCTI->SetVarName(uIndex, wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( "Could not set name", szName, hr);
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetVarDocString(uIndex, wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetVarHelpContext(uIndex, hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetVarHelpStringContext( uIndex, hc );
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
VARIANT variant;
ATTR_T curAttrID;
GUID guid;
((named_node*)pLabel)->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &variant,
sizeof(variant));
ConvertToVariant( variant,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetVarCustData( uIndex,
guid,
&variant);
}
pCurAttr = pCurAttr->GetNext();
}
uIndex++;
};
// Set all common type attributes
WALK_CTXT ctxt(GetType());
hr = pCTI->SetTypeFlags(GetTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
VARIANT variant;
ATTR_T curAttrID;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &variant,
sizeof(variant));
ConvertToVariant( variant,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&variant);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *)ctxt.ExtractAttribute(ATTR_GUID);
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) && hr != 0x800288C6L )
{
// do not report duplicate UUID errors. Duplicate UUIDs
// are caught by the front end. They only way they can
// occur here is because tries to set the UUID on both
// the typedef and the enum. This is benign.
ReportTLGenWarning( szErrUUID, pEnum->GetSymName(), hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
node_version * pVer = (node_version *) ctxt.GetAttribute(ATTR_VERSION);
if (pVer)
pVer->GetVersion(&Maj, &Min);
else
{
Maj = Min = 0;
}
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
hr = pCTI->SetAlignment( GetMemoryAlignment() );
hr = pCTI->LayOut();
if FAILED(hr)
{
ReportTLGenError( "LayOut failed on enum", szName, hr);
}
LayedOut();
}
else
{
// It's possible that this type has already been created.
if (NULL == (pCTI = (ICreateTypeInfo *)gpobjholder->Find(szName)))
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
pCCB->SetCreateTypeInfo(pCTI);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_STRUCT::GenTypeInfo
//
// Synopsis: generates a type info for a struct
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
// Notes: see note at beginning of this file about CG_STATUS return
// codes and cyclic dependencies
//
//----------------------------------------------------------------------------
CG_STATUS CG_STRUCT::GenTypeInfo(CCB *pCCB)
{
HRESULT hr;
// check to see if we've already been created
if (NULL != _pCTI)
{
// we have
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
if (!IsReadyForLayOut())
{
return CG_NOT_LAYED_OUT;
}
if (!AreDepsLayedOut())
{
// avoid infinite loops
DepsLayedOut();
// give dependents a chance to be layed out
CG_ITERATOR I;
CG_CLASS *pCG;
GetMembers(I);
I.Init();
CG_STATUS cgs = CG_OK;
while(ITERATOR_GETNEXT(I, pCG))
{
switch(pCG->GenTypeInfo(pCCB))
{
case CG_NOT_LAYED_OUT:
cgs = CG_NOT_LAYED_OUT;
break;
case CG_REF_NOT_LAYED_OUT:
if (CG_OK == cgs)
cgs = CG_REF_NOT_LAYED_OUT;
break;
default:
break;
}
}
if (cgs != CG_OK)
{
ClearDepsLayedOut();
return cgs;
}
}
// SetAlignment()
hr = ((ICreateTypeInfo *)_pCTI)->SetAlignment( GetMemoryAlignment() );
hr = ((ICreateTypeInfo *)_pCTI)->LayOut();
LayedOut();
return CG_OK;
}
BOOL fDependentsLayedOut = TRUE;
BOOL fICanLayOut = TRUE;
char * szName = ((node_su_base *)GetBasicType())->GetTypeInfoName();
// HACK HACK HACK: special case to keep the base types
// CY and DECIMAL from getting entered into the library
if (0 == _stricmp(szName, "CY") || 0 == _stricmp(szName, "DECIMAL"))
return CG_OK;
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
A2O(wszScratch, szName, MAX_PATH);
hr = pCTL->CreateTypeInfo(wszScratch, TKIND_RECORD, &pCTI);
if SUCCEEDED(hr)
{
// remember the ICreateTypeInfo pointer
_pCTI = pCTI;
gpobjholder->Add(pCTI);
pCCB->SetCreateTypeInfo(pCTI);
CG_ITERATOR I;
CG_CLASS * pCG;
GetMembers(I);
I.Init();
unsigned uRememberPreviousVarNum = pCCB->GetVarNum();
pCCB->SetVarNum(0);
// walk members, adding them to the type info
while (ITERATOR_GETNEXT(I, pCG))
{
CG_STATUS cgs = pCG->GenTypeInfo(pCCB);
switch (cgs)
{
case CG_NOT_LAYED_OUT:
fICanLayOut = FALSE;
// fall through
case CG_REF_NOT_LAYED_OUT:
fDependentsLayedOut = FALSE;
// fall through
default:
break;
}
}
pCCB->SetVarNum((unsigned short)uRememberPreviousVarNum);
// Set all common type attributes
WALK_CTXT ctxt(GetType());
hr = pCTI->SetTypeFlags(GetTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *)ctxt.ExtractAttribute(ATTR_GUID);
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
node_version * pVer = (node_version *) ctxt.GetAttribute(ATTR_VERSION);
if (pVer)
pVer->GetVersion(&Maj, &Min);
else
{
Maj = Min = 0;
}
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
ReadyForLayOut();
if (fICanLayOut)
{
// SetAlignment()
hr = pCTI->SetAlignment( GetMemoryAlignment() );
hr = pCTI->LayOut();
if FAILED(hr)
{
ReportTLGenError( "LayOut failed on struct",szName, hr);
}
LayedOut();
if (!fDependentsLayedOut)
{
// The only way I can get here is if my dependents were either blocked by me
// or blocked by one of my ancestors.
// Now that I've been layed out, they may no longer be blocked.
BOOL fSucceeded = TRUE;
I.Init();
while (ITERATOR_GETNEXT(I, pCG))
{
CG_STATUS cgs = pCG->GenTypeInfo(pCCB);
if (CG_OK != cgs)
fSucceeded = FALSE;
}
if (fSucceeded)
{
DepsLayedOut();
return CG_OK;
}
return CG_REF_NOT_LAYED_OUT;
}
DepsLayedOut();
return CG_OK;
}
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_NOT_LAYED_OUT;
}
//+---------------------------------------------------------------------------
//
// Member: CG_UNION::GenTypeInfo
//
// Synopsis: generates a type info for a union
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
// Notes: see note at beginning of this file about CG_STATUS return
// codes and cyclic dependencies
//
//----------------------------------------------------------------------------
CG_STATUS CG_UNION::GenTypeInfo(CCB *pCCB)
{
HRESULT hr;
// check to see if we've already been created
if (NULL != _pCTI)
{
// we have
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
if (!IsReadyForLayOut())
{
return CG_NOT_LAYED_OUT;
}
if (!AreDepsLayedOut())
{
// avoid infinite loops
DepsLayedOut();
// give dependents a chance to be layed out
CG_ITERATOR I;
CG_CLASS *pCG;
GetMembers(I);
I.Init();
CG_STATUS cgs = CG_OK;
while(ITERATOR_GETNEXT(I, pCG))
{
switch(pCG->GenTypeInfo(pCCB))
{
case CG_NOT_LAYED_OUT:
cgs = CG_NOT_LAYED_OUT;
break;
case CG_REF_NOT_LAYED_OUT:
if (CG_OK == cgs)
cgs = CG_REF_NOT_LAYED_OUT;
break;
default:
break;
}
}
if (cgs != CG_OK)
{
ClearDepsLayedOut();
return cgs;
}
}
hr = ((ICreateTypeInfo *)_pCTI)->SetAlignment( GetMemoryAlignment() );
hr = ((ICreateTypeInfo *)_pCTI)->LayOut();
if FAILED(hr)
{
char * szName = ((node_su_base *)GetBasicType())->GetTypeInfoName();
if ( !szName )
szName = GetSymName();
ReportTLGenError( "LayOut failed on union", szName, hr);
}
LayedOut();
return CG_OK;
}
BOOL fDependentsLayedOut = TRUE;
BOOL fICanLayOut = TRUE;
char * szName = ((node_su_base *)GetBasicType())->GetTypeInfoName();
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
A2O(wszScratch, szName, MAX_PATH);
hr = pCTL->CreateTypeInfo(wszScratch, TKIND_UNION, &pCTI);
if SUCCEEDED(hr)
{
// remember the ICreateTypeInfo pointer
_pCTI = pCTI;
gpobjholder->Add(pCTI);
pCCB->SetCreateTypeInfo(pCTI);
CG_ITERATOR I;
CG_CLASS * pCG;
GetMembers(I);
I.Init();
unsigned uRememberPreviousVarNum = pCCB->GetVarNum();
pCCB->SetVarNum(0);
// walk members, adding them to the type info
while (ITERATOR_GETNEXT(I, pCG))
{
CG_STATUS cgs = pCG->GenTypeInfo(pCCB);
switch (cgs)
{
case CG_NOT_LAYED_OUT:
fICanLayOut = FALSE;
// fall through
case CG_REF_NOT_LAYED_OUT:
fDependentsLayedOut = FALSE;
// fall through
default:
break;
}
}
pCCB->SetVarNum((unsigned short)uRememberPreviousVarNum);
// Set all common type attributes
WALK_CTXT ctxt(GetType());
hr = pCTI->SetTypeFlags(GetTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *)ctxt.ExtractAttribute(ATTR_GUID);
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
node_version * pVer = (node_version *) ctxt.GetAttribute(ATTR_VERSION);
if (pVer)
pVer->GetVersion(&Maj, &Min);
else
{
Maj = Min = 0;
}
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
ReadyForLayOut();
if (fICanLayOut)
{
hr = pCTI->SetAlignment( GetMemoryAlignment() );
hr = pCTI->LayOut();
if FAILED(hr)
{
ReportTLGenError( "LayOut failed on union", szName, hr);
}
LayedOut();
if (!fDependentsLayedOut)
{
// The only way I can get here is if my dependents were either blocked by me
// or blocked by one of my ancestors.
// Now that I've been layed out, they may no longer be blocked.
BOOL fSucceeded = TRUE;
I.Init();
while (ITERATOR_GETNEXT(I, pCG))
{
CG_STATUS cgs = pCG->GenTypeInfo(pCCB);
if (CG_OK != cgs)
fSucceeded = FALSE;
}
if (fSucceeded)
{
DepsLayedOut();
return CG_OK;
}
return CG_REF_NOT_LAYED_OUT;
}
DepsLayedOut();
return CG_OK;
}
}
else
{
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
}
return CG_NOT_LAYED_OUT;
}
//+---------------------------------------------------------------------------
//
// Member: CG_PROC::GenTypeInfo
//
// Synopsis: generates a type info for a procedure
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_PROC::GenTypeInfo(CCB *pCCB)
{
OLECHAR ** rgwsz = NULL;
FUNCDESC fdesc;
memset(&fdesc, 0, sizeof(FUNCDESC));
fdesc.memid = DISPID_UNKNOWN;
CG_RETURN * pRet = GetReturnType();
TYPEDESC * ptdesc = NULL;
CG_CLASS * pComplexReturnType = NULL;
//
// If the function has a complex return type, it get's transformed such
// that the return type is represented as an extra parameter which is a
// simple ref pointer to the type. The actual return type is void.
// Oleaut doesn't like this however so mangle things around.
//
if ( HasComplexReturnType() )
{
CG_CLASS *pPrev = NULL;
CG_CLASS *pCur = GetChild();
// Find the last param
while ( NULL != pCur->GetSibling() )
{
pPrev = pCur;
pCur = pCur->GetSibling();
}
MIDL_ASSERT( NULL == pRet );
pRet = (CG_RETURN *) pCur;
// Make the return type the actual type, not a pointer to the type
pComplexReturnType = pRet->GetChild();
pRet->SetChild( pComplexReturnType->GetChild() );
SetReturnType( pRet );
// Remove the extra "return type" param
if ( NULL == pPrev )
SetChild( NULL );
else
pPrev->SetSibling( NULL );
}
if (pRet)
{
pRet->GetTypeDesc(ptdesc, pCCB);
if (!ptdesc)
{
ReportTLGenError( "return type has no type", GetSymName(), 0);
}
memcpy(&fdesc.elemdescFunc.tdesc, ptdesc, sizeof(TYPEDESC));
}
else
{
// no return type specified
// CONSIDER - emit warning?
fdesc.elemdescFunc.tdesc.vt = VT_VOID;
}
node_proc * pProc = (node_proc *)GetType();
WALK_CTXT ctxt(pProc);
fdesc.elemdescFunc.idldesc.wIDLFlags = GetIDLFlags(&ctxt);
BOOL fPropGet, fPropPut, fPropPutRef, fVararg;
fdesc.wFuncFlags = (unsigned short)GetFuncFlags(&ctxt, &fPropGet, &fPropPut, &fPropPutRef, &fVararg);
ICreateTypeInfo * pCTI = pCCB->GetCreateTypeInfo();
CG_ITERATOR I;
CG_PARAM * pCG;
GetMembers(I);
int cParams = I.GetCount();
fdesc.cParams = (unsigned short)cParams;
fdesc.lprgelemdescParam = new ELEMDESC [fdesc.cParams];
memset(fdesc.lprgelemdescParam, 0, sizeof(ELEMDESC) * fdesc.cParams);
rgwsz = new WCHAR * [fdesc.cParams + 1];
memset(rgwsz, 0, sizeof (WCHAR *) * (fdesc.cParams + 1));
I.Init();
int nParam = 0;
while (ITERATOR_GETNEXT(I, pCG))
{
rgwsz[nParam + 1] = TranscribeA2O( pCG->GetSymName() );
TYPEDESC * ptdesc;
pCG->GetTypeDesc(ptdesc, pCCB);
memcpy(&fdesc.lprgelemdescParam[nParam].tdesc, ptdesc, sizeof (TYPEDESC));
delete ptdesc;
node_constant_attr * pCA;
WALK_CTXT ctxt(pCG->GetType());
fdesc.lprgelemdescParam[nParam].idldesc.wIDLFlags = GetIDLFlags(&ctxt);
if (pCG->IsOptional())
{
fdesc.cParamsOpt++;
fdesc.lprgelemdescParam[nParam].paramdesc.wParamFlags |= PARAMFLAG_FOPT;
if (pCA = (node_constant_attr *)ctxt.GetAttribute(ATTR_DEFAULTVALUE))
{
fdesc.cParamsOpt = 0;
fdesc.lprgelemdescParam[nParam].paramdesc.wParamFlags |= PARAMFLAG_FHASDEFAULT;
fdesc.lprgelemdescParam[nParam].paramdesc.pparamdescex = new PARAMDESCEX;
fdesc.lprgelemdescParam[nParam].paramdesc.pparamdescex->cBytes = sizeof(PARAMDESCEX);
TYPEDESC tdesc = fdesc.lprgelemdescParam[nParam].tdesc;
if (tdesc.vt == VT_PTR && (fdesc.lprgelemdescParam[nParam].idldesc.wIDLFlags & IDLFLAG_FOUT) != 0)
{
// handle OUT parameters correctly
tdesc = *tdesc.lptdesc;
}
GetValueFromExpression(
fdesc.lprgelemdescParam[nParam].paramdesc.pparamdescex->varDefaultValue,
tdesc,
pCA->GetExpr(),
pCCB->GetLcid(),
GetSymName());
}
else
{
if (!IsVariantBasedType(fdesc.lprgelemdescParam[nParam].tdesc))
{
fdesc.cParamsOpt = 0;
}
}
}
else
{
if (!pCG->IsRetval())
{
fdesc.cParamsOpt = 0;
}
}
nParam++;
if (pCG->IsRetval())
{
fdesc.lprgelemdescParam[nParam - 1].paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
}
}
unsigned cchPrefixString = 0;
if (fVararg)
{
fdesc.cParamsOpt = -1;
}
if (fPropGet)
{
fdesc.invkind = INVOKE_PROPERTYGET;
cchPrefixString = 4;
}
else if (fPropPut)
{
fdesc.invkind = INVOKE_PROPERTYPUT;
cchPrefixString = 4;
}
else if (fPropPutRef)
{
fdesc.invkind = INVOKE_PROPERTYPUTREF;
cchPrefixString = 7;
}
else
{
fdesc.invkind = INVOKE_FUNC;
}
switch(GetProckind())
{
case PROC_STATIC:
fdesc.funckind = FUNC_STATIC;
break;
case PROC_PUREVIRTUAL:
default:
fdesc.funckind = FUNC_PUREVIRTUAL;
break;
}
node_constant_attr *pCA;
unsigned uFunc = pCCB->GetProcNum();
if (pCCB->IsInDispinterface())
{
fdesc.funckind = FUNC_DISPATCH;
fdesc.memid = 0x60000000 + uFunc;
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_ID))
{
fdesc.memid = (ulong) pCA->GetExpr()->GetValue();
}
ATTR_T cc;
pProc->GetCallingConvention(cc);
switch(cc)
{
case ATTR_STDCALL:
fdesc.callconv = CC_STDCALL;
break;
case ATTR_CDECL:
fdesc.callconv = CC_CDECL;
break;
case ATTR_PASCAL:
fdesc.callconv = CC_PASCAL;
break;
case ATTR_FASTCALL:
case ATTR_FORTRAN:
// There is no appropriate CC setting for FASTCALL or FORTRAN
// CONSIDER - consider displaying a warning
default:
fdesc.callconv = CC_STDCALL;
break;
}
char * szName = GetSymName();
HRESULT hr = pCTI->AddFuncDesc(uFunc, &fdesc);
if (FAILED(hr))
{
ReportTLGenError( "AddFuncDesc failed", szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
// process custom attributes for function
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetFuncCustData(uFunc,
guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
// process custom attributes for each param.
I.Init();
nParam = 0;
while (ITERATOR_GETNEXT(I, pCG))
{
((named_node*)(pCG->GetType()))->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetParamCustData( uFunc,
nParam,
guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
pCA = (node_constant_attr *) ctxt.GetAttribute( ATTR_HELPSTRINGCONTEXT );
if ( pCA )
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetVarHelpStringContext( nParam, hc );
}
nParam++;
}
if (ptdesc)
{
DeleteTypedescChildren(ptdesc);
delete ptdesc;
}
if (szName)
{
rgwsz[0] = TranscribeA2O( szName + cchPrefixString );
hr = pCTI->SetFuncAndParamNames(uFunc, rgwsz, fdesc.cParams + (fPropPut | fPropPutRef ? 0 : 1));
if (FAILED(hr))
{
ReportTLGenError( "SetFuncAndParamNames failed", szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetFuncDocString(uFunc, wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetFuncHelpContext(uFunc, hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetFuncHelpStringContext(uFunc, hc);
}
node_entry_attr * pEA;
if (pEA = (node_entry_attr *)ctxt.GetAttribute(ATTR_ENTRY))
{
if (!pCCB->GetDllName())
{
RpcError(NULL, 0, DLLNAME_REQUIRED, szName);
exit(ERR_TYPELIB_GENERATION);
}
A2O(wszScratch, pCCB->GetDllName(), MAX_PATH);
WCHAR * wszEntry;
if (pEA->IsNumeric())
{
wszEntry = (WCHAR *)pEA->GetID();
MIDL_ASSERT(HIWORD(wszEntry) == 0);
}
else
{
char * szEntry = pEA->GetSz();
MIDL_ASSERT(HIWORD(szEntry) != 0);
wszEntry = TranscribeA2O( szEntry );
}
hr = pCTI->DefineFuncAsDllEntry(uFunc, wszScratch, wszEntry);
if ( FAILED( hr ) )
{
ReportTLGenError( "Could not set entry point", szName, hr);
}
if (HIWORD(wszEntry))
delete [] wszEntry;
}
// clean up allocated stuff:
unsigned n;
// use cParams sinc fdesc.cParams might have been decrimented
for (n = cParams; n--; )
{
DeleteTypedescChildren(&fdesc.lprgelemdescParam[n].tdesc);
}
delete [] fdesc.lprgelemdescParam;
for (n = cParams + 1; n--; )
{
delete [] rgwsz[n];
}
delete [] rgwsz;
// bump the variable number
pCCB->SetProcNum(unsigned short(uFunc + 1));
// Undo the complex return type changes from above
if ( HasComplexReturnType() )
{
pRet->SetChild( pComplexReturnType );
CG_CLASS *pCur = GetChild();
if ( !pCur )
{
SetChild( pRet );
}
else
{
while ( NULL != pCur->GetSibling() )
pCur = pCur->GetSibling();
pCur->SetSibling( pRet );
}
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_PARAM::GetTypeDesc
//
// Synopsis: generates a TYPEDESC for a parameter
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_PARAM::GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB)
{
return(GetChild()->GetTypeDesc(ptd, pCCB));
}
//+---------------------------------------------------------------------------
//
// Member: CG_CASE::GenTypeInfo
//
// Synopsis: generates type information for a union member
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
// Notes: CG_CASE nodes are not interesting for type info generation
// since case information can't be stored in type libraries.
// However, CG_CASE nodes are often found between CG_UNION nodes
// and CG_FIELD nodes. This method just forwards the method
// call on down the chain.
//
//----------------------------------------------------------------------------
CG_STATUS CG_CASE::GenTypeInfo(CCB *pCCB)
{
return(GetChild()->GenTypeInfo(pCCB));
}
//+---------------------------------------------------------------------------
//
// Member: CG_FIELD::GenTypeInfo
//
// Synopsis: adds a Vardesc to the current type info for this union or
// structure field
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-13-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_FIELD::GenTypeInfo(CCB *pCCB)
{
if (IsReadyForLayOut())
{
// this node has been visited before, just make sure its dependents
// get the chance to lay themselves out
CG_CLASS * pCG = GetChild();
if (NULL == pCG)
return CG_OK;
TYPEDESC * ptdesc;
CG_STATUS cgs = pCG->GetTypeDesc(ptdesc, pCCB);
if (ptdesc)
{
DeleteTypedescChildren(ptdesc);
delete ptdesc;
}
return cgs;
}
VARDESC vdesc;
memset(&vdesc, 0, sizeof(VARDESC));
CG_CLASS * pCG = GetChild();
if (NULL == pCG)
return CG_OK;
char * szName = GetSymName();
TYPEDESC * ptdesc;
CG_STATUS cgs = pCG->GetTypeDesc(ptdesc, pCCB);
if (!ptdesc)
{
ReportTLGenError( "field has no type", szName, 0);
}
memcpy(&vdesc.elemdescVar.tdesc, ptdesc, sizeof(TYPEDESC));
WALK_CTXT ctxt(GetType());
vdesc.elemdescVar.idldesc.wIDLFlags = GetIDLFlags(&ctxt);
vdesc.wVarFlags = (unsigned short)GetVarFlags(&ctxt);
ICreateTypeInfo * pCTI = pCCB->GetCreateTypeInfo();
unsigned uVar = pCCB->GetVarNum();
node_constant_attr *pCA;
if (pCCB->IsInDispinterface())
{
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_ID))
{
vdesc.memid = (ulong) pCA->GetExpr()->GetValue();
}
else
{
vdesc.memid = 0x30000000 + uVar;
}
vdesc.varkind = VAR_DISPATCH;
}
else
{
vdesc.memid = DISPID_UNKNOWN;
vdesc.varkind = VAR_PERINSTANCE;
}
HRESULT hr = pCTI->AddVarDesc(uVar, &vdesc);
if (FAILED(hr))
{
ReportTLGenError( "AddVarDesc failed", szName, hr);
}
DeleteTypedescChildren(ptdesc);
delete ptdesc;
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetVarCustData( uVar,
guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
if (szName)
{
A2O(wszScratch, szName, MAX_PATH);
hr = pCTI->SetVarName(uVar, wszScratch);
if (FAILED(hr))
{
ReportTLGenError( "SetVarName failed", szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetVarDocString(uVar,wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetVarHelpContext(uVar, hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetVarHelpStringContext( uVar, hc );
}
// bump the variable number
pCCB->SetVarNum(unsigned short(uVar + 1));
ReadyForLayOut();
return cgs;
}
//+---------------------------------------------------------------------------
//
// Member: CG_TYPEDEF::GenTypeInfo
//
// Synopsis: generates a type info for a TYPEDEF
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_TYPEDEF::GenTypeInfo(CCB *pCCB)
{
// check to see if we've already been created
if (NULL != _pCTI)
{
pCCB->SetCreateTypeInfo((ICreateTypeInfo *) _pCTI);
if (!IsLayedOut())
{
if (!IsReadyForLayOut())
{
return CG_NOT_LAYED_OUT;
}
// give dependents a chance to be layed out
TYPEDESC * ptdesc;
CG_STATUS cgs = GetChild()->GetTypeDesc(ptdesc, pCCB);
if (ptdesc)
{
DeleteTypedescChildren(ptdesc);
delete ptdesc;
}
if (cgs == CG_OK)
{
HRESULT hr;
unsigned short MemAlignment = GetMemoryAlignment();
if ( MemAlignment )
hr = ((ICreateTypeInfo *)_pCTI )->SetAlignment( MemAlignment);
hr = ((ICreateTypeInfo *)_pCTI)->LayOut();
if (SUCCEEDED(hr))
{
LayedOut();
return CG_OK;
}
}
return cgs;
}
return CG_OK;
}
char * szName = GetSymName();
// Due to the nature of the MIDL compiler, it is possible that
// certain OLE Automation base types may show up here. The following
// test makes sure that type info isn't created for these types.
if ((0 == strcmp(szName, "VARIANT")) || (0 == strcmp(szName, "wireVARIANT"))
|| (0 == strcmp(szName, "DATE")) || (0 == strcmp(szName, "HRESULT"))
|| (0 == strcmp(szName, "CURRENCY")) || (0 == strcmp(szName, "CY"))
|| (0 == strcmp(szName, "DECIMAL"))
|| (0 == strcmp(szName, "wireBSTR")))
{
return CG_OK;
}
// SPECIAL CASE: If both the typedef and it's child share the same name, then
// we MUST NOT enter a TKIND_ALIAS for the typedef. Otherwise we will get name
// conflicts.
node_skl * pBasicType = GetBasicType();
NODE_T type = pBasicType->NodeKind();
if (type == NODE_STRUCT || type == NODE_ENUM || type == NODE_UNION)
{
char * szChildName = ((node_su_base *)pBasicType)->GetTypeInfoName();
if (szChildName)
{
if ( 0 == strcmp(szName, szChildName) && !GetChild()->IsInterfacePointer() )
{
return GetChild()->GenTypeInfo(pCCB);
}
}
}
ICreateTypeLib * pCTL = pCCB->GetCreateTypeLib();
ICreateTypeInfo * pCTI;
A2O(wszScratch, szName, MAX_PATH);
HRESULT hr = pCTL->CreateTypeInfo(wszScratch, TKIND_ALIAS, &pCTI);
if SUCCEEDED(hr)
{
// remember the ICreateTypeInfo pointer
_pCTI = pCTI;
gpobjholder->Add(pCTI, szName);
pCCB->SetCreateTypeInfo(pCTI);
TYPEDESC * ptdesc;
// Set all common type attributes
WALK_CTXT ctxt(GetType());
hr = pCTI->SetTypeFlags(GetTypeFlags(&ctxt));
if ( FAILED( hr ) )
{
ReportTLGenError( szErrTypeFlags, szName, hr);
}
ATTRLIST myAttrs;
node_base_attr * pCurAttr;
ATTR_T curAttrID;
VARIANT var;
GUID guid;
((named_node*)GetType())->GetAttributeList( myAttrs );
pCurAttr = myAttrs.GetFirst();
while ( pCurAttr )
{
curAttrID = pCurAttr->GetAttrID();
if (curAttrID == ATTR_CUSTOM)
{
ZeroMemory( &var,
sizeof(VARIANT));
ConvertToVariant( var,
((node_custom_attr*)pCurAttr)->GetVal(),
pCCB->GetLcid());
((node_custom_attr*)pCurAttr)->GetGuid()->GetGuid(guid);
((ICreateTypeInfo2 *)pCTI)->SetCustData(guid,
&var);
}
pCurAttr = pCurAttr->GetNext();
}
node_guid * pGuid = (node_guid *)ctxt.ExtractAttribute(ATTR_GUID);
if (pGuid)
{
GUID guid;
pGuid->GetGuid(guid);
hr = pCTI->SetGuid(guid);
if ( FAILED( hr ) )
{
ReportTLGenWarning( szErrUUID, szName, hr);
}
}
node_text_attr * pTA;
if (pTA = (node_text_attr *)ctxt.GetAttribute(ATTR_HELPSTRING))
{
char * szHelpString = pTA->GetText();
A2O(wszScratch, szHelpString, MAX_PATH);
hr = pCTI->SetDocString(wszScratch);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpString, szName, hr);
}
}
node_constant_attr *pCA;
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
hr = pCTI->SetHelpContext(hc);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrHelpContext, szName, hr);
}
}
if (pCA = (node_constant_attr *) ctxt.GetAttribute(ATTR_HELPSTRINGCONTEXT))
{
DWORD hc = (DWORD) pCA->GetExpr()->GetValue();
((ICreateTypeInfo2 *)pCTI)->SetHelpStringContext(hc);
}
unsigned short Maj;
unsigned short Min;
node_version * pVer = (node_version *) ctxt.GetAttribute(ATTR_VERSION);
if (pVer)
pVer->GetVersion(&Maj, &Min);
else
{
Maj = Min = 0;
}
hr = pCTI->SetVersion(Maj, Min);
if ( FAILED( hr ) )
{
ReportTLGenError( szErrVersion, szName, hr);
}
CG_STATUS cgs = GetChild()->GetTypeDesc(ptdesc, pCCB);
if (ptdesc)
{
hr = pCTI->SetTypeDescAlias(ptdesc);
if FAILED(hr)
{
ReportTLGenError( "SetTypeDescAlias failed", szName, hr);
}
DeleteTypedescChildren(ptdesc);
delete ptdesc;
}
ReadyForLayOut();
if (CG_NOT_LAYED_OUT != cgs)
{
if ( GetMemoryAlignment() )
hr = pCTI->SetAlignment( GetMemoryAlignment() );
hr = pCTI->LayOut();
if FAILED(hr)
{
ReportTLGenError( "LayOut failed on typedef",szName, hr);
}
LayedOut();
if (CG_REF_NOT_LAYED_OUT == cgs)
{
// The only way I can get here is if my dependents were either blocked by me
// or blocked by one of my ancestors.
// Now that I've been layed out, they may no longer be blocked.
TYPEDESC * ptdesc;
cgs = GetChild()->GetTypeDesc(ptdesc, pCCB);
if (ptdesc)
{
DeleteTypedescChildren(ptdesc);
delete ptdesc;
}
return (CG_OK == cgs ? CG_OK : CG_REF_NOT_LAYED_OUT);
}
}
return cgs;
}
else
{
// It's possible that this type has already been created.
if (NULL == (pCTI = (ICreateTypeInfo *)gpobjholder->Find(szName)))
ReportTLGenError( "CreateTypeInfo failed", szName, hr);
pCCB->SetCreateTypeInfo(pCTI);
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_FIXED_ARRAY::GetTypeDesc
//
// Synopsis: generates a TYPEDESC for an array
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_FIXED_ARRAY::GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB)
{
ptd = new TYPEDESC;
CG_CLASS * pElement = this;
unsigned short cDims = GetDimensions();
MIDL_ASSERT(cDims > 0);
ptd->vt = VT_CARRAY;
ptd->lpadesc = (ARRAYDESC *) new BYTE [ sizeof(ARRAYDESC) +
(cDims - 1) * sizeof (SAFEARRAYBOUND)
];
ptd->lpadesc->cDims = cDims;
int i;
for (i = 0; i<cDims; i++)
{
ptd->lpadesc->rgbounds[i].lLbound = 0;
ptd->lpadesc->rgbounds[i].cElements = ((CG_FIXED_ARRAY *)pElement)->GetNumOfElements();
pElement = pElement->GetChild();
}
TYPEDESC * ptdElem;
CG_STATUS cgs = pElement->GetTypeDesc(ptdElem, pCCB);
memcpy(&ptd->lpadesc->tdescElem, ptdElem, sizeof(TYPEDESC));
delete ptdElem;
return cgs;
}
//+---------------------------------------------------------------------------
//
// Member: CG_CONFORMANT_ARRAY::GetTypeDesc
//
// Synopsis: generates a TYPEDESC for a conformant array
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
// Notes: Conformant arrays are not directly representable in type
// info, so they get converted to pointers.
//
//----------------------------------------------------------------------------
CG_STATUS CG_CONFORMANT_ARRAY::GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB)
{
ptd = new TYPEDESC;
MIDL_ASSERT(1 == GetDimensions());
ptd->vt = VT_PTR;
CG_CLASS * pElement = GetChild();
CG_STATUS cgs = pElement->GetTypeDesc(ptd->lptdesc, pCCB);
return (CG_OK == cgs ? CG_OK : CG_REF_NOT_LAYED_OUT);
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE_POINTER::CheckImportLib
//
// Synopsis: Checks to see if a particular CG node has a definition in
// an imported type libaray.
//
// Returns: NULL => the node has no imported definition
// !NULL => ITypeInfo pointer for the imported type definition
//
// History: 6-14-95 stevebl Commented
//
// Notes: see description of CG_NDR::CheckImportLib
//
//----------------------------------------------------------------------------
void * CG_INTERFACE_POINTER::CheckImportLib()
{
node_skl * pn = GetTheInterface();
node_file * pf = pn->GetDefiningFile();
if (pf && (pf->GetImportLevel() > 0) )
{
A2O(wszScratch, pn->GetSymName(), MAX_PATH);
return(gtllist.FindName(pf->GetFileName(), wszScratch));
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CG_IIDIS_INTERFACE_POINTER::CheckImportLib
//
// Synopsis: Checks to see if a particular CG node has a definition in
// an imported type libaray.
//
// Returns: NULL => the node has no imported definition
// !NULL => ITypeInfo pointer for the imported type definition
//
// History: 6-14-95 stevebl Commented
//
// Notes: see description of CG_NDR::CheckImportLib
//
//----------------------------------------------------------------------------
void * CG_IIDIS_INTERFACE_POINTER::CheckImportLib()
{
node_skl * pn = GetBaseInterface();
node_file * pf = pn->GetDefiningFile();
if (pf && (pf->GetImportLevel() > 0) )
{
A2O(wszScratch, pn->GetSymName(), MAX_PATH);
return(gtllist.FindName(pf->GetFileName(), wszScratch));
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE_POINTER::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for an interface pointer
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
// Notes: IDispatch* and IUnknown* are treated as special cases since
// they are base types in ODL.
//
//----------------------------------------------------------------------------
CG_STATUS CG_INTERFACE_POINTER::GetTypeDesc(TYPEDESC * &ptd, CCB *pCCB)
{
ptd = new TYPEDESC;
named_node* pPointee = GetTheInterface();
if ( pPointee && pPointee->NodeKind() == NODE_INTERFACE_REFERENCE )
{
pPointee = ( ( node_interface_reference* ) pPointee )->GetRealInterface();
}
node_interface * pI = (node_interface*) pPointee;
char * sz = pI->GetSymName();
CG_STATUS cgs = CG_OK;
if (0 == _stricmp(sz, "IDispatch"))
{
ptd->vt = VT_DISPATCH;
}
else if (0 == _stricmp(sz, "IUnknown"))
{
ptd->vt = VT_UNKNOWN;
}
else
{
CG_CLASS * pCG = GetTypeAlias();
if (!pCG)
{
pCG = pI->GetCG(TRUE);
if (!pCG)
{
// This must be an imported definition.
// Call ILxlate to manufacture a CG node for it
XLAT_CTXT ctxt(GetType());
ctxt.SetAncestorBits(IL_IN_LIBRARY);
pCG = pI->ILxlate(&ctxt);
// make sure we get the right CG node
if (pI->GetCG(TRUE))
pCG = pI->GetCG(TRUE);
}
}
ptd->vt = VT_PTR;
cgs = pCG->GetTypeDesc(ptd->lptdesc, pCCB);
}
return cgs;
}
//+---------------------------------------------------------------------------
//
// Member: CG_IIDIS_INTERFACE_POINTER::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for an interface pointer
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
// Notes: IDispatch* and IUnknown* are treated as special cases since
// they are base types in ODL.
//
//----------------------------------------------------------------------------
CG_STATUS CG_IIDIS_INTERFACE_POINTER::GetTypeDesc(TYPEDESC * &ptd, CCB *pCCB)
{
ptd = new TYPEDESC;
pCCB;
node_interface * pI = (node_interface*) GetBaseInterface();
char * sz = pI->GetSymName();
CG_STATUS cgs = CG_OK;
if (0 == _stricmp(sz, "IDispatch"))
{
ptd->vt = VT_DISPATCH;
}
else if (0 == _stricmp(sz, "IUnknown"))
{
ptd->vt = VT_UNKNOWN;
}
else if ( pI->NodeKind() == NODE_VOID )
{
// this node is void * forced into interface because iid_is.
ptd->vt = VT_PTR ;
ptd->lptdesc = new TYPEDESC;
ptd->lptdesc->vt = VT_VOID;
}
else
{
// although it doesn't make sense to have (iid_is(riid), [out] IBar ** ppv),
// I still have the tlb preserves what user specified.
CG_CLASS * pCG = GetTypeAlias();
if (!pCG)
{
pCG = pI->GetCG(TRUE);
if (!pCG)
{
// This must be an imported definition.
// Call ILxlate to manufacture a CG node for it
XLAT_CTXT ctxt(GetType());
ctxt.SetAncestorBits(IL_IN_LIBRARY);
pCG = pI->ILxlate(&ctxt);
// make sure we get the right CG node
if (pI->GetCG(TRUE))
pCG = pI->GetCG(TRUE);
}
}
ptd->vt = VT_PTR;
cgs = pCG->GetTypeDesc(ptd->lptdesc, pCCB);
}
return cgs;
}
//+---------------------------------------------------------------------------
//
// Member: CG_INTERFACE_POINTER::GenTypeInfo
//
// Synopsis: generates type info for an interface pointer
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_INTERFACE_POINTER::GenTypeInfo(CCB * pCCB)
{
node_interface * pI = GetTheInterface();
char * sz = pI->GetSymName();
if (0 == _stricmp(sz, "IDispatch"))
{
return CG_OK;
}
else if (0 == _stricmp(sz, "IUnknown"))
{
return CG_OK;
}
CG_CLASS * pCG = pI->GetCG(TRUE);
if (!pCG)
{
// This must be an imported definition.
// Call ILxlate to manufacture a CG node for it
XLAT_CTXT ctxt(GetType());
ctxt.SetAncestorBits(IL_IN_LIBRARY);
pCG = pI->ILxlate(&ctxt);
// make sure we get the right CG node
pCG = pI->GetCG(TRUE);
}
return pCG->GenTypeInfo(pCCB);
}
//+---------------------------------------------------------------------------
//
// Member: CG_IIDIS_INTERFACE_POINTER::GenTypeInfo
//
// Synopsis: generates type info for an interface pointer
//
// Arguments: [pCCB] - CG control block
//
// Returns: CG_OK
// CG_NOT_LAYED_OUT
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_IIDIS_INTERFACE_POINTER::GenTypeInfo(CCB * pCCB)
{
node_skl * pBase = GetBaseInterface();
node_interface *pI;
char * sz = pBase->GetSymName();
// base can be void *
if ( 0 == _stricmp(sz, "IDispatch") ||
0 == _stricmp(sz, "IUnknown") ||
pBase->NodeKind() == NODE_VOID )
{
return CG_OK;
}
// semantic checking has forced the base to be either void **
// or interface
pI = (node_interface *)pBase;
//preserve what's in the idl
CG_CLASS * pCG = pI->GetCG(TRUE);
if (!pCG)
{
// This must be an imported definition.
// Call ILxlate to manufacture a CG node for it
XLAT_CTXT ctxt(GetType());
ctxt.SetAncestorBits(IL_IN_LIBRARY);
pCG = pI->ILxlate(&ctxt);
// make sure we get the right CG node
pCG = pI->GetCG(TRUE);
}
return pCG->GenTypeInfo(pCCB);
}
//+---------------------------------------------------------------------------
//
// Member: CG_STRING_POINTER::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for a string pointer
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_REF_NOT_LAYED_OUT
//
// History: 10-26-95 stevebl Created
//
// Notes: BSTR, LPSTR and LPWSTR are handled as special cases because
// they are base types in ODL.
//
//----------------------------------------------------------------------------
CG_STATUS CG_STRING_POINTER::GetTypeDesc(TYPEDESC * &ptd, CCB* )
{
ptd = new TYPEDESC;
ptd->lptdesc = NULL;
if (((CG_STRING_POINTER *)this)->IsBStr())
{
ptd->vt = VT_BSTR;
}
else if (1 == ((CG_NDR *)GetChild())->GetMemorySize())
{
ptd->vt = VT_LPSTR;
}
else
{
ptd->vt = VT_LPWSTR;
}
return CG_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CG_POINTER::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for a pointer
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_POINTER::GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB)
{
ptd = new TYPEDESC;
ptd->vt = VT_PTR;
CG_CLASS * pCG = GetChild();
CG_STATUS cgs = pCG->GetTypeDesc(ptd->lptdesc, pCCB);
return (CG_OK == cgs ? CG_OK : CG_REF_NOT_LAYED_OUT);
}
//+---------------------------------------------------------------------------
//
// Member: CG_SAFEARRAY::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for a SAFEARRAY
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
// CG_REF_NOT_LAYED_OUT
//
// History: 6-14-95 stevebl Commented
//
//----------------------------------------------------------------------------
CG_STATUS CG_SAFEARRAY::GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB)
{
ptd = new TYPEDESC;
ptd->vt = VT_SAFEARRAY;
CG_STATUS cgs = GetChild()->GetTypeDesc(ptd->lptdesc, pCCB);
return (CG_OK == cgs ? CG_OK : CG_REF_NOT_LAYED_OUT);
}
//+---------------------------------------------------------------------------
//
// The order of the items in this table must match the order of the items
// in the node_t enumeration defined in midlnode.hxx.
//
// To make the dependency visible to C++ the browser, the third column has
// explicit node_t enums that otherwise are not used for any purpose. (rkk).
//
// There is a VT_INT_PTR in the public headers that corresponds to __int3264.
// However, it is defined currently to VT_I4 or VT_I8, and definition can
// change on us unexpectedly. /use_vt_int_ptr switch addresses that problem.
//
// This table is used for Win32 with VT_INT_PTR being represented as VT_I4.
//
VARTYPE rgMapOldBaseTypeToVARTYPE[][3] = // This table used for Win32.
{
// unsigned signed not used
{VT_R4, VT_R4, (VARTYPE) NODE_FLOAT },
{VT_R8, VT_R8, (VARTYPE) NODE_DOUBLE },
{0, 0, (VARTYPE) NODE_FLOAT80 }, //not in TLB
{0, 0, (VARTYPE) NODE_FLOAT128 }, //not in TLB
{VT_UI8, VT_I8, (VARTYPE) NODE_HYPER },
{VT_UI8, VT_I8, (VARTYPE) NODE_INT64 },
{0, 0, (VARTYPE) NODE_INT128 }, //not in TLB
{VT_UI4, VT_I4, (VARTYPE) NODE_INT3264 },
{VT_UI4, VT_I4, (VARTYPE) NODE_INT32 },
{VT_UI4, VT_I4, (VARTYPE) NODE_LONG },
{VT_UI8, VT_I8, (VARTYPE) NODE_LONGLONG },
{VT_UI2, VT_I2, (VARTYPE) NODE_SHORT },
{VT_UINT, VT_INT, (VARTYPE) NODE_INT },
{VT_UI1, VT_I1, (VARTYPE) NODE_SMALL },
{VT_UI1, VT_I1, (VARTYPE) NODE_CHAR },
{VT_UI1, VT_I1, (VARTYPE) NODE_BOOLEAN },
{VT_UI1, VT_I1, (VARTYPE) NODE_BYTE },
{VT_VOID, VT_VOID, (VARTYPE) NODE_VOID },
{VT_UI2, VT_I2, (VARTYPE) NODE_HANDLE_T },
{0, 0, (VARTYPE) NODE_FORWARD },
{VT_UI2, VT_I2, (VARTYPE) NODE_WCHAR_T }
};
// This table used for Win32 with VT_INT_PTR being represented as VT_INT_PTR.
// The table is used when the -use_vt_int_ptr is used.
VARTYPE rgMapBaseTypeToVARTYPE[][3] = // This table used for Win32.
{
// unsigned signed not used
{VT_R4, VT_R4, (VARTYPE) NODE_FLOAT },
{VT_R8, VT_R8, (VARTYPE) NODE_DOUBLE },
{0, 0, (VARTYPE) NODE_FLOAT80 }, //not in TLB
{0, 0, (VARTYPE) NODE_FLOAT128 }, //not in TLB
{VT_UI8, VT_I8, (VARTYPE) NODE_HYPER },
{VT_UI8, VT_I8, (VARTYPE) NODE_INT64 },
{0, 0, (VARTYPE) NODE_INT128 }, //not in TLB
{VT_UINT_PTR, VT_INT_PTR, (VARTYPE) NODE_INT3264 },
{VT_UI4, VT_I4, (VARTYPE) NODE_INT32 },
{VT_UI4, VT_I4, (VARTYPE) NODE_LONG },
{VT_UI8, VT_I8, (VARTYPE) NODE_LONGLONG },
{VT_UI2, VT_I2, (VARTYPE) NODE_SHORT },
{VT_UINT, VT_INT, (VARTYPE) NODE_INT },
{VT_UI1, VT_I1, (VARTYPE) NODE_SMALL },
{VT_UI1, VT_I1, (VARTYPE) NODE_CHAR },
{VT_UI1, VT_I1, (VARTYPE) NODE_BOOLEAN },
{VT_UI1, VT_I1, (VARTYPE) NODE_BYTE },
{VT_VOID, VT_VOID, (VARTYPE) NODE_VOID },
{VT_UI2, VT_I2, (VARTYPE) NODE_HANDLE_T },
{0, 0, (VARTYPE) NODE_FORWARD },
{VT_UI2, VT_I2, (VARTYPE) NODE_WCHAR_T }
};
// This table used for Win64 with VT_INT_PTR being represented as VT_I8.
VARTYPE rgMapOld64BaseTypeToVARTYPE[][3] =
{
// unsigned signed not used
{VT_R4, VT_R4, (VARTYPE) NODE_FLOAT },
{VT_R8, VT_R8, (VARTYPE) NODE_DOUBLE },
{0, 0, (VARTYPE) NODE_FLOAT80 }, //not in TLB
{0, 0, (VARTYPE) NODE_FLOAT128 }, //not in TLB
{VT_UI8, VT_I8, (VARTYPE) NODE_HYPER },
{VT_UI8, VT_I8, (VARTYPE) NODE_INT64 },
{0, 0, (VARTYPE) NODE_INT128 }, //not in TLB
{VT_UI8, VT_I8, (VARTYPE) NODE_INT3264 },
{VT_UI4, VT_I4, (VARTYPE) NODE_INT32 },
{VT_UI4, VT_I4, (VARTYPE) NODE_LONG },
{VT_UI8, VT_I8, (VARTYPE) NODE_LONGLONG },
{VT_UI2, VT_I2, (VARTYPE) NODE_SHORT },
{VT_UINT, VT_INT, (VARTYPE) NODE_INT },
{VT_UI1, VT_I1, (VARTYPE) NODE_SMALL },
{VT_UI1, VT_I1, (VARTYPE) NODE_CHAR },
{VT_UI1, VT_I1, (VARTYPE) NODE_BOOLEAN },
{VT_UI1, VT_I1, (VARTYPE) NODE_BYTE },
{VT_VOID, VT_VOID, (VARTYPE) NODE_VOID },
{VT_UI2, VT_I2, (VARTYPE) NODE_HANDLE_T },
{0, 0, (VARTYPE) NODE_FORWARD },
{VT_UI2, VT_I2, (VARTYPE) NODE_WCHAR_T }
};
// This table used for Win64 with VT_INT_PTR being represented as VT_INT_PTR.
// The table is used when the -use_vt_int_ptr is used.
VARTYPE rgMap64BaseTypeToVARTYPE[][3] = // This table used for Win64.
{
// unsigned signed not used
{VT_R4, VT_R4, (VARTYPE) NODE_FLOAT },
{VT_R8, VT_R8, (VARTYPE) NODE_DOUBLE },
{0, 0, (VARTYPE) NODE_FLOAT80 }, // not in TLB
{0, 0, (VARTYPE) NODE_FLOAT128 }, // not in TLB
{VT_UI8, VT_I8, (VARTYPE) NODE_HYPER },
{VT_UI8, VT_I8, (VARTYPE) NODE_INT64 },
{0, 0, (VARTYPE) NODE_INT128 }, // not in TLB
{VT_UINT_PTR, VT_INT_PTR, (VARTYPE) NODE_INT3264 },
{VT_UI4, VT_I4, (VARTYPE) NODE_INT32 },
{VT_UI4, VT_I4, (VARTYPE) NODE_LONG },
{VT_UI8, VT_I8, (VARTYPE) NODE_LONGLONG },
{VT_UI2, VT_I2, (VARTYPE) NODE_SHORT },
{VT_UINT, VT_INT, (VARTYPE) NODE_INT },
{VT_UI1, VT_I1, (VARTYPE) NODE_SMALL },
{VT_UI1, VT_I1, (VARTYPE) NODE_CHAR },
{VT_UI1, VT_I1, (VARTYPE) NODE_BOOLEAN },
{VT_UI1, VT_I1, (VARTYPE) NODE_BYTE },
{VT_VOID, VT_VOID, (VARTYPE) NODE_VOID },
{VT_UI2, VT_I2, (VARTYPE) NODE_HANDLE_T },
{0, 0, (VARTYPE) NODE_FORWARD },
{VT_UI2, VT_I2, (VARTYPE) NODE_WCHAR_T }
};
//+---------------------------------------------------------------------------
//
// Member: CG_BASETYPE::GetTypeDesc
//
// Synopsis: creates a TYPEDESC for a base type
//
// Arguments: [ptd] - reference to a TYPEDESC pointer
// [pCCB] - CG control block
//
// Returns: CG_OK
//
// History: 6-14-95 stevebl Commented
//
// Notes: rgIntrinsic contains an array of types which are intrinsic
// types in ODL but are not INTRINSIC types in IDL, therefore
// they must be treated as a special case.
//
//----------------------------------------------------------------------------
CG_STATUS CG_BASETYPE::GetTypeDesc(TYPEDESC * &ptd, CCB* )
{
node_skl * pskl = GetType();
while (NODE_DEF == pskl->NodeKind())
{
char * szName = pskl->GetSymName();
int iIntrinsicType = 0;
while (iIntrinsicType < (sizeof(rgIntrinsic) / sizeof(INTRINSIC)))
{
int i = _stricmp(szName, rgIntrinsic[iIntrinsicType].szType);
if (i == 0)
{
ptd = new TYPEDESC;
ptd->lptdesc = NULL;
ptd->vt = rgIntrinsic[iIntrinsicType].vt;
return CG_OK;
}
iIntrinsicType++;
}
pskl = pskl->GetChild();
}
NODE_T type = pskl->NodeKind();
unsigned short Option = pCommand->GetCharOption ();
// CONSIDER - perhaps this should be an assertion
if (type < BASE_NODE_START || type >= BASE_NODE_END || NODE_FORWARD == type)
{
ReportTLGenError( "bad type", GetSymName(), 0);
}
int iTable = 1;
if (pskl->FInSummary(ATTR_UNSIGNED) || type == NODE_BYTE || type == NODE_WCHAR_T )
{
iTable = 0;
}
else if (pskl->FInSummary(ATTR_SIGNED))
{
iTable = 1;
}
else if (NODE_CHAR == type || NODE_SMALL == type)
{
iTable = (CHAR_SIGNED == Option) ? 1 : 0;
}
/*
INT_PTR problem
Old .tlb and old oleaut32.dll don't support VT_INT_PTR. Adding 32bit
support for the new VT code creates backward compatibility problem.
To work aroud the problem, we define a new switch -use_vt_int_ptr.
If this is not defined, we'll save VT_INT_PTR as VT_I4.
*/
VARTYPE vt;
if (NODE_BOOLEAN == type && pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
vt = VT_BOOL;
else
if ( pCommand->Is64BitEnv() )
{
if ( pCommand->IsSwitchDefined(SWITCH_USE_VT_INT_PTR) )
vt = rgMap64BaseTypeToVARTYPE[type - BASE_NODE_START][iTable];
else
vt = rgMapOld64BaseTypeToVARTYPE[type - BASE_NODE_START][iTable];
}
else
{
if ( pCommand->IsSwitchDefined(SWITCH_USE_VT_INT_PTR) )
vt = rgMapBaseTypeToVARTYPE[type - BASE_NODE_START][iTable];
else
vt = rgMapOldBaseTypeToVARTYPE[type - BASE_NODE_START][iTable];
}
ptd = new TYPEDESC;
ptd->lptdesc = NULL;
ptd->vt = vt;
return CG_OK;
}
// The following two functions are necessary because this information
// is needed within TYPELIB.CXX and pCommand isn't visible to
// that module.
int FOldTlbSwitch(void)
{
return (pCommand->IsSwitchDefined(SWITCH_OLD_TLB));
}
int FNewTlbSwitch(void)
{
return (pCommand->IsSwitchDefined(SWITCH_NEW_TLB));
}
/*
This routine returns TRUE if the expression is evaluated as a floating point expression.
The results of the evaluation are returned in var.
*/
BOOL EvaluateFloatExpr( VARIANT& var, expr_node* pExpr )
{
BOOL fIsFloat = FALSE;
if ( pExpr->IsConstant() )
{
SExprValue v = {VALUE_TYPE_UNDEFINED, 0};
BOOL fSuccess = pExpr->GetExprValue( v );
if (fSuccess)
{
if ( v.format == VALUE_TYPE_FLOAT )
{
var.vt = VT_R4;
var.fltVal = v.f;
fIsFloat = TRUE;
}
else if ( v.format == VALUE_TYPE_DOUBLE )
{
var.vt = VT_R8;
var.dblVal = v.d;
fIsFloat = TRUE;
}
}
else if ( v.format != VALUE_TYPE_UNDEFINED )
{
RpcError(NULL, 0, INVALID_FLOAT, 0);
}
}
return fIsFloat;
}
//=============================================================================
//=============================================================================
//=============================================================================
void ConvertToVariant(VARIANT & var, expr_node * pExpr, LCID lcid)
{
if ( EvaluateFloatExpr( var, pExpr) )
{
// this is a floating point expression.
return;
}
EXPR_VALUE val = pExpr->GetValue();
if (pExpr->IsStringConstant() && !IsBadStringPtr((char *)val, 256))
{
char * sz = (char *) val;
TranslateEscapeSequences(sz);
WCHAR * wsz = TranscribeA2O( sz );
VARIANT varTemp;
varTemp.bstrVal = LateBound_SysAllocString(wsz);
varTemp.vt = VT_BSTR;
HRESULT hr;
// try floating point numeric types first
hr = LateBound_VariantChangeTypeEx(&var, &varTemp, lcid, 0, VT_R8);
if (FAILED(hr))
{
// if it can't be coerced into a floating point type, then just stuff the BSTR value
var.bstrVal = LateBound_SysAllocString(wsz);
var.vt = VT_BSTR;
}
LateBound_SysFreeString(varTemp.bstrVal);
delete [] wsz;
}
else
{
var.vt = VT_I4;
var.lVal = (long) val;
}
}
void GetValueFromExpression(VARIANT & var, TYPEDESC tdesc, expr_node * pExpr, LCID lcid, char * szSymName)
{
memset(&var, 0, sizeof(VARIANT));
if ( EvaluateFloatExpr( var, pExpr) )
{
// this is a floating point expression.
return;
}
if (tdesc.vt == VT_PTR && (tdesc.lptdesc->vt == VT_I1 || tdesc.lptdesc->vt == VT_VARIANT))
{
// Fool switch into realizing that the data should be in string form.
tdesc.vt = VT_LPSTR;
}
// set the value
switch (tdesc.vt)
{
case VT_BOOL:
// var.vt = VT_BOOL;
// var.boolVal = (pExpr->GetValue() ? VARIANT_TRUE : VARIANT_FALSE);
// break;
case VT_I1:
case VT_UI1:
// var.vt = VT_UI1;
// var.bVal = (unsigned char) pExpr->GetValue();
// break;
case VT_UI2:
// var.vt = VT_UI4;
// var.ulVal = (unsigned short) pExpr->GetValue();
// break;
case VT_I2:
var.vt = VT_I2;
var.iVal = (short) pExpr->GetValue();
break;
case VT_UI4:
// var.vt = VT_UI4;
// var.ulVal = (unsigned long) pExpr->GetValue();
// break;
case VT_UINT:
// var.vt = VT_UI4;
// var.ulVal = (unsigned int) pExpr->GetValue();
// break;
case VT_INT:
case VT_I4:
var.vt = VT_I4;
var.lVal = (long) pExpr->GetValue();
break;
case VT_DISPATCH:
case VT_UNKNOWN:
//var.vt = vt;
var.vt = VT_I4;
if (pExpr->GetValue())
{
RpcError(NULL, 0, ILLEGAL_CONSTANT, szSymName);
exit(ERR_TYPELIB_GENERATION);
}
var.ppunkVal = NULL; // the only supported value for constants of this type
break;
case VT_ERROR:
var.vt = VT_I4;
// var.vt = VT_ERROR;
var.lVal = (long) pExpr->GetValue();
// var.scode = (SCODE) pExpr->GetValue();
break;
case VT_LPSTR:
case VT_LPWSTR:
{
var.vt = VT_BSTR;
var.bstrVal = 0;
EXPR_VALUE val = pExpr->GetValue();
if (pExpr->IsStringConstant() && !IsBadStringPtr((char *)val, 256))
{
// Constants of these types may be defined as a string.
// Convert the string to a BSTR and use VariantChangeType to
// coerce the BSTR to the appropriate variant type.
char * sz = (char *) val;
TranslateEscapeSequences(sz);
WCHAR * wsz = TranscribeA2O( sz );
var.bstrVal = LateBound_SysAllocString(wsz);
delete [] wsz;
}
else
{
// get the value as a LONG and coerce it to the correct type.
// If the value is not a string then it should be NULL.
if (pExpr->GetValue())
{
// value wasn't NULL
// convert it to a string
char sz[40];
WCHAR wsz [40];
sprintf(sz,"%li",val);
A2O(wsz, sz, 40);
var.bstrVal = LateBound_SysAllocString(wsz);
}
}
}
break;
case VT_R4:
case VT_R8:
case VT_I8:
case VT_UI8:
case VT_CY:
case VT_DATE:
case VT_BSTR:
case VT_DECIMAL:
{
VARIANT varTemp;
HRESULT hr;
EXPR_VALUE val = pExpr->GetValue();
if (pExpr->IsStringConstant() && !IsBadStringPtr((char *)val, 256))
{
// Constants of these types may be defined as a string.
// Convert the string to a BSTR and use VariantChangeType to
// coerce the BSTR to the appropriate variant type.
char * sz = (char *) val;
WCHAR * wsz = TranscribeA2O( sz );
varTemp.bstrVal = LateBound_SysAllocString(wsz);
varTemp.vt = VT_BSTR;
delete [] wsz;
hr = LateBound_VariantChangeTypeEx(&var, &varTemp, lcid, 0, tdesc.vt);
if (FAILED(hr))
{
RpcError(NULL, 0, CONSTANT_TYPE_MISMATCH, szSymName);
exit(ERR_TYPELIB_GENERATION);
}
LateBound_SysFreeString(varTemp.bstrVal);
}
else
{
// get the value as a LONG and coerce it to the correct type.
varTemp.vt = VT_I4;
varTemp.lVal = (long) val;
hr = LateBound_VariantChangeTypeEx(&var, &varTemp, lcid, 0, tdesc.vt);
if (FAILED(hr))
{
RpcError(NULL, 0, CONSTANT_TYPE_MISMATCH, szSymName);
exit(ERR_TYPELIB_GENERATION);
}
}
}
break;
case VT_VARIANT:
ConvertToVariant(var, pExpr, lcid);
break;
case VT_VOID:
case VT_HRESULT:
case VT_SAFEARRAY:
case VT_CARRAY:
case VT_USERDEFINED:
case VT_PTR:
default:
ConvertToVariant(var, pExpr, lcid);
// assert(!"Illegal constant value");
// var.vt = VT_I4; // put us in a legal state just to keep code from crashing
}
}
unsigned long CG_INTERFACE::LayOut()
{
unsigned long ulRet = 0;
if (!IsLayedOut())
{
if (GetBaseInterfaceCG())
{
GetBaseInterfaceCG()->LayOut();
}
#ifdef __TRACE_LAYOUT__
printf("LayOut, %s\n", GetType()->GetSymName());
#endif
ICreateTypeInfo* pCTI = (ICreateTypeInfo*)_pCTI;
// ulRet = (pCTI) ? pCTI->LayOut() : TYPE_E_INVALIDSTATE;
if (pCTI)
{
HRESULT hr;
// Alignment is not defined for interfaces, so we set it
// to an arbitrary value, same as mktplib.
hr = pCTI->SetAlignment( pCommand->GetZeePee() );
ulRet = pCTI->LayOut();
}
LayedOut();
}
return ulRet;
}
unsigned long CG_COCLASS::LayOut()
{
unsigned long ulRet = 0;
if (!IsLayedOut())
{
#ifdef __TRACE_LAYOUT__
printf("LayOut, %s\n", GetType()->GetSymName());
#endif
ICreateTypeInfo* pCTI = (ICreateTypeInfo*)_pCTI;
// ulRet = (pCTI) ? pCTI->LayOut() : TYPE_E_INVALIDSTATE;
if (pCTI)
{
HRESULT hr;
// Alignment is not defined for coclasses, so we set it
// to an arbitrary value, same as mktplib.
hr = pCTI->SetAlignment( pCommand->GetZeePee() );
ulRet = pCTI->LayOut();
}
LayedOut();
}
return ulRet;
}
unsigned long CG_MODULE::LayOut()
{
unsigned long ulRet = 0;
if (!IsLayedOut())
{
#ifdef __TRACE_LAYOUT__
printf("LayOut, %s\n", GetType()->GetSymName());
#endif
ICreateTypeInfo* pCTI = (ICreateTypeInfo*)_pCTI;
// ulRet = (pCTI) ? pCTI->LayOut() : TYPE_E_INVALIDSTATE;
if (pCTI)
{
HRESULT hr;
// Alignment is not defined for modules, so we set it
// to an arbitrary value, same as mktplib.
hr = pCTI->SetAlignment( pCommand->GetZeePee() );
ulRet = pCTI->LayOut();
}
LayedOut();
}
return ulRet;
}
WCHAR *
TranscribeA2O( char * sz )
//+---------------------------------------------------------------------------
//
// Synopsis: creates a unicode string corresponding to a multibyte string.
//
// Arguments: sz - multibyte string
//
// Returns: the unicode string
//
// History: 1-3-97 ryszardk Created
//
//----------------------------------------------------------------------------
{
// The length includes the terminating character.
unsigned long cc = (unsigned long) strlen(sz)+1;
unsigned long cw = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, cc, 0, 0);
WCHAR * wsz = new WCHAR [cw];
wsz[0] = 0;
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, sz, cc, wsz, cw );
return wsz;
}
char *
TranscribeO2A( BSTR bstr )
//+---------------------------------------------------------------------------
//
// Synopsis: creates a multibyte string corresponding to a unicode string.
//
// Arguments: bstr - the unicode string
//
// Returns: the multibyte string
//
// History: 1-3-97 ryszardk Created
//
//----------------------------------------------------------------------------
{
// The length includes the terminating character.
unsigned long cw = (unsigned long) wcslen(bstr)+1;
unsigned long cc = WideCharToMultiByte( CP_ACP, 0, bstr, cw, 0, 0, 0, 0);
char * sz = new char [cc];
sz[0] = 0;
WideCharToMultiByte( CP_ACP, 0, bstr, cw, sz, cc, 0, 0 );
return sz;
}