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.
2529 lines
84 KiB
2529 lines
84 KiB
#include "headers.hxx"
|
|
|
|
// COM+ shim. Uncomment below line to build the COM+ shim.
|
|
//#define COMPLUS_SHIM
|
|
|
|
#ifndef X_PDLPARSE_HXX_
|
|
#define X_PDLPARSE_HXX_
|
|
#include "pdlparse.hxx"
|
|
#endif
|
|
|
|
#ifndef X_DATA_HXX_
|
|
#define X_DATA_HXX_
|
|
#include "data.hxx"
|
|
#endif
|
|
|
|
#ifndef X_VTABLE_HXX_
|
|
#define X_VTABLE_HXX_
|
|
#include <vtable.hxx>
|
|
#endif
|
|
|
|
#ifndef X_ASSERT_H_
|
|
#define X_ASSERT_H_
|
|
#include <assert.h>
|
|
#endif
|
|
|
|
// Win16 needs the old typelibs. Old Typelib can't cope
|
|
// with default parameters. So if this flag is set we
|
|
// ignore all the default parameters in the PDL files.
|
|
// This flag is set based on run-time argument "win16"
|
|
BOOL gbWin16Mode = FALSE;
|
|
|
|
|
|
//
|
|
// TO deal with the LONG_PTR problem : we need to translate it to different
|
|
// automation type for Win32 and Win64
|
|
//
|
|
BOOL gfWin64 = FALSE;
|
|
|
|
static
|
|
BOOL
|
|
GetALine ( FILE *fp, char *szLineBuffer, int nMaxLen, int &nLenRead );
|
|
|
|
|
|
void PDLError (char *szTextError)
|
|
{
|
|
printf ( "PDLParse (0) : error PDL0001: /G %s", szTextError);
|
|
}
|
|
|
|
|
|
BOOL TagArray::CompareTag ( INT nIndex, char *szWith )
|
|
{
|
|
if ( szValues [ nIndex ] == NULL )
|
|
return FALSE;
|
|
else
|
|
return _stricmp ( szValues [ nIndex ], szWith ) == 0 ? TRUE : FALSE;
|
|
}
|
|
|
|
char *TagArray::GetTagValue ( INT nIndex )
|
|
{
|
|
// If the string is null always return an empty string
|
|
if ( szValues [ nIndex ] == NULL )
|
|
return szEmptyString;
|
|
else
|
|
return szValues [ nIndex ];
|
|
}
|
|
|
|
BOOL TagArray::AddTag ( int iTag, LPCSTR szStr, int nLen )
|
|
{
|
|
if ( szValues [ iTag ] )
|
|
delete [] ( szValues [ iTag ] );
|
|
if ( nLen == -1 )
|
|
nLen = strlen ( szStr );
|
|
if ( szStr == NULL )
|
|
{
|
|
szValues [ iTag ] = NULL;
|
|
return TRUE;
|
|
}
|
|
szValues [ iTag ] = new char [ nLen + 1 ];
|
|
if ( !szValues [ iTag ] )
|
|
return FALSE;
|
|
strncpy ( szValues [ iTag ], szStr, nLen );
|
|
szValues [ iTag ][ nLen ] = '\0';
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
Token::~Token()
|
|
{
|
|
if ( _pChildList )
|
|
_pChildList -> Release();
|
|
}
|
|
|
|
void CTokenListWalker::Reset ( void )
|
|
{
|
|
_pCurrentToken = NULL;
|
|
if ( _pszFileName )
|
|
_fInCurrentFile = FALSE;
|
|
else
|
|
_fInCurrentFile = TRUE;
|
|
_fAtEnd = FALSE;
|
|
}
|
|
|
|
|
|
UINT CString::Lookup ( Associate *pArray, LPCSTR pStr )
|
|
{
|
|
UINT uIndex =0;
|
|
while ( pArray->szKey )
|
|
{
|
|
if ( strcmp ( pArray->szKey, pStr ) == 0 )
|
|
{
|
|
strcpy ( szString, pArray->szValue );
|
|
return uIndex;
|
|
}
|
|
pArray++; uIndex++;
|
|
}
|
|
return (UINT)-1;
|
|
}
|
|
|
|
UINT CString::Lookup ( AssociateDataType *pArray, LPCSTR pStr )
|
|
{
|
|
UINT uIndex =0;
|
|
while ( pArray->szKey )
|
|
{
|
|
if ( strcmp ( pArray->szKey, pStr ) == 0 )
|
|
{
|
|
strcpy ( szString, pArray->szValue );
|
|
return uIndex;
|
|
}
|
|
pArray++; uIndex++;
|
|
}
|
|
return (UINT)-1;
|
|
}
|
|
|
|
|
|
/* static */
|
|
char *TagArray::szEmptyString = "";
|
|
|
|
BOOL
|
|
GetStdInLine ( char *szLineBuffer, int nMaxLen )
|
|
{
|
|
int nLenRead,i;
|
|
int nTotalRead = 0;
|
|
|
|
do
|
|
{
|
|
if ( !GetALine ( NULL, szLineBuffer+nTotalRead,
|
|
nMaxLen, nLenRead ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
nTotalRead += nLenRead;
|
|
for ( i = nTotalRead-1 ; i >= 0 ; i-- )
|
|
{
|
|
if ( !isspace ( szLineBuffer [ i ] ) )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( i > 0 )
|
|
{
|
|
if ( szLineBuffer [ i ] == '\\' )
|
|
{
|
|
szLineBuffer [ i ] = ' ';
|
|
szLineBuffer [ i+1 ] = '\0';
|
|
// we'll go on to the next line
|
|
nTotalRead = i+1;
|
|
// Don't break, so we append the next line
|
|
}
|
|
else
|
|
{
|
|
// Regular line
|
|
szLineBuffer [ i+1 ] = '\0';
|
|
nTotalRead = i+1;
|
|
// Not continuing - break so we process this line
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Completly blank line - ignore it...
|
|
nTotalRead = 0;
|
|
}
|
|
} while ( nTotalRead < nMaxLen );
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
GetALine ( FILE *fp,char *szLineBuffer, int nMaxLen, int &nLenRead )
|
|
{
|
|
nLenRead = 0;
|
|
// Keep reading in data until we blow the buffer size, or hit a real
|
|
// EOL. If we have a trailing \ character, go on to the next line
|
|
if ( fp )
|
|
{
|
|
if ( !fgets ( szLineBuffer, nMaxLen, fp ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !gets ( szLineBuffer ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
nLenRead = strlen ( szLineBuffer );
|
|
if ( szLineBuffer [ 0 ] && szLineBuffer [ nLenRead-1 ] == '\n' )
|
|
{
|
|
szLineBuffer [ --nLenRead ] = '\0';
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
Token *CTokenList::FindToken ( char *pTokenName, DESCRIPTOR_TYPE nType ) const
|
|
{
|
|
Token *pToken;
|
|
|
|
for ( pToken = _pFirstToken ;
|
|
pToken != NULL ; pToken = pToken-> GetNextToken() )
|
|
{
|
|
// Token 0 is always the name
|
|
// Case sensitive match
|
|
if ( strcmp ( pToken->GetTagValue ( 0 ), pTokenName ) == 0 )
|
|
{
|
|
return pToken->GetType() ? pToken : NULL;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
Token *CTokenList::AddNewToken ( DESCRIPTOR_TYPE nTokenDescriptor )
|
|
{
|
|
Token *pNewToken = new Token ( nTokenDescriptor );
|
|
|
|
if ( !pNewToken )
|
|
return NULL;
|
|
|
|
if ( !_pFirstToken )
|
|
{
|
|
_pFirstToken = pNewToken;
|
|
}
|
|
else
|
|
{
|
|
_pLastToken->SetNextToken ( pNewToken );
|
|
}
|
|
_pLastToken = pNewToken;
|
|
_uTokens++;
|
|
return pNewToken;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Scan the input file and extract the 4 build arguments
|
|
Do this to be compatible with previous version of mkprop
|
|
*/
|
|
//--------------------------------------------------
|
|
//TODO: Modify this to accept flags for ia64/i386!
|
|
//--------------------------------------------------
|
|
static
|
|
BOOL
|
|
ScanBuildFile ( char *szBuildFileName,
|
|
char *szInputFile,
|
|
char *szOutputFileRoot,
|
|
char *szPDLFileName,
|
|
char *szOutputPath )
|
|
{
|
|
FILE *fp = NULL;
|
|
char szLineBuffer [ MAX_LINE_LEN+1 ];
|
|
BOOL fReturn = FALSE;
|
|
int nRead;
|
|
|
|
fp = fopen ( szBuildFileName, "r" );
|
|
if ( !fp )
|
|
{
|
|
printf ( "Cannot open %s\n", szBuildFileName );
|
|
goto cleanup;
|
|
}
|
|
if ( !GetALine ( fp, szLineBuffer, sizeof ( szLineBuffer ), nRead ) )
|
|
{
|
|
printf ( "Cannot read %s\n", szBuildFileName );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Old input file used to support "-<flags>" - which was never used
|
|
// so I just skip them
|
|
if (sscanf ( szLineBuffer, "- %s %s %s",
|
|
(LPCSTR)szOutputFileRoot,
|
|
(LPCSTR)szInputFile,
|
|
(LPCSTR)szOutputPath ) != 3)
|
|
{
|
|
printf ( "Cannot read params from %s\n", szBuildFileName );
|
|
goto cleanup;
|
|
}
|
|
|
|
while ( GetALine ( fp, szLineBuffer, sizeof ( szLineBuffer ), nRead ) )
|
|
printf ( "Build file Line:%s\n",szLineBuffer );
|
|
|
|
strcpy ( szPDLFileName, szInputFile );
|
|
|
|
fReturn = TRUE;
|
|
goto cleanup;
|
|
|
|
cleanup:
|
|
if ( fp )
|
|
fclose ( fp );
|
|
return fReturn;
|
|
}
|
|
|
|
CTokenList::~CTokenList()
|
|
{
|
|
Token *pNextToken;
|
|
Token *pToken;
|
|
// Tidy up the list
|
|
for ( pToken = _pFirstToken ; pToken != NULL ; pToken = pNextToken )
|
|
{
|
|
pNextToken = pToken -> _pNextToken;
|
|
delete pToken;
|
|
}
|
|
}
|
|
|
|
|
|
Token *CTokenListWalker::GetNext ( void )
|
|
{
|
|
Token *pToken;
|
|
while ( pToken = GetNextToken() )
|
|
{
|
|
if ( _pszFileName )
|
|
{
|
|
if ( _pCurrentToken->nType == TYPE_FILE )
|
|
{
|
|
if ( _fInCurrentFile && _pszFileName )
|
|
{
|
|
_fInCurrentFile = FALSE;
|
|
}
|
|
else
|
|
{
|
|
_fInCurrentFile = pToken->CompareTag ( FILE_TAG, _pszFileName );
|
|
}
|
|
}
|
|
else if ( _fInCurrentFile )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return pToken;
|
|
}
|
|
|
|
Token *CTokenListWalker::GetNext ( DESCRIPTOR_TYPE Type, LPCSTR pName )
|
|
{
|
|
Token *pToken;
|
|
while ( pToken = GetNext() )
|
|
{
|
|
if ( pToken -> nType == Type &&
|
|
( pName == NULL || _stricmp ( pName, pToken -> GetTagValue ( NAME_TAG ) ) == 0 ) )
|
|
{
|
|
return pToken;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
Token *Token::AddChildToken ( DESCRIPTOR_TYPE nType )
|
|
{
|
|
Token *pNewToken;
|
|
|
|
if ( _pChildList == NULL )
|
|
{
|
|
if ( ( _pChildList = new CTokenList() ) == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Created the new arg token
|
|
if ( ! ( pNewToken = _pChildList->AddNewToken ( nType ) ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
return pNewToken;
|
|
}
|
|
|
|
void Token::CalculateEnumMask ( Token *pParentToken )
|
|
{
|
|
INT nValue;
|
|
if ( IsSet ( EVAL_VALUE ) )
|
|
{
|
|
nValue = atoi ( GetTagValue ( EVAL_VALUE ) );
|
|
}
|
|
else
|
|
{
|
|
char szText [ MAX_LINE_LEN+1 ];
|
|
nValue = pParentToken -> nNextEnumValue;
|
|
// Plug the new value into the tag
|
|
sprintf ( szText, "%d", nValue );
|
|
AddTag ( EVAL_VALUE, szText );
|
|
|
|
}
|
|
if ( nValue >=0 && nValue < 32 )
|
|
{
|
|
pParentToken -> uEnumMask |= (1 << (UINT)nValue);
|
|
}
|
|
pParentToken -> nNextEnumValue = ++nValue;
|
|
}
|
|
|
|
UINT Token::GetChildTokenCount ( void )
|
|
{
|
|
return _pChildList ? _pChildList -> GetTokenCount() : 0;
|
|
}
|
|
|
|
// Helper for building comma sperarated arg lists
|
|
// if the arg is set add the corresponding text to
|
|
// the arg string
|
|
void Token::AddParam ( CString &szArg, INT nTag, LPCSTR szText )
|
|
{
|
|
if ( IsSet ( nTag ) )
|
|
{
|
|
if ( szArg [ 0 ] != '\0' )
|
|
szArg += ", ";
|
|
|
|
szArg += szText;
|
|
}
|
|
}
|
|
|
|
// Helper for building comma sperarated arg lists
|
|
// if the arg is set add the corresponding text to
|
|
// the arg string. With the current arg value replacing the %s
|
|
// szArg must contain one and only one %s
|
|
void Token::AddParamStr ( CString &szArg, INT nTag, LPCSTR szText )
|
|
{
|
|
char szTemp [ MAX_LINE_LEN+1 ];
|
|
if ( IsSet ( nTag ) )
|
|
{
|
|
sprintf ( szTemp, (LPCSTR)szText, (LPCSTR)GetTagValue ( nTag ) );
|
|
if ( szArg [ 0 ] != '\0' )
|
|
szArg += ", ";
|
|
szArg += szTemp;
|
|
}
|
|
}
|
|
|
|
void Token::Clone ( Token *pFrom )
|
|
{
|
|
UINT i;
|
|
INT nLen;
|
|
|
|
for ( i = 0 ; i < MAX_TAGS ; i++ )
|
|
{
|
|
nLen = pFrom -> TagValues.GetInternalValue ( i ) ? strlen ( pFrom -> TagValues.GetInternalValue ( i ) ) : 0;
|
|
TagValues.AddTag ( i, pFrom -> TagValues.GetInternalValue ( i ), nLen );
|
|
}
|
|
nType = pFrom -> nType;
|
|
|
|
// Now clone the child arg list if there is one
|
|
// Implemented an Addref/Release to simplify the process
|
|
if ( _pChildList )
|
|
{
|
|
_pChildList -> Release();
|
|
_pChildList = NULL;
|
|
}
|
|
if ( pFrom -> _pChildList )
|
|
{
|
|
// Point ourselves at the child list & AddRef it
|
|
_pChildList = pFrom -> _pChildList;
|
|
_pChildList -> AddRef();
|
|
}
|
|
}
|
|
|
|
|
|
struct METH_PARAMS {
|
|
BOOL fOptional;
|
|
BOOL fDefaultValue;
|
|
CString szVTParamType;
|
|
CString szCParamType;
|
|
VARTYPE vtParam;
|
|
};
|
|
|
|
#define ATYPE_Undefined 0
|
|
#define ATYPE_Method 1
|
|
#define ATYPE_GetProperty 2
|
|
#define ATYPE_SetProperty 4
|
|
#define ATYPE_ReturnValue 8
|
|
#define ATYPE_ParametersOnly 16
|
|
|
|
struct DispatchHandler {
|
|
CString szRawString;
|
|
WORD invokeType;
|
|
CString szDispName;
|
|
CString szVTResult;
|
|
CString szCResult;
|
|
VARTYPE vtResult;
|
|
METH_PARAMS params[8];
|
|
};
|
|
|
|
|
|
#define MAX_HANDLERS 130
|
|
#define MAX_IIDS 330
|
|
|
|
int _cHandlers;
|
|
DispatchHandler _allHandlers[MAX_HANDLERS];
|
|
int _cIID;
|
|
LPSTR _allIIDs[MAX_IIDS];
|
|
|
|
#ifdef COMPLUS_SHIM
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Beginning of COM+ code //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
enum CODETYPE {CT_managed, CT_unmanaged, CT_managedNDirect};
|
|
|
|
typedef void (__stdcall * NDBodyFunc)(FILE *, DispatchHandler *, CODETYPE, int);
|
|
|
|
#define PARAM_NAME_PREFIX "param"
|
|
#define PARAM_RESULT_PREFIX "resultParam"
|
|
|
|
|
|
// When we have a setter or getter only we look to see if there were any properties with the same type that supported
|
|
// getting/setting if so use that entry.
|
|
BOOL AnyGSHandler(DispatchHandler & handler)
|
|
{
|
|
if (handler.invokeType & (ATYPE_GetProperty | ATYPE_SetProperty))
|
|
{
|
|
for (int i = 0; i < _cHandlers; i++)
|
|
{
|
|
if ((_allHandlers[i].invokeType & (ATYPE_GetProperty | ATYPE_SetProperty)) == (ATYPE_GetProperty | ATYPE_SetProperty))
|
|
{
|
|
if (_allHandlers[i].vtResult == handler.vtResult)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
LPCSTR ResultType(DispatchHandler *pHandler, CODETYPE codeType, BOOL *pfAllocate)
|
|
{
|
|
BOOL tempBool;
|
|
|
|
if (!pfAllocate)
|
|
{
|
|
pfAllocate = &tempBool;
|
|
}
|
|
*pfAllocate = FALSE;
|
|
|
|
VARTYPE vtResult = pHandler->vtResult & VT_TYPEMASK;
|
|
|
|
if (codeType == CT_managedNDirect)
|
|
{
|
|
if (vtResult == VT_BSTR)
|
|
{
|
|
return "wchar_t*";
|
|
}
|
|
else if (vtResult == VT_DISPATCH || vtResult == VT_UNKNOWN)
|
|
{
|
|
return "unsigned int";
|
|
}
|
|
else if (vtResult == VT_VARIANT)
|
|
{
|
|
return "unsigned int";
|
|
}
|
|
else if (vtResult == VT_BOOL)
|
|
{
|
|
return "short";
|
|
}
|
|
else if (vtResult == VT_I4)
|
|
{
|
|
return "long";
|
|
}
|
|
else if (vtResult == VT_I2)
|
|
{
|
|
return "short";
|
|
}
|
|
else if (pHandler->vtResult == VT_ARRAY)
|
|
{
|
|
return "wchar_t*"; // ***TLL*** COM+: Need something different here for now it's a string.
|
|
}
|
|
else
|
|
{
|
|
return (LPCSTR)pHandler->szCResult;
|
|
}
|
|
}
|
|
else if (codeType == CT_managed)
|
|
{
|
|
if (vtResult != VT_EMPTY)
|
|
{
|
|
if (vtResult == VT_BSTR)
|
|
{
|
|
return "String";
|
|
}
|
|
else if (vtResult == VT_DISPATCH || vtResult == VT_UNKNOWN)
|
|
{
|
|
return "unsigned int";
|
|
}
|
|
else if (vtResult == VT_VARIANT)
|
|
{
|
|
return "Variant";
|
|
}
|
|
else if (vtResult == VT_BOOL)
|
|
{
|
|
return "Boolean";
|
|
}
|
|
else if (vtResult == VT_I4)
|
|
{
|
|
return "long";
|
|
}
|
|
else if (vtResult == VT_I2)
|
|
{
|
|
return "short";
|
|
}
|
|
else if (pHandler->vtResult == VT_ARRAY)
|
|
{
|
|
return "String"; // ***TLL*** COM+: Need something different here for now it's a string.
|
|
}
|
|
else
|
|
{
|
|
LPCSTR pFoundSpace = strchr((LPCSTR)pHandler->szCResult, ' ');
|
|
LPSTR pString;
|
|
|
|
if (pFoundSpace)
|
|
{
|
|
UINT cLen = pFoundSpace - (LPCSTR)pHandler->szCResult;
|
|
pString = new char[cLen + 1];
|
|
if (pString)
|
|
{
|
|
*pfAllocate = TRUE;
|
|
strncpy(pString, (LPCSTR)pHandler->szCResult, cLen);
|
|
pString[cLen] = '\0';
|
|
return pString;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (LPCSTR)pHandler->szCResult;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "void";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (LPCSTR)pHandler->szCResult;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
OutputParameters(FILE *fpOut, DispatchHandler *pHandler, CODETYPE codeType, int invokeType)
|
|
{
|
|
BOOL fAllocate = FALSE;
|
|
LPCSTR mappedParamType = ResultType(pHandler, codeType, &fAllocate);
|
|
|
|
if (invokeType & ATYPE_GetProperty)
|
|
{
|
|
if (codeType != CT_managed)
|
|
{
|
|
fprintf(fpOut, ", %s* " PARAM_RESULT_PREFIX ")", mappedParamType);
|
|
}
|
|
else
|
|
{
|
|
fprintf(fpOut, ")");
|
|
}
|
|
}
|
|
else if (invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf(fpOut, ", %s " PARAM_NAME_PREFIX "1)", mappedParamType);
|
|
}
|
|
else if (invokeType & ATYPE_ReturnValue)
|
|
{
|
|
fprintf(fpOut, "%s ", mappedParamType);
|
|
}
|
|
else
|
|
{
|
|
int j = 0;
|
|
int cArgs = 0;
|
|
|
|
if (fAllocate)
|
|
{
|
|
delete [] (LPSTR)mappedParamType;
|
|
fAllocate = FALSE;
|
|
}
|
|
|
|
while (pHandler->params[j].szVTParamType.Length())
|
|
{
|
|
VARTYPE vtParam = pHandler->params[j].vtParam & VT_TYPEMASK;
|
|
|
|
if (codeType == CT_managedNDirect)
|
|
{
|
|
if (vtParam == VT_BSTR)
|
|
{
|
|
mappedParamType = "wchar_t*";
|
|
}
|
|
else if (vtParam == VT_DISPATCH || vtParam == VT_UNKNOWN)
|
|
{
|
|
mappedParamType = "unsigned int";
|
|
}
|
|
else if (vtParam == VT_VARIANT)
|
|
{
|
|
mappedParamType = "unsigned int";
|
|
}
|
|
else if (vtParam == VT_BOOL)
|
|
{
|
|
mappedParamType = "short";
|
|
}
|
|
else if (vtParam == VT_I4)
|
|
{
|
|
mappedParamType = "long";
|
|
}
|
|
else if (vtParam == VT_I2)
|
|
{
|
|
mappedParamType = "short";
|
|
}
|
|
else if (pHandler->params[j].vtParam == VT_ARRAY)
|
|
{
|
|
mappedParamType = "wchar_t*"; // ***TLL*** COM+: Need something different here for now it's a string.
|
|
}
|
|
else
|
|
{
|
|
mappedParamType = (LPCSTR)pHandler->params[j].szCParamType;
|
|
}
|
|
}
|
|
else if (codeType == CT_managed)
|
|
{
|
|
if (vtParam == VT_BSTR)
|
|
{
|
|
mappedParamType = "String";
|
|
}
|
|
else if (vtParam == VT_DISPATCH || vtParam == VT_UNKNOWN)
|
|
{
|
|
mappedParamType = "unsigned int";
|
|
}
|
|
else if (vtParam == VT_VARIANT)
|
|
{
|
|
mappedParamType = "Variant";
|
|
}
|
|
else if (vtParam == VT_BOOL)
|
|
{
|
|
mappedParamType = "Boolean";
|
|
}
|
|
else if (vtParam == VT_I4)
|
|
{
|
|
mappedParamType = "long";
|
|
}
|
|
else if (vtParam == VT_I2)
|
|
{
|
|
mappedParamType = "short";
|
|
}
|
|
else if (pHandler->params[j].vtParam == VT_ARRAY)
|
|
{
|
|
mappedParamType = "String"; // ***TLL*** COM+: Need something different here for now it's a string.
|
|
}
|
|
else
|
|
{
|
|
mappedParamType = (LPCSTR)pHandler->params[j].szCParamType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mappedParamType = (LPCSTR)pHandler->params[j].szCParamType;
|
|
}
|
|
|
|
fprintf (fpOut, ", %s " PARAM_NAME_PREFIX "%i", mappedParamType, j + 1);
|
|
j++;
|
|
cArgs++;
|
|
}
|
|
|
|
if (!(invokeType & ATYPE_ParametersOnly))
|
|
{
|
|
if (pHandler->vtResult != VT_EMPTY)
|
|
{
|
|
mappedParamType = ResultType(pHandler, codeType, &fAllocate);
|
|
fprintf(fpOut, ", %s " PARAM_RESULT_PREFIX, mappedParamType);
|
|
}
|
|
}
|
|
|
|
fprintf(fpOut, ")");
|
|
}
|
|
|
|
if (fAllocate)
|
|
{
|
|
delete [] (LPSTR)mappedParamType;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
OutputNDSignature(FILE *fpOut, DispatchHandler *pHandler, LPCSTR pPreHeader, CODETYPE codeType, NDBodyFunc pNDBodyFunc)
|
|
{
|
|
BOOL fSetDone = FALSE;
|
|
int invokeType = pHandler->invokeType;
|
|
BOOL fGetAndSet = ((invokeType & ATYPE_GetProperty) && (invokeType & ATYPE_SetProperty));
|
|
CString funcName;
|
|
|
|
if (!fGetAndSet)
|
|
{
|
|
if (AnyGSHandler(*pHandler))
|
|
return;
|
|
|
|
if (codeType == CT_managedNDirect || codeType == CT_unmanaged)
|
|
{
|
|
fprintf(fpOut, "%s NDCP_%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset", pPreHeader, (LPCSTR)(pHandler->szRawString));
|
|
}
|
|
else if (codeType == CT_managed)
|
|
{
|
|
if (!pNDBodyFunc)
|
|
fprintf(fpOut, "\tstatic ");
|
|
OutputParameters(fpOut, pHandler, codeType, ATYPE_ReturnValue);
|
|
|
|
if (pNDBodyFunc)
|
|
fprintf(fpOut, "\nCPThunks::");
|
|
|
|
if (pHandler->szRawString[0] == 'G' || pHandler->szRawString[0] == 'S')
|
|
{
|
|
funcName = pHandler->szRawString[0] == 'G' ? "G_" : "S_";
|
|
|
|
if (strcmp((LPCSTR)(pHandler->szRawString) + 2, "BSTR") == 0)
|
|
{
|
|
funcName += "String";
|
|
}
|
|
else if (strcmp((LPCSTR)(pHandler->szRawString) + 2, "VARIANT") == 0)
|
|
{
|
|
funcName += "Variant";
|
|
}
|
|
else if (strcmp((LPCSTR)(pHandler->szRawString) + 2, "VARIANTBOOL") == 0)
|
|
{
|
|
funcName += "Boolean";
|
|
}
|
|
else if (strcmp((LPCSTR)(pHandler->szRawString) + 2, "IDispatchp") == 0 ||
|
|
strcmp((LPCSTR)(pHandler->szRawString) + 2, "IUnknownp") == 0)
|
|
{
|
|
funcName += "Object";
|
|
}
|
|
else
|
|
{
|
|
funcName = (LPCSTR)(pHandler->szRawString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
funcName = (LPCSTR)(pHandler->szRawString);
|
|
}
|
|
|
|
fprintf(fpOut, "COMPLUS_%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset", (LPCSTR)funcName);
|
|
|
|
invokeType |= (~ATYPE_ReturnValue & ATYPE_ParametersOnly);
|
|
}
|
|
|
|
OutputParameters(fpOut, pHandler, codeType, invokeType);
|
|
|
|
if (pNDBodyFunc)
|
|
{
|
|
fprintf(fpOut, "\n");
|
|
|
|
(*pNDBodyFunc)(fpOut, pHandler, codeType, invokeType);
|
|
|
|
fprintf(fpOut, "\n\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(fpOut, ";\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (codeType == CT_managed)
|
|
{
|
|
if (strcmp((LPCSTR)(pHandler->szRawString) + 3, "BSTR") == 0)
|
|
{
|
|
funcName = "_String";
|
|
}
|
|
else if (strcmp((LPCSTR)(pHandler->szRawString) + 3, "VARIANT") == 0)
|
|
{
|
|
funcName = "_Variant";
|
|
}
|
|
else if (strcmp((LPCSTR)(pHandler->szRawString) + 3, "VARIANTBOOL") == 0)
|
|
{
|
|
funcName = "_Boolean";
|
|
}
|
|
else
|
|
{
|
|
funcName = (LPCSTR)((pHandler->szRawString)) + 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
funcName = pHandler->szRawString;
|
|
}
|
|
|
|
SpitOutAgain:
|
|
if (!fSetDone && (pHandler->invokeType & ATYPE_GetProperty))
|
|
{
|
|
if (codeType == CT_managedNDirect || codeType == CT_unmanaged)
|
|
{
|
|
fprintf(fpOut, "%s NDCP_G%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset", pPreHeader, (LPCSTR)((pHandler->szRawString)) + 2);
|
|
OutputParameters(fpOut, pHandler, codeType, ATYPE_GetProperty);
|
|
}
|
|
else if (codeType == CT_managed)
|
|
{
|
|
if (!pNDBodyFunc)
|
|
fprintf(fpOut, "\tstatic ");
|
|
|
|
OutputParameters(fpOut, pHandler, codeType, ATYPE_ReturnValue);
|
|
|
|
if (pNDBodyFunc)
|
|
fprintf(fpOut, "\nCPThunks::");
|
|
|
|
fprintf(fpOut, "COMPLUS_G%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset)", (LPCSTR)funcName);
|
|
}
|
|
|
|
fSetDone = TRUE;
|
|
|
|
if (pNDBodyFunc)
|
|
{
|
|
fprintf(fpOut, "\n");
|
|
|
|
(*pNDBodyFunc)(fpOut, pHandler, codeType, ATYPE_GetProperty);
|
|
|
|
fprintf(fpOut, "\n\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(fpOut, ";\n");
|
|
}
|
|
|
|
goto SpitOutAgain;
|
|
}
|
|
else if (pHandler->invokeType & ATYPE_SetProperty)
|
|
{
|
|
if (codeType == CT_managedNDirect || codeType == CT_unmanaged)
|
|
{
|
|
fprintf(fpOut, "%s NDCP_S%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset", pPreHeader, (LPCSTR)((pHandler->szRawString)) + 2);
|
|
}
|
|
else if (codeType == CT_managed)
|
|
{
|
|
if (!pNDBodyFunc)
|
|
{
|
|
fprintf(fpOut, "\tstatic void ");
|
|
}
|
|
else
|
|
{
|
|
fprintf(fpOut, "void\nCPThunks::");
|
|
}
|
|
|
|
fprintf(fpOut, "COMPLUS_S%s (unsigned int myThis, unsigned int idxIID, unsigned int wVTblOffset", (LPCSTR)funcName);
|
|
}
|
|
|
|
OutputParameters(fpOut, pHandler, codeType, ATYPE_SetProperty);
|
|
|
|
if (pNDBodyFunc)
|
|
{
|
|
fprintf(fpOut, "\n");
|
|
|
|
(*pNDBodyFunc)(fpOut, pHandler, codeType, ATYPE_SetProperty);
|
|
|
|
fprintf(fpOut, "\n\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(fpOut, ";\n");
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL GenerateNDirectHeader (LPCSTR pszOutputPath)
|
|
{
|
|
char chNDDefFileName[255];
|
|
FILE *fpNDDefFile;
|
|
|
|
strcpy(chNDDefFileName, pszOutputPath);
|
|
strcat(chNDDefFileName, FILENAME_SEPARATOR_STR "ComPlsND.def");
|
|
|
|
fpNDDefFile = fopen(chNDDefFileName, "w");
|
|
if (!fpNDDefFile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
fprintf(fpNDDefFile, "// Trident Def file NDirect functions.\n\n\n");
|
|
|
|
// Spit out function signatures for NDirect functions.
|
|
for (int i = 0; i < _cHandlers; i++)
|
|
{
|
|
BOOL fSetDone = FALSE;
|
|
BOOL fGetAndSet = ((_allHandlers[i].invokeType & ATYPE_GetProperty) && (_allHandlers[i].invokeType & ATYPE_SetProperty));
|
|
|
|
if (!fGetAndSet)
|
|
{
|
|
if (!AnyGSHandler(_allHandlers[i]))
|
|
{
|
|
fprintf(fpNDDefFile, "NDCP_%s\t\tPRIVATE\n", (LPCSTR)(_allHandlers[i].szRawString));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SpitOutAgain:
|
|
if (!fSetDone && (_allHandlers[i].invokeType & ATYPE_GetProperty))
|
|
{
|
|
fprintf(fpNDDefFile, "NDCP_G%s\t\tPRIVATE\n", (LPCSTR)((_allHandlers[i].szRawString)) + 2);
|
|
fSetDone = TRUE;
|
|
goto SpitOutAgain;
|
|
}
|
|
else if (_allHandlers[i].invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf(fpNDDefFile, "NDCP_S%s\t\tPRIVATE\n", (LPCSTR)((_allHandlers[i].szRawString)) + 2);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fpNDDefFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void GenerateNDBody(FILE *fpOut, DispatchHandler *pHandler, CODETYPE codeType, int invokeType)
|
|
{
|
|
fprintf(fpOut, "{\n");
|
|
|
|
fprintf(fpOut, "\ttypedef HRESULT (STDMETHODCALLTYPE *OLEVTblPropFunc)(IDispatch *");
|
|
OutputParameters(fpOut, pHandler, codeType, invokeType);
|
|
fprintf(fpOut, ";\n\n");
|
|
|
|
fprintf(fpOut, "\tHRESULT\t\t\thr;\n\tIUnknown\t\t*pUnknownInstance;\n\tIDispatch\t\t*pInstance = 0;\n\tVTABLE_ENTRY\t*pVTbl;\n\n");
|
|
|
|
fprintf(fpOut, "\tAssert(myThis);\n\n");
|
|
|
|
fprintf(fpOut, "\tpUnknownInstance = (IUnknown *)myThis;\n\n");
|
|
|
|
fprintf(fpOut, "\tAssert(idxIID <= MAX_IIDS);\n");
|
|
fprintf(fpOut, "\thr = pUnknownInstance->QueryInterface(*_IIDTable[idxIID], (void **)&pInstance);\n");
|
|
fprintf(fpOut, "\tif (hr)\n");
|
|
fprintf(fpOut, "\t\tgoto Cleanup;\n\n");
|
|
fprintf(fpOut, "\tpVTbl = (VTABLE_ENTRY *)(((BYTE *)(*(DWORD_PTR *)pInstance)) + (wVTblOffset*sizeof(VTABLE_ENTRY)/sizeof(DWORD_PTR) + FIRST_VTABLE_OFFSET));\n");
|
|
|
|
fprintf(fpOut, "\thr = (*(OLEVTblPropFunc)VTBL_PFN(pVTbl))((IDispatch*) VTBL_THIS(pVTbl,pInstance)");
|
|
if (invokeType & ATYPE_GetProperty)
|
|
{
|
|
fprintf(fpOut, ", resultParam");
|
|
}
|
|
else if (invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf(fpOut, ", param1");
|
|
}
|
|
else
|
|
{
|
|
int i = 0;
|
|
|
|
while (pHandler->params[i++].szVTParamType.Length())
|
|
{
|
|
fprintf (fpOut, ", param%i", i);
|
|
}
|
|
|
|
if (pHandler->vtResult != VT_EMPTY)
|
|
{
|
|
fprintf(fpOut, ", resultParam");
|
|
}
|
|
}
|
|
|
|
fprintf(fpOut, ");\n\n");
|
|
|
|
fprintf(fpOut, "\tpInstance->Release();\n\n");
|
|
|
|
fprintf(fpOut, "Cleanup:\n\treturn hr;\n");
|
|
|
|
fprintf(fpOut, "}\n");
|
|
}
|
|
|
|
|
|
BOOL GenerateNDirectCXX (LPCSTR pszOutputPath)
|
|
{
|
|
char chNDCXXFileName[255];
|
|
FILE *fpNDCXXFile;
|
|
|
|
strcpy(chNDCXXFileName, pszOutputPath);
|
|
strcat(chNDCXXFileName, FILENAME_SEPARATOR_STR "funcND.cpp");
|
|
|
|
fpNDCXXFile = fopen(chNDCXXFileName, "w");
|
|
if (!fpNDCXXFile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
fprintf(fpNDCXXFile, "// Trident NDirect functions source file.\n\n\n");
|
|
|
|
// Spit out function signatures for NDirect functions.
|
|
for (int i = 0; i < _cHandlers; i++)
|
|
{
|
|
OutputNDSignature(fpNDCXXFile, &(_allHandlers[i]), "STDAPI ", CT_unmanaged, GenerateNDBody);
|
|
}
|
|
|
|
fclose(fpNDCXXFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void GenerateManagedThunkBody(FILE *fpOut, DispatchHandler *pHandler, CODETYPE codeType, int invokeType)
|
|
{
|
|
CString szAfterBlock;
|
|
CString szResult;
|
|
|
|
fprintf(fpOut, "{\n");
|
|
|
|
fprintf(fpOut, "\tif (myThis)\n");
|
|
fprintf(fpOut, "\t{\n");
|
|
fprintf(fpOut, "\t\tHRESULT\thr;\n");
|
|
|
|
// Spit out the getter body.
|
|
if (invokeType & ATYPE_GetProperty)
|
|
{
|
|
if ((pHandler->vtResult & VT_TYPEMASK) == VT_BSTR)
|
|
{
|
|
fprintf(fpOut, "\t\twchar_t\t*bstrString = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_BSTR(myThis, idxIID, wVTblOffset, &bstrString);\n\n");
|
|
fprintf(fpOut, "\t\tString pString = CustomInvoke::BSTRToString(bstrString, 1);\n\n");
|
|
fprintf(fpOut, "\t\treturn pString;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_DISPATCH)
|
|
{
|
|
fprintf(fpOut, "\t\tunsigned int\tmyPDispatch = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_IDispatchp(myThis, idxIID, wVTblOffset, &myPDispatch);\n\n");
|
|
fprintf(fpOut, "\t\treturn myPDispatch;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_UNKNOWN)
|
|
{
|
|
fprintf(fpOut, "\t\tunsigned int\tmyPUnknown = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_IUnknownp(myThis, idxIID, wVTblOffset, &myPUnknown);\n\n");
|
|
fprintf(fpOut, "\t\treturn myPUnknown;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_BOOL)
|
|
{
|
|
fprintf(fpOut, "\t\tshort\tmyCOMBool = 0;\n");
|
|
fprintf(fpOut, "\t\tBoolean\tmyCPBool = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_VARIANTBOOL(myThis, idxIID, wVTblOffset, &myCOMBool);\n\n");
|
|
fprintf(fpOut, "\t\treturn myCPBool;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_VARIANT)
|
|
{
|
|
//
|
|
// COM+ Need to fix dispatch getter to return this as unsigned int and have the actual COM+ function create the
|
|
// COM+ Variant.
|
|
//
|
|
fprintf(fpOut, "\t\tunsigned int myPDispatch;\n");
|
|
fprintf(fpOut, "\t\tVariant myVariant;\n");
|
|
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_VARIANT(myThis, idxIID, wVTblOffset, &myPDispatch);\n\n");
|
|
fprintf(fpOut, "\t\treturn myVariant;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
else
|
|
{
|
|
if (pHandler->szCResult == "LONG")
|
|
{
|
|
szResult = "long";
|
|
}
|
|
else if (pHandler->szCResult == "SHORT")
|
|
{
|
|
szResult = "short";
|
|
}
|
|
else
|
|
{
|
|
szResult = pHandler->szCResult;
|
|
}
|
|
|
|
fprintf(fpOut, "\t\t%s\treturnValue = 0;\n\n", (LPCSTR)szResult);
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_G_%s(myThis, idxIID, wVTblOffset, &returnValue);\n\n", (LPCSTR)szResult);
|
|
fprintf(fpOut, "\t\treturn returnValue;\n");
|
|
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
}
|
|
|
|
// Spit out the setter body.
|
|
if (invokeType & ATYPE_SetProperty)
|
|
{
|
|
if ((pHandler->vtResult & VT_TYPEMASK) == VT_BSTR)
|
|
{
|
|
fprintf(fpOut, "\t\twchar_t\t*bstrString = 0;\n\n");
|
|
fprintf(fpOut, "\t\tbstrString = CustomInvoke::StringToBSTR(param1);\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_BSTR(myThis, idxIID, wVTblOffset, bstrString);\n\n");
|
|
fprintf(fpOut, "\t\tCustomInvoke::SysFreeString(bstrString);\n");
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_DISPATCH)
|
|
{
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_IDispatchp(myThis, idxIID, wVTblOffset, param1);\n\n");
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_UNKNOWN)
|
|
{
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_IUnknownpp(myThis, idxIID, wVTblOffset, param1);\n\n");
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_VARIANT)
|
|
{
|
|
fprintf(fpOut, "\t\tunsigned myCOMVariant = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_VARIANT(myThis, idxIID, wVTblOffset, myCOMVariant);\n\n");
|
|
}
|
|
else if ((pHandler->vtResult & VT_TYPEMASK) == VT_BOOL)
|
|
{
|
|
fprintf(fpOut, "\t\tshort myCOMBool = 0;\n\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_VARIANTBOOL(myThis, idxIID, wVTblOffset, myCOMBool);\n\n");
|
|
}
|
|
else
|
|
{
|
|
if (pHandler->szCResult == "LONG")
|
|
{
|
|
szResult = "long";
|
|
}
|
|
else if (pHandler->szCResult == "SHORT")
|
|
{
|
|
szResult = "short";
|
|
}
|
|
else
|
|
{
|
|
szResult = pHandler->szCResult;
|
|
}
|
|
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_S_%s(myThis, idxIID, wVTblOffset, param1);\n\n", (LPCSTR)szResult);
|
|
}
|
|
}
|
|
|
|
// Spit out the method body.
|
|
if (invokeType & ATYPE_Method)
|
|
{
|
|
// ***TLL*** COM+: Just look for one parameter BSTR
|
|
if (pHandler->params[0].szVTParamType.Length() && !pHandler->params[1].szVTParamType.Length())
|
|
{
|
|
if (pHandler->params[0].vtParam == VT_BSTR)
|
|
{
|
|
fprintf(fpOut, "\t\twchar_t *bstrString = 0;\n\n");
|
|
|
|
fprintf(fpOut, "\t\tbstrString = CustomInvoke::StringToBSTR(param1);\n");
|
|
fprintf(fpOut, "\t\thr = CustomInvoke::NDCP_Method_void_BSTR(myThis, idxIID, wVTblOffset, bstrString);\n\n");
|
|
|
|
fprintf(fpOut, "\t\tCustomInvoke::SysFreeString(bstrString);\n");
|
|
}
|
|
}
|
|
|
|
// ***TLL*** COM+: Need to do.
|
|
// If no void result then return 0 for now.
|
|
if ((pHandler->vtResult & VT_TYPEMASK) != VT_EMPTY)
|
|
szAfterBlock = "\treturn 0;\n";
|
|
}
|
|
|
|
fprintf(fpOut, "\t}\n");
|
|
|
|
fprintf(fpOut, (LPCSTR)szAfterBlock);
|
|
|
|
fprintf(fpOut, "}\n");
|
|
}
|
|
|
|
|
|
BOOL GenerateComPlusHeader (LPCSTR pszOutputPath)
|
|
{
|
|
char chCPHeaderFileName[255];
|
|
FILE *fpCPHeaderFile;
|
|
int i;
|
|
|
|
strcpy(chCPHeaderFileName, pszOutputPath);
|
|
strcat(chCPHeaderFileName, FILENAME_SEPARATOR_STR "TComPlus.hxx");
|
|
|
|
fpCPHeaderFile = fopen(chCPHeaderFileName, "w");
|
|
if (!fpCPHeaderFile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
fprintf(fpCPHeaderFile, "// Trident COM+ Header file.\n\n\n");
|
|
|
|
fprintf(fpCPHeaderFile, "[managed,coclass] class CustomInvoke {\n");
|
|
fprintf(fpCPHeaderFile, "public:\n");
|
|
fprintf(fpCPHeaderFile, "\t// Function signatures:\n");
|
|
|
|
|
|
// Spit out COM+ NDirect signatures
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
OutputNDSignature(fpCPHeaderFile, &(_allHandlers[i]), "\t[sysimport(dll=\"mshtml.dll\")]\n\tstatic HRESULT ", CT_managedNDirect, NULL);
|
|
}
|
|
|
|
fprintf(fpCPHeaderFile, "\n");
|
|
|
|
// Output misc. conversion routines:
|
|
fprintf(fpCPHeaderFile, "\t// Conversion routines:\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic String BSTRToString(wchar_t* myBSTR, int fFreeBSTR);\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic wchar_t* StringToBSTR(String myString);\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic unsigned int VariantToVARIANT(Variant myVariant);\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic void VariantClear(unsigned int myCOMVariant);\n\n");
|
|
fprintf(fpCPHeaderFile, "\t// Misc BSTR routines:\n");
|
|
fprintf(fpCPHeaderFile, "\t[sysimport(dll=\"oleaut32.dll\")]\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic wchar_t* SysAllocStringLen(wchar_t *pch, unsigned int cch);\n\n");
|
|
fprintf(fpCPHeaderFile, "\t[sysimport(dll=\"oleaut32.dll\")]\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic void SysFreeString(wchar_t *myBSTR);\n\n");
|
|
fprintf(fpCPHeaderFile, "\t// Misc VARIANT routines:\n");
|
|
fprintf(fpCPHeaderFile, "\t[sysimport(dll=\"oleaut32.dll\", name=\"SysAllocStringLen\")]\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic unsigned int AllocVariant(wchar_t *pch, unsigned int cch);\n\n");
|
|
fprintf(fpCPHeaderFile, "\t[sysimport(dll=\"oleaut32.dll\")]\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic void VariantInit(unsigned int);\n\n");
|
|
fprintf(fpCPHeaderFile, "\t[sysimport(dll=\"oleaut32.dll\", name=\"SysFreeString\")]\n");
|
|
fprintf(fpCPHeaderFile, "\tstatic void FreeVariant(wchar_t *myBSTR);\n");
|
|
|
|
fprintf(fpCPHeaderFile, "};\n\n");
|
|
|
|
fprintf(fpCPHeaderFile, "[managed,coclass] class CPThunks {\n");
|
|
fprintf(fpCPHeaderFile, "public:\n");
|
|
fprintf(fpCPHeaderFile, "\t// Function signatures:\n");
|
|
|
|
// Spit out COM+ thunks for each signature type
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
OutputNDSignature(fpCPHeaderFile, &(_allHandlers[i]), "", CT_managed, NULL);
|
|
}
|
|
|
|
fprintf(fpCPHeaderFile, "};\n\n");
|
|
|
|
fclose(fpCPHeaderFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL GenerateComPlusCXX (LPCSTR pszOutputPath)
|
|
{
|
|
char chCPCXXFileName[255];
|
|
FILE *fpCPCXXFile;
|
|
|
|
strcpy(chCPCXXFileName, pszOutputPath);
|
|
strcat(chCPCXXFileName, FILENAME_SEPARATOR_STR "TComPlus.cpp");
|
|
|
|
fpCPCXXFile = fopen(chCPCXXFileName, "w");
|
|
if (!fpCPCXXFile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
fprintf(fpCPCXXFile, "// Trident COM+ source file.\n\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "#import <mscorlib.dll>\n");
|
|
fprintf(fpCPCXXFile, "#include <crt.h>\n");
|
|
fprintf(fpCPCXXFile, "#include \"TComPlus.hxx\"\n\n\n");
|
|
|
|
// Spit out COM+ thunks for each signature type
|
|
for (int i = 0; i < _cHandlers; i++)
|
|
{
|
|
OutputNDSignature(fpCPCXXFile, &(_allHandlers[i]), "", CT_managed, GenerateManagedThunkBody);
|
|
}
|
|
|
|
// Output conversion routines:
|
|
fprintf(fpCPCXXFile, "\n\n");
|
|
fprintf(fpCPCXXFile, "//////////////////////////////////////////////////////////////////////////\n");
|
|
fprintf(fpCPCXXFile, "//////////////////////////////////////////////////////////////////////////\n");
|
|
fprintf(fpCPCXXFile, "// //\n");
|
|
fprintf(fpCPCXXFile, "// //\n");
|
|
fprintf(fpCPCXXFile, "// Conversion routines: //\n");
|
|
fprintf(fpCPCXXFile, "// //\n");
|
|
fprintf(fpCPCXXFile, "// //\n");
|
|
fprintf(fpCPCXXFile, "//////////////////////////////////////////////////////////////////////////\n");
|
|
fprintf(fpCPCXXFile, "//////////////////////////////////////////////////////////////////////////\n\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "String\n");
|
|
fprintf(fpCPCXXFile, "CustomInvoke::BSTRToString(wchar_t *myBSTR, int fFreeBSTR)\n");
|
|
fprintf(fpCPCXXFile, "{\n");
|
|
fprintf(fpCPCXXFile, "\tString pString(\"\");\n\n");
|
|
fprintf(fpCPCXXFile, "\tif (myBSTR)\n");
|
|
fprintf(fpCPCXXFile, "\t{\n");
|
|
fprintf(fpCPCXXFile, "\t\tpString = Interop.PInvoke.PtrToStringAuto((int)myBSTR);\n");
|
|
fprintf(fpCPCXXFile, "\t\tif (fFreeBSTR)\n");
|
|
fprintf(fpCPCXXFile, "\t\t{\n");
|
|
fprintf(fpCPCXXFile, "\t\t\tSysFreeString(myBSTR);\n");
|
|
fprintf(fpCPCXXFile, "\t\t}\n");
|
|
fprintf(fpCPCXXFile, "\t}\n\n");
|
|
fprintf(fpCPCXXFile, "\treturn pString;\n");
|
|
fprintf(fpCPCXXFile, "}\n\n\n");
|
|
|
|
|
|
fprintf(fpCPCXXFile, "wchar_t*\n");
|
|
fprintf(fpCPCXXFile, "CustomInvoke::StringToBSTR(String myString)\n");
|
|
fprintf(fpCPCXXFile, "{\n");
|
|
fprintf(fpCPCXXFile, "\twchar_t *myBSTR = 0;\n");
|
|
fprintf(fpCPCXXFile, "\tint cch;\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "\tcch = myString.GetLength();\n");
|
|
|
|
fprintf(fpCPCXXFile, "\tmyBSTR = CustomInvoke::SysAllocStringLen(0, cch);\n");
|
|
fprintf(fpCPCXXFile, "\tif (myBSTR)\n");
|
|
fprintf(fpCPCXXFile, "\t{\n");
|
|
fprintf(fpCPCXXFile, "\t\tunsigned int i = 0;\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "\t\twhile (cch-- > 0)\n");
|
|
fprintf(fpCPCXXFile, "\t\t{\n");
|
|
fprintf(fpCPCXXFile, "\t\t\t*(myBSTR + i) = myString.GetChar(i);\n");
|
|
fprintf(fpCPCXXFile, "\t\t\ti++;\n");
|
|
fprintf(fpCPCXXFile, "\t\t};\n");
|
|
fprintf(fpCPCXXFile, "\t}\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "\treturn myBSTR;\n");
|
|
fprintf(fpCPCXXFile, "}\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "unsigned int\n");
|
|
fprintf(fpCPCXXFile, "CustomInvoke::VariantToVARIANT(Variant myVariant)\n");
|
|
fprintf(fpCPCXXFile, "{\n");
|
|
fprintf(fpCPCXXFile, "\treturn 0;\n");
|
|
fprintf(fpCPCXXFile, "}\n\n");
|
|
|
|
fprintf(fpCPCXXFile, "void\n");
|
|
fprintf(fpCPCXXFile, "CustomInvoke::VariantClear(unsigned int myCOMVariant)\n");
|
|
fprintf(fpCPCXXFile, "{\n");
|
|
fprintf(fpCPCXXFile, "\n\n");
|
|
fprintf(fpCPCXXFile, "}\n\n");
|
|
|
|
// Close file.
|
|
fclose(fpCPCXXFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
// End of COM+ code //
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#endif // COMPLUS_SHIM
|
|
|
|
|
|
BOOL GenerateVTableHeader ( LPCSTR pszOutputPath )
|
|
{
|
|
char chHeaderFileName[255];
|
|
FILE *fpHeaderFile;
|
|
int i;
|
|
|
|
strcpy(chHeaderFileName, pszOutputPath);
|
|
strcat(chHeaderFileName, FILENAME_SEPARATOR_STR "funcsig.hxx");
|
|
|
|
fpHeaderFile = fopen ( chHeaderFileName, "w" );
|
|
if ( !fpHeaderFile )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
fprintf ( fpHeaderFile, "BOOL DispNonDualDIID(IID iid);\n" );
|
|
|
|
fprintf ( fpHeaderFile, "typedef HRESULT (*CustomHandler)(CBase *pBase,\n" );
|
|
fprintf ( fpHeaderFile, " IServiceProvider *pSrvProvider,\n" );
|
|
fprintf ( fpHeaderFile, " IDispatch *pInstance,\n" );
|
|
fprintf ( fpHeaderFile, " WORD wVTblOffset,\n" );
|
|
fprintf ( fpHeaderFile, " PROPERTYDESC_BASIC_ABSTRACT *pDesc,\n" );
|
|
fprintf ( fpHeaderFile, " WORD wFlags,\n" );
|
|
fprintf ( fpHeaderFile, " DISPPARAMS *pdispparams,\n" );
|
|
fprintf ( fpHeaderFile, " VARIANT *pvarResult);\n\n\n" );
|
|
|
|
// Spit out function signatures for handlers.
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
fprintf ( fpHeaderFile, "HRESULT %s (CBase *pBase,\n", (LPCSTR)(_allHandlers[i].szRawString) );
|
|
fprintf ( fpHeaderFile, " IServiceProvider *pSrvProvider,\n" );
|
|
fprintf ( fpHeaderFile, " IDispatch *pInstance,\n" );
|
|
fprintf ( fpHeaderFile, " WORD wVTblOffset,\n" );
|
|
fprintf ( fpHeaderFile, " PROPERTYDESC_BASIC_ABSTRACT *pDesc,\n" );
|
|
fprintf ( fpHeaderFile, " WORD wFlags,\n" );
|
|
fprintf ( fpHeaderFile, " DISPPARAMS *pdispparams,\n" );
|
|
fprintf ( fpHeaderFile, " VARIANT *pvarResult);\n\n" );
|
|
}
|
|
|
|
fprintf ( fpHeaderFile, "\n" );
|
|
|
|
// Spit out indexes into handler table.
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
fprintf ( fpHeaderFile, "#define \tIDX_%s \t%i\n", (LPCSTR)(_allHandlers[i].szRawString), i );
|
|
}
|
|
|
|
fclose ( fpHeaderFile );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void GenerateFunctionBody ( FILE * fpCXXFile, DispatchHandler *pHandler)
|
|
{
|
|
if ((pHandler->invokeType & ATYPE_GetProperty) || (pHandler->invokeType & ATYPE_SetProperty))
|
|
{
|
|
BOOL fObjectRet = FALSE;
|
|
BOOL fBSTRParam = FALSE;
|
|
BOOL fGetAndSet = (pHandler->invokeType & ATYPE_GetProperty) &&
|
|
(pHandler->invokeType & ATYPE_SetProperty);
|
|
BOOL fGS_BSTR = pHandler->szRawString == "GS_BSTR";
|
|
BOOL fGS_VARIANT = pHandler->szRawString == "GS_VARIANT";
|
|
BOOL fGS_PropEnum = pHandler->szRawString == "GS_PropEnum";
|
|
char chIdent[16];
|
|
|
|
chIdent[0] = '\0';
|
|
|
|
// Does the property muck with an object?
|
|
fObjectRet = ((pHandler->vtResult & VT_TYPEMASK) == VT_UNKNOWN) ||
|
|
((pHandler->vtResult & VT_TYPEMASK) == VT_DISPATCH);
|
|
fBSTRParam = ((pHandler->vtResult & VT_TYPEMASK) == VT_BSTR);
|
|
|
|
if (pHandler->invokeType & ATYPE_GetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " typedef HRESULT (STDMETHODCALLTYPE *OLEVTbl%sPropFunc)(IDispatch *, %s *);\n", fGetAndSet ? "Get" : "", (LPCSTR)pHandler->szCResult );
|
|
}
|
|
if (pHandler->invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " typedef HRESULT (STDMETHODCALLTYPE *OLEVTbl%sPropFunc)(IDispatch *, %s);\n", fGetAndSet ? "Set" : "", (LPCSTR)pHandler->szCResult );
|
|
}
|
|
fprintf ( fpCXXFile, "\n" );
|
|
|
|
fprintf ( fpCXXFile, " HRESULT hr;\n" );
|
|
|
|
// Any IDispatch* or IUnknown* arguments? If so then possible
|
|
// creation of BSTR/object needs to be handled.
|
|
if ((pHandler->invokeType & ATYPE_SetProperty) && (fObjectRet || fBSTRParam || fGS_VARIANT))
|
|
{
|
|
fprintf ( fpCXXFile, " ULONG ulAlloc = 0;\n" );
|
|
}
|
|
|
|
if (pHandler->invokeType & ATYPE_GetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " VTABLE_ENTRY *pVTbl;\n");
|
|
}
|
|
else if (pHandler->invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " VTABLE_ENTRY *pVTbl;\n");
|
|
}
|
|
fprintf ( fpCXXFile, " VARTYPE argTypes[] = { %s };\n", (LPCSTR)pHandler->szVTResult );
|
|
|
|
if (pHandler->invokeType & ATYPE_SetProperty && pHandler->szCResult.Length() > 0)
|
|
{
|
|
fprintf ( fpCXXFile, " %s param1;\n", (LPCSTR)pHandler->szCResult );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, "\n Assert(pInstance || pDesc || pdispparams);\n\n" );
|
|
|
|
if (pHandler->invokeType & ATYPE_GetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " pVTbl = (VTABLE_ENTRY *)(((BYTE *)(*(DWORD_PTR *)pInstance)) + (wVTblOffset*sizeof(VTABLE_ENTRY)/sizeof(DWORD_PTR) + FIRST_VTABLE_OFFSET));\n\n");
|
|
}
|
|
else if (pHandler->invokeType & ATYPE_SetProperty)
|
|
{
|
|
fprintf ( fpCXXFile, " pVTbl = (VTABLE_ENTRY *)(((BYTE *)(*(DWORD_PTR *)pInstance)) + (wVTblOffset*sizeof(VTABLE_ENTRY)/sizeof(DWORD_PTR) + FIRST_VTABLE_OFFSET));\n\n");
|
|
}
|
|
|
|
if ((pHandler->invokeType & ATYPE_GetProperty) && (pHandler->invokeType & ATYPE_SetProperty))
|
|
{
|
|
fprintf ( fpCXXFile, " if (wFlags & INVOKE_PROPERTYGET)\n" );
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
strcpy( chIdent, " " );
|
|
}
|
|
|
|
if (pHandler->invokeType & ATYPE_GetProperty)
|
|
{
|
|
if ((pHandler->szCResult.Length() > 0) && (pHandler->vtResult != VT_VARIANT))
|
|
{
|
|
fprintf ( fpCXXFile, "%s hr = (*(OLEVTbl%sPropFunc)VTBL_PFN(pVTbl))((IDispatch*) VTBL_THIS(pVTbl,pInstance), (%s *)&pvarResult->iVal);\n", chIdent, fGetAndSet ? "Get" : "", (LPCSTR)pHandler->szCResult);
|
|
fprintf ( fpCXXFile, "%s if (!hr)\n", chIdent );
|
|
fprintf ( fpCXXFile, "%s V_VT(pvarResult) = argTypes[0];\n", chIdent );
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, "%s hr = (*(OLEVTbl%sPropFunc)VTBL_PFN(pVTbl))((IDispatch*)VTBL_THIS(pVTbl, pInstance), pvarResult);\n", chIdent, fGetAndSet ? "Get" : "");
|
|
}
|
|
}
|
|
|
|
if ((pHandler->invokeType & ATYPE_GetProperty) && (pHandler->invokeType & ATYPE_SetProperty))
|
|
{
|
|
fprintf ( fpCXXFile, " }\n" );
|
|
fprintf ( fpCXXFile, " else\n" );
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
}
|
|
|
|
if (pHandler->invokeType & ATYPE_SetProperty)
|
|
{
|
|
if (pHandler->szCResult.Length() > 0)
|
|
{
|
|
fprintf ( fpCXXFile, "%s // Convert dispatch params to C params.\n", chIdent );
|
|
fprintf ( fpCXXFile, "%s hr = DispParamsToCParams(pSrvProvider, pdispparams, ", chIdent);
|
|
if (fObjectRet || fBSTRParam || fGS_VARIANT)
|
|
fprintf ( fpCXXFile, "&ulAlloc, " ); // Keep track of all allocation.
|
|
else
|
|
fprintf ( fpCXXFile, "0L, " );
|
|
|
|
if (fGS_BSTR || fGS_VARIANT || fGS_PropEnum)
|
|
fprintf ( fpCXXFile, "((PROPERTYDESC_BASIC_ABSTRACT *)pDesc)->b.wMaxstrlen, " );
|
|
else
|
|
fprintf ( fpCXXFile, "0, " );
|
|
|
|
fprintf ( fpCXXFile, "argTypes, ¶m1, -1);\n" );
|
|
|
|
fprintf ( fpCXXFile, "%s if (hr)\n", chIdent );
|
|
fprintf ( fpCXXFile, "%s pBase->SetErrorInfo(hr);\n", chIdent );
|
|
fprintf ( fpCXXFile, "%s else\n", chIdent );
|
|
if (fGetAndSet)
|
|
{
|
|
fprintf ( fpCXXFile, "%s hr = (*(OLEVTblSetPropFunc)VTBL_PFN(pVTbl))((IDispatch*)VTBL_THIS(pVTbl,pInstance), (%s)param1);\n", chIdent, (LPCSTR)pHandler->szCResult);
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, "%s hr = (*(OLEVTblPropFunc)VTBL_PFN(pVTbl))((IDispatch*)VTBL_THIS(pVTbl,pInstance), (%s)param1);\n", chIdent, (LPCSTR)pHandler->szCResult);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, "%s hr = (*(OLEVTblPropFunc)VTBL_PFN(pVTbl))((IDispatch*)VTBL_THIS(pVTbl,pInstance), pdispparams[0]);\n", chIdent );
|
|
}
|
|
}
|
|
|
|
if ((pHandler->invokeType & ATYPE_GetProperty) && (pHandler->invokeType & ATYPE_SetProperty))
|
|
{
|
|
fprintf ( fpCXXFile, " }\n" );
|
|
}
|
|
|
|
if ((pHandler->invokeType & ATYPE_SetProperty) && (fObjectRet || fBSTRParam || fGS_VARIANT))
|
|
{
|
|
if (fGS_VARIANT)
|
|
fprintf ( fpCXXFile, " if (ulAlloc)\n" );
|
|
else
|
|
fprintf ( fpCXXFile, " if (ulAlloc && param1)\n" );
|
|
|
|
if (fObjectRet)
|
|
{
|
|
fprintf ( fpCXXFile, " param1->Release();\n");
|
|
}
|
|
else if (fBSTRParam)
|
|
{
|
|
fprintf ( fpCXXFile, " SysFreeString(param1);\n");
|
|
}
|
|
else if (fGS_VARIANT)
|
|
{
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
fprintf ( fpCXXFile, " Assert(V_VT(¶m1) == VT_BSTR);\n" );
|
|
fprintf ( fpCXXFile, " SysFreeString(V_BSTR(¶m1));\n" );
|
|
fprintf ( fpCXXFile, " }\n" );
|
|
}
|
|
}
|
|
|
|
fprintf ( fpCXXFile, "\n return hr;\n" );
|
|
}
|
|
else if ( pHandler->invokeType & ATYPE_Method )
|
|
{
|
|
// We've got a method to spit out.
|
|
char chVARMacro[16];
|
|
int i;
|
|
BOOL fParamConvert;
|
|
BOOL fBSTRParam = FALSE;
|
|
BOOL fObjectParam = FALSE;
|
|
BOOL fVariantParam = FALSE;
|
|
int cArgs;
|
|
|
|
if (pHandler->vtResult & VT_BYREF)
|
|
{
|
|
strcpy(chVARMacro, "V_BYREF");
|
|
}
|
|
else
|
|
{
|
|
switch (pHandler->vtResult & VT_TYPEMASK) {
|
|
case VT_EMPTY:
|
|
strcpy(chVARMacro, "");
|
|
break;
|
|
case VT_I2:
|
|
strcpy(chVARMacro, "V_I2");
|
|
break;
|
|
case VT_I4:
|
|
strcpy(chVARMacro, "V_I4");
|
|
break;
|
|
case VT_R4:
|
|
strcpy(chVARMacro, "V_R4");
|
|
break;
|
|
case VT_R8:
|
|
strcpy(chVARMacro, "V_R8");
|
|
break;
|
|
case VT_CY:
|
|
strcpy(chVARMacro, "V_CY");
|
|
break;
|
|
case VT_BSTR:
|
|
strcpy(chVARMacro, "V_BSTR");
|
|
break;
|
|
case VT_DISPATCH:
|
|
case VT_VARIANT:
|
|
case VT_UNKNOWN:
|
|
strcpy(chVARMacro, "V_BYREF");
|
|
break;
|
|
case VT_BOOL:
|
|
strcpy(chVARMacro, "V_BOOL");
|
|
break;
|
|
default:
|
|
strcpy(chVARMacro, "Unsupported");
|
|
}
|
|
}
|
|
|
|
fprintf ( fpCXXFile, " typedef HRESULT (STDMETHODCALLTYPE *MethodOLEVTblFunc)(IDispatch *" );
|
|
|
|
i = 0;
|
|
cArgs = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
fprintf ( fpCXXFile, ", %s", (LPCSTR)pHandler->params[i].szCParamType );
|
|
i++;
|
|
cArgs++;
|
|
}
|
|
|
|
if ( pHandler->vtResult != VT_EMPTY )
|
|
{
|
|
fprintf ( fpCXXFile, ", %s", (LPCSTR)pHandler->szCResult );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, ");\n\n" );
|
|
|
|
fprintf ( fpCXXFile, " HRESULT hr;\n" );
|
|
fprintf ( fpCXXFile, " VTABLE_ENTRY *pVTbl;\n" );
|
|
|
|
fParamConvert = cArgs;
|
|
|
|
// Any paramters?
|
|
if (fParamConvert)
|
|
{
|
|
int iDefIndex;
|
|
|
|
fprintf ( fpCXXFile, " VARTYPE argTypes[] = {\n" );
|
|
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
fprintf ( fpCXXFile, " %s,\n",
|
|
(LPCSTR)pHandler->params[i].szVTParamType );
|
|
i++;
|
|
}
|
|
|
|
fprintf ( fpCXXFile, " };\n" );
|
|
|
|
i = 0;
|
|
iDefIndex = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
fBSTRParam |= ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_BSTR);
|
|
fVariantParam |= ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_VARIANT);
|
|
fObjectParam |= ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_UNKNOWN) ||
|
|
((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_DISPATCH);
|
|
|
|
if (pHandler->params[i].fOptional)
|
|
{
|
|
if (pHandler->params[i].vtParam == (VT_VARIANT | VT_BYREF))
|
|
{
|
|
fprintf ( fpCXXFile, " CVariant param%iopt(VT_ERROR); // optional variant\n", i + 1 );
|
|
fprintf ( fpCXXFile, " VARIANT *param%i = ¶m%iopt; // optional arg.\n", i + 1, i + 1 );
|
|
}
|
|
else if (pHandler->params[i].vtParam == VT_VARIANT)
|
|
{
|
|
fprintf ( fpCXXFile, " VARIANT param%i; // optional arg.\n", i + 1 );
|
|
}
|
|
else
|
|
{
|
|
// error, only VARIANT and VARIANT * can be optional.
|
|
PDLError("optional only allowed for VARIANT and VARIANT *");
|
|
return;
|
|
}
|
|
}
|
|
else if (pHandler->params[i].fDefaultValue)
|
|
{
|
|
if (pHandler->params[i].vtParam == VT_BSTR)
|
|
{
|
|
fprintf ( fpCXXFile, " %s paramDef%i = SysAllocString((TCHAR *)(((PROPERTYDESC_METHOD *)pDesc)->c->defargs[%i]));\n",
|
|
(LPCSTR)pHandler->params[i].szCParamType,
|
|
i + 1,
|
|
iDefIndex );
|
|
fprintf ( fpCXXFile, " %s param%i = paramDef%i;\n",
|
|
(LPCSTR)pHandler->params[i].szCParamType,
|
|
i + 1,
|
|
i + 1);
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, " %s param%i = (%s)(((PROPERTYDESC_METHOD *)pDesc)->c->defargs[%i]);\n",
|
|
(LPCSTR)pHandler->params[i].szCParamType,
|
|
i + 1,
|
|
(LPCSTR)pHandler->params[i].szCParamType,
|
|
iDefIndex );
|
|
}
|
|
|
|
iDefIndex++;
|
|
}
|
|
else
|
|
{
|
|
// Non optional variants need conversion if they contain a string that it longer than maxlen
|
|
fprintf ( fpCXXFile, " %s param%i;\n", (LPCSTR)pHandler->params[i].szCParamType, i + 1 );
|
|
}
|
|
i++;
|
|
}
|
|
|
|
// Any BSTR or IDispatch* or IUnknown* arguments? If so then possible
|
|
// creation of BSTR/object needs to be handled.
|
|
if (fBSTRParam || fObjectParam || fVariantParam)
|
|
{
|
|
fprintf ( fpCXXFile, " ULONG ulAlloc = 0;\n" );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, "\n" );
|
|
}
|
|
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
if ( pHandler->params[i].fOptional &&
|
|
pHandler->params[i].vtParam == VT_VARIANT )
|
|
{
|
|
fprintf ( fpCXXFile, " V_VT(¶m%i) = VT_ERROR;\n", i + 1 );
|
|
}
|
|
|
|
i++;
|
|
};
|
|
fprintf ( fpCXXFile, "\n" );
|
|
|
|
fprintf ( fpCXXFile, " Assert(pInstance || pDesc || pdispparams);\n\n" );
|
|
fprintf ( fpCXXFile, " pVTbl = (VTABLE_ENTRY*)(((BYTE *)(*(DWORD_PTR *)pInstance)) + wVTblOffset * sizeof(VTABLE_ENTRY)/sizeof(DWORD_PTR) + FIRST_VTABLE_OFFSET);\n\n" );
|
|
|
|
if ( pHandler->params[0].vtParam == VT_ARRAY )
|
|
{
|
|
fprintf ( fpCXXFile, " // Convert dispatch params to safearray.\n" );
|
|
fprintf ( fpCXXFile, " param1 = DispParamsToSAFEARRAY(pdispparams);\n" );
|
|
}
|
|
else if ( fParamConvert )
|
|
{
|
|
// Any parameters?
|
|
fprintf ( fpCXXFile, " // Convert dispatch params to C params.\n" );
|
|
fprintf ( fpCXXFile, " hr = DispParamsToCParams(pSrvProvider, pdispparams, " );
|
|
if (fBSTRParam || fObjectParam || fVariantParam)
|
|
fprintf ( fpCXXFile, "&ulAlloc, " );
|
|
else
|
|
fprintf ( fpCXXFile, "NULL, " );
|
|
|
|
if (fBSTRParam || fVariantParam)
|
|
fprintf ( fpCXXFile, "((PROPERTYDESC_BASIC_ABSTRACT *)pDesc)->b.wMaxstrlen" );
|
|
else
|
|
fprintf ( fpCXXFile, "0" );
|
|
|
|
fprintf ( fpCXXFile, ", argTypes" );
|
|
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
fprintf ( fpCXXFile, ", ¶m%i", i + 1 );
|
|
i++;
|
|
}
|
|
|
|
fprintf ( fpCXXFile, ", -1L);\n" );
|
|
|
|
fprintf ( fpCXXFile, " if (hr)\n" );
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
fprintf ( fpCXXFile, " pBase->SetErrorInfo(hr);\n" );
|
|
fprintf ( fpCXXFile, " goto Cleanup;\n" );
|
|
fprintf ( fpCXXFile, " }\n\n" );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, " hr = (*(MethodOLEVTblFunc)VTBL_PFN(pVTbl))((IDispatch*)VTBL_THIS(pVTbl,pInstance)", chVARMacro );
|
|
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
fprintf ( fpCXXFile, ", param%i", i + 1 );
|
|
i++;
|
|
}
|
|
|
|
// Do we have a result type?
|
|
if ( pHandler->vtResult != VT_EMPTY )
|
|
{
|
|
if (((pHandler->vtResult & VT_BYREF) == VT_BYREF) && ((pHandler->vtResult & VT_TYPEMASK) != VT_VARIANT))
|
|
{
|
|
fprintf ( fpCXXFile, ", (%s)(&(pvarResult->pdispVal))", (LPCSTR)pHandler->szCResult );
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, ", pvarResult" );
|
|
}
|
|
}
|
|
|
|
fprintf ( fpCXXFile, ");\n" );
|
|
|
|
if (((pHandler->vtResult & VT_BYREF) == VT_BYREF) && ((pHandler->vtResult & VT_TYPEMASK) != VT_VARIANT))
|
|
{
|
|
fprintf ( fpCXXFile, " if (!hr)\n");
|
|
fprintf ( fpCXXFile, " V_VT(pvarResult) = (%s) & ~VT_BYREF;\n", (LPCSTR)pHandler->szVTResult );
|
|
}
|
|
|
|
if ( pHandler->params[0].vtParam == VT_ARRAY )
|
|
{
|
|
fprintf ( fpCXXFile, " if (param1)\n" );
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
fprintf ( fpCXXFile, " HRESULT hr1 = SafeArrayDestroy(param1);\n" );
|
|
fprintf ( fpCXXFile, " if (hr1)\n");
|
|
fprintf ( fpCXXFile, " hr = hr1;\n");
|
|
fprintf ( fpCXXFile, " }\n" );
|
|
}
|
|
else if ( fParamConvert )
|
|
{
|
|
// Any parameters then we'll need a cleanup routine.
|
|
fprintf ( fpCXXFile, "\nCleanup:\n" );
|
|
}
|
|
|
|
|
|
// Deallocate any default BSTR parameters.
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
if (pHandler->params[i].fDefaultValue && pHandler->params[i].vtParam == VT_BSTR)
|
|
{
|
|
fprintf ( fpCXXFile, " SysFreeString(paramDef%i);\n", i + 1);
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (fBSTRParam || fObjectParam || fVariantParam)
|
|
{
|
|
i = 0;
|
|
while ( pHandler->params[i].szVTParamType.Length() )
|
|
{
|
|
// Variants don't need conversion.
|
|
if ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_BSTR)
|
|
{
|
|
fprintf ( fpCXXFile, " if (ulAlloc & %i)\n", (1 << i) );
|
|
fprintf ( fpCXXFile, " SysFreeString(param%i);\n", i + 1);
|
|
}
|
|
if ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_UNKNOWN ||
|
|
(pHandler->params[i].vtParam & VT_TYPEMASK) == VT_DISPATCH)
|
|
{
|
|
if (!(pHandler->params[i].vtParam & VT_BYREF))
|
|
{
|
|
fprintf ( fpCXXFile, " if ((ulAlloc & %i) && param%i)\n", (1 << i), i + 1 );
|
|
fprintf ( fpCXXFile, " param%i->Release();\n", i + 1);
|
|
}
|
|
else
|
|
{
|
|
fprintf ( fpCXXFile, " if ((ulAlloc & %i) && *param%i)\n", (1 << i), i + 1 );
|
|
fprintf ( fpCXXFile, " (*param%i)->Release();\n", i + 1);
|
|
}
|
|
}
|
|
if ((pHandler->params[i].vtParam & VT_TYPEMASK) == VT_VARIANT)
|
|
{
|
|
fprintf ( fpCXXFile, " if (ulAlloc & %i)\n", (1 << i) );
|
|
fprintf ( fpCXXFile, " {\n" );
|
|
fprintf ( fpCXXFile, " Assert(V_VT(%sparam%i) == VT_BSTR);\n",
|
|
pHandler->params[i].vtParam & VT_BYREF ? "" : "&", i + 1);
|
|
fprintf ( fpCXXFile, " SysFreeString(V_BSTR(%sparam%i));\n",
|
|
pHandler->params[i].vtParam & VT_BYREF ? "" : "&", i + 1);
|
|
fprintf ( fpCXXFile, " }\n" );
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
fprintf ( fpCXXFile, " return hr;\n" );
|
|
}
|
|
}
|
|
|
|
|
|
BOOL GenerateVTableCXX ( LPCSTR pszOutputPath )
|
|
{
|
|
char chCXXFileName[255];
|
|
FILE *fpCXXFile;
|
|
int i;
|
|
|
|
strcpy(chCXXFileName, pszOutputPath);
|
|
strcat(chCXXFileName, FILENAME_SEPARATOR_STR "funcsig.cxx");
|
|
|
|
fpCXXFile = fopen ( chCXXFileName, "w" );
|
|
if ( !fpCXXFile )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Generate CXX file.
|
|
//
|
|
|
|
// Spit out handler table.
|
|
fprintf ( fpCXXFile, "\n\nstatic const CustomHandler _HandlerTable[] = {\n" );
|
|
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
fprintf ( fpCXXFile, " %s,\n", (LPCSTR)(_allHandlers[i].szRawString));
|
|
}
|
|
|
|
fprintf ( fpCXXFile, " NULL\n" );
|
|
fprintf ( fpCXXFile, "};\n\n" );
|
|
|
|
// Spit out function signatures for handlers.
|
|
for (i = 0; i < _cHandlers; i++)
|
|
{
|
|
fprintf ( fpCXXFile, "HRESULT %s (CBase *pBase,\n", (LPCSTR)(_allHandlers[i].szRawString) );
|
|
fprintf ( fpCXXFile, " IServiceProvider *pSrvProvider,\n" );
|
|
fprintf ( fpCXXFile, " IDispatch *pInstance,\n" );
|
|
fprintf ( fpCXXFile, " WORD wVTblOffset,\n" );
|
|
fprintf ( fpCXXFile, " PROPERTYDESC_BASIC_ABSTRACT *pDesc,\n" );
|
|
fprintf ( fpCXXFile, " WORD wFlags,\n" );
|
|
fprintf ( fpCXXFile, " DISPPARAMS *pdispparams,\n" );
|
|
fprintf ( fpCXXFile, " VARIANT *pvarResult)\n" );
|
|
fprintf ( fpCXXFile, "{\n" );
|
|
|
|
GenerateFunctionBody ( fpCXXFile, &(_allHandlers[i]) );
|
|
|
|
fprintf ( fpCXXFile, "}\n" );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, "\n" );
|
|
|
|
for (i = 0; i < _cIID; i++)
|
|
{
|
|
fprintf ( fpCXXFile, "EXTERN_C const IID IID_%s;\n", _allIIDs[i] );
|
|
}
|
|
|
|
fprintf ( fpCXXFile, "\n\n" );
|
|
|
|
fprintf ( fpCXXFile, "#define MAX_IIDS %i\n", _cIID + 1); // The null entry at index 0.
|
|
|
|
fprintf ( fpCXXFile, "static const IID * _IIDTable[MAX_IIDS] = {\n" );
|
|
fprintf ( fpCXXFile, "\tNULL,\n" ); // Index 0 is reserved for primary dispatch interface.
|
|
// Spit out indexes into IID table.
|
|
for (i = 0; i < _cIID; i++)
|
|
{
|
|
fprintf ( fpCXXFile, "\t&IID_%s,\n", _allIIDs[i] );
|
|
}
|
|
fprintf ( fpCXXFile, "};\n");
|
|
|
|
fprintf ( fpCXXFile, "\n" );
|
|
|
|
// Helper function for mapping DISP_IHTMLxxxxx
|
|
fprintf ( fpCXXFile, "#define DIID_DispBase 0x3050f500\n" );
|
|
fprintf ( fpCXXFile, "#define DIID_DispMax 0x3050f5a0\n" );
|
|
fprintf ( fpCXXFile, "\n" );
|
|
fprintf ( fpCXXFile, "const GUID DIID_Low12Bytes = { 0x00000000, 0x98b5, 0x11cf, { 0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b } };\n" );
|
|
fprintf ( fpCXXFile, "\n\n" );
|
|
fprintf ( fpCXXFile, "BOOL DispNonDualDIID(IID iid)\n" );
|
|
fprintf ( fpCXXFile, "{\n" );
|
|
fprintf ( fpCXXFile, "\tBOOL fRetVal = FALSE;\n" );
|
|
fprintf ( fpCXXFile, "\n" );
|
|
fprintf ( fpCXXFile, "\tif (iid.Data1 >= DIID_DispBase && iid.Data1 <= DIID_DispMax)\n" );
|
|
fprintf ( fpCXXFile, "\t{\n" );
|
|
fprintf ( fpCXXFile, "\t\tfRetVal = memcmp(&iid.Data2,\n" );
|
|
fprintf ( fpCXXFile, "\t\t\t\t&DIID_Low12Bytes.Data2,\n" );
|
|
fprintf ( fpCXXFile, "\t\t\t\tsizeof(IID) - sizeof(DWORD)) == 0;\n" );
|
|
fprintf ( fpCXXFile, "\t}\n" );
|
|
fprintf ( fpCXXFile, "\n" );
|
|
fprintf ( fpCXXFile, "\treturn fRetVal;\n" );
|
|
fprintf ( fpCXXFile, "}\n\n" );
|
|
|
|
fclose ( fpCXXFile );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
struct TypeMap {
|
|
char chType[32];
|
|
char chAutomationType[32];
|
|
char chCType[32];
|
|
VARTYPE vtResult;
|
|
};
|
|
|
|
static TypeMap _mapper[] = {
|
|
{ "IDispatchp" , "VT_DISPATCH" , "IDispatch *" , VT_DISPATCH }, // Entry 0 is VT_DISPATCH
|
|
{ "IDispatchpp" , "VT_DISPATCH | VT_BYREF" , "IDispatch **" , VT_DISPATCH | VT_BYREF }, // Entry 1 is VT_DISPATCH | VT_BYREF
|
|
{ "DWORD" , "VT_I4" , "DWORD" , VT_I4 },
|
|
{ "long" , "VT_I4" , "LONG" , VT_I4 },
|
|
{ "LONG" , "VT_I4" , "LONG" , VT_I4 },
|
|
//************************************************************************************************
|
|
// Warning Warning Warning:
|
|
// This only works for abstract properies. To use it for non-abstract property, please modify corresponding Trident code
|
|
//
|
|
{ "LONGPTR" , "VT_I4" , "LONG_PTR" , VT_I4},
|
|
{ "LONGPTR" , "VT_I8" , "LONG_PTR" , VT_I8},
|
|
//
|
|
//************************************************************************************************
|
|
{ "short" , "VT_I2" , "SHORT" , VT_I2 },
|
|
{ "VARIANT" , "VT_VARIANT" , "VARIANT" , VT_VARIANT },
|
|
{ "BSTR" , "VT_BSTR" , "BSTR" , VT_BSTR },
|
|
{ "BOOL" , "VT_BOOL" , "VARIANT_BOOL" , VT_BOOL },
|
|
{ "BOOLp" , "VT_BOOL | VT_BYREF" , "VARIANT_BOOL *" , VT_BOOL | VT_BYREF },
|
|
{ "VARIANTp" , "VT_VARIANT | VT_BYREF" , "VARIANT *" , VT_VARIANT | VT_BYREF },
|
|
{ "IUnknownp" , "VT_UNKNOWN" , "IUnknown *" , VT_UNKNOWN },
|
|
{ "IUnknownpp" , "VT_UNKNOWN | VT_BYREF" , "IUnknown **" , VT_UNKNOWN | VT_BYREF },
|
|
{ "float" , "VT_R4" , "float" , VT_R4 },
|
|
{ "longp" , "VT_I4 | VT_BYREF" , "LONG *" , VT_I4 | VT_BYREF },
|
|
{ "BSTRp" , "VT_BSTR | VT_BYREF" , "BSTR *" , VT_BSTR | VT_BYREF },
|
|
{ "int" , "VT_I4" , "LONG" , VT_I4 },
|
|
{ "VARIANTBOOL" , "VT_BOOL" , "VARIANT_BOOL" , VT_BOOL },
|
|
{ "VARIANTBOOLp" , "VT_BOOL | VT_BYREF" , "VARIANT_BOOL *" , VT_BOOL | VT_BYREF },
|
|
{ "SAFEARRAYPVARIANTP" , "VT_ARRAY" , "SAFEARRAY *" , VT_ARRAY },
|
|
{ "void" , "" , "" , VT_EMPTY },
|
|
{ "PropEnum" , "VT_BSTR" , "BSTR" , VT_BSTR }, // TODO: Remove and fix.
|
|
{ "IHTMLControlElementp", "VT_DISPATCH" , "IDispatch *" , VT_DISPATCH }, // TODO: Not converted to IDispatch
|
|
{ "IHTMLElementpp" , "VT_DISPATCH | VT_BYREF" , "IDispatch **" , VT_DISPATCH | VT_BYREF }, // TODO: Not converted to IDispatch
|
|
{ "IHTMLElementCollectionpp" , "VT_DISPATCH | VT_BYREF" , "IDispatch **" , VT_DISPATCH | VT_BYREF }, // TODO: Not converted to IDispatch
|
|
{ "" , "" , "" , VT_EMPTY }
|
|
};
|
|
|
|
BOOL MapTypeToAutomationType (char *pTypeStr, char **ppAutomationType, char **ppCType, VARTYPE *pVTType)
|
|
{
|
|
int i = 0;
|
|
int win64offset = 0;
|
|
VARTYPE vtTemp;
|
|
|
|
if (!pVTType)
|
|
pVTType = &vtTemp;
|
|
|
|
if (gfWin64)
|
|
win64offset = 1;
|
|
|
|
while (_mapper[i].chType[0])
|
|
{
|
|
if (strcmp(_mapper[i].chType, pTypeStr) == 0)
|
|
{
|
|
//
|
|
// special handling for LONGPTR is required since it will be
|
|
// resolved to two diffferent types depending on arch!
|
|
//
|
|
if (strcmp(_mapper[i].chType, "LONGPTR") == 0)
|
|
{
|
|
i += win64offset;
|
|
}
|
|
|
|
*ppAutomationType = _mapper[i].chAutomationType;
|
|
*ppCType = _mapper[i].chCType;
|
|
*pVTType = _mapper[i].vtResult;
|
|
return TRUE;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL ProcessDatFile ( LPCSTR pszOutputPath )
|
|
{
|
|
char *buffer;
|
|
FILE *fpDatFile;
|
|
char chDatFileName[255];
|
|
char szTextError[MAX_LINE_LEN+1];
|
|
char *pATypeStr;
|
|
char *pCTypeStr;
|
|
int cLines;
|
|
|
|
if ( !pszOutputPath )
|
|
return FALSE;
|
|
|
|
strcpy(chDatFileName, pszOutputPath);
|
|
strcat(chDatFileName, FILENAME_SEPARATOR_STR "funcsig.dat");
|
|
|
|
fpDatFile = fopen ( chDatFileName, "rb");
|
|
|
|
if ( !fpDatFile )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( fseek( fpDatFile, 0, SEEK_END ) == 0 )
|
|
{
|
|
fpos_t pos;
|
|
|
|
if ( fgetpos( fpDatFile, &pos ) == 0 )
|
|
{
|
|
int i = 0;
|
|
|
|
buffer = new char[pos];
|
|
if (buffer == NULL)
|
|
return FALSE;
|
|
|
|
fseek( fpDatFile, 0, SEEK_SET );
|
|
|
|
if ( (unsigned) fread ( buffer, 1, pos, fpDatFile ) != pos )
|
|
return FALSE;
|
|
|
|
// Create the header file from the .dat file.
|
|
_cHandlers = buffer[0]; // Number of signatures
|
|
_cHandlers &= 0x000000ff;
|
|
_cIID = buffer[1]; // Number of IIDs
|
|
_cIID &= 0x000000ff;
|
|
|
|
if (_cHandlers >= MAX_HANDLERS)
|
|
{
|
|
PDLError("To many handlers increase MAX_HANDLERS\n");
|
|
goto Error;
|
|
}
|
|
|
|
if (_cIID >= MAX_IIDS)
|
|
{
|
|
PDLError("To many handlers increase MAX_IIDS\n");
|
|
goto Error;
|
|
}
|
|
|
|
i = 4; // Skip 4 byte header.
|
|
cLines = 0;
|
|
while ( cLines < _cHandlers )
|
|
{
|
|
char *pStrWork;
|
|
char *pStrWork2;
|
|
int cStr = strlen ( buffer + i );
|
|
|
|
// Copy raw function signature.
|
|
_allHandlers[cLines].szRawString = (buffer + i);
|
|
|
|
pStrWork = buffer + i;
|
|
|
|
// Get type
|
|
pStrWork2 = strchr(pStrWork, '_');
|
|
if (!pStrWork2)
|
|
goto Error;
|
|
*pStrWork2 = '\0';
|
|
|
|
_allHandlers[cLines].invokeType = ATYPE_Undefined;
|
|
if (strchr(pStrWork, 'G'))
|
|
_allHandlers[cLines].invokeType |= ATYPE_GetProperty;
|
|
if (strchr(pStrWork, 'S'))
|
|
_allHandlers[cLines].invokeType |= ATYPE_SetProperty;
|
|
if (strchr(pStrWork, 'M'))
|
|
_allHandlers[cLines].invokeType = ATYPE_Method;
|
|
|
|
// Point pass the G, S, GS or Method
|
|
pStrWork = pStrWork2 + 1;
|
|
|
|
if (_allHandlers[cLines].invokeType == ATYPE_Method)
|
|
{
|
|
// Do method parsing:
|
|
int iArg;
|
|
|
|
pStrWork2 = strchr(pStrWork, '_');
|
|
if (!pStrWork2)
|
|
{
|
|
PDLError("bad method result");
|
|
return FALSE;
|
|
}
|
|
|
|
*pStrWork2 = '\0';
|
|
|
|
// Get result type
|
|
if (MapTypeToAutomationType(pStrWork, &pATypeStr, &pCTypeStr, &(_allHandlers[cLines].vtResult)))
|
|
{
|
|
_allHandlers[cLines].szVTResult = pATypeStr;
|
|
_allHandlers[cLines].szCResult = pCTypeStr;
|
|
}
|
|
else
|
|
{
|
|
sprintf(szTextError, "result type '%s' not found.", pStrWork);
|
|
PDLError(szTextError);
|
|
return FALSE;
|
|
}
|
|
|
|
pStrWork = pStrWork2 + 1;
|
|
|
|
// arg parsing:
|
|
iArg = 0;
|
|
while (*pStrWork)
|
|
{
|
|
pStrWork2 = strchr(pStrWork, '_');
|
|
if (pStrWork2)
|
|
{
|
|
*pStrWork2 = '\0';
|
|
}
|
|
|
|
// optional argument?
|
|
_allHandlers[cLines].params[iArg].fOptional =
|
|
(pStrWork[0] == 'o' &&
|
|
pStrWork[1] == '0' &&
|
|
pStrWork[2] == 'o');
|
|
_allHandlers[cLines].params[iArg].fDefaultValue =
|
|
(pStrWork[0] == 'o' &&
|
|
pStrWork[1] == 'D' &&
|
|
pStrWork[2] == 'o');
|
|
|
|
if (_allHandlers[cLines].params[iArg].fOptional ||
|
|
_allHandlers[cLines].params[iArg].fDefaultValue)
|
|
{
|
|
pStrWork += 3; // Skip o0o or oDo which signals optional (litle o zero little o) or defaultValue.
|
|
}
|
|
|
|
if (MapTypeToAutomationType(pStrWork, &pATypeStr, &pCTypeStr, &(_allHandlers[cLines].params[iArg].vtParam)))
|
|
{
|
|
_allHandlers[cLines].params[iArg].szVTParamType = pATypeStr;
|
|
_allHandlers[cLines].params[iArg].szCParamType = pCTypeStr;
|
|
}
|
|
else
|
|
{
|
|
sprintf(szTextError, "argument type '%s' not found.", pStrWork);
|
|
PDLError(szTextError);
|
|
return FALSE;
|
|
}
|
|
|
|
pStrWork += strlen(pStrWork);
|
|
// More args to parse?
|
|
if (pStrWork2)
|
|
pStrWork++; // Point at next arg.
|
|
|
|
iArg++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Do property parsing
|
|
if (MapTypeToAutomationType(pStrWork, &pATypeStr, &pCTypeStr, &(_allHandlers[cLines].vtResult)))
|
|
{
|
|
_allHandlers[cLines].szVTResult = pATypeStr;
|
|
_allHandlers[cLines].szCResult = pCTypeStr;
|
|
}
|
|
else
|
|
{
|
|
sprintf(szTextError, "type '%s' not found.", pStrWork);
|
|
PDLError(szTextError);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
cLines++;
|
|
i += cStr + 1;
|
|
}
|
|
|
|
// Load up the IIDs.
|
|
cLines = 0;
|
|
while ( cLines < _cIID )
|
|
{
|
|
int cStr = strlen ( buffer + i );
|
|
|
|
_allIIDs[cLines] = buffer + i;
|
|
|
|
cLines++;
|
|
i += cStr + 1;
|
|
}
|
|
|
|
fclose ( fpDatFile );
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
Error:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
int __cdecl
|
|
main ( int argc, char *argv[] )
|
|
{
|
|
int nReturnCode;
|
|
char szInputFile [ MAX_PATH+1 ];
|
|
char szOutputFileRoot [ MAX_PATH+1 ];
|
|
char szPDLFileName [ MAX_PATH+1 ];
|
|
char szOutputPath [ MAX_PATH+1 ];
|
|
BOOL fDebugging = FALSE;
|
|
|
|
{
|
|
CPDLParser Parser;
|
|
|
|
|
|
// argv[1] is the name of a file containing build args
|
|
// arg1 of this file is the full path/filename of the input file
|
|
// arg2 is the full name of the output file, minus the file extension
|
|
// arg3 is the 8.3 pdl file name
|
|
// arg4 is a log file name
|
|
if ( argc == 5 )
|
|
{
|
|
strcpy ( szInputFile, argv [ 1] );
|
|
strcpy ( szOutputFileRoot, argv [ 2 ] );
|
|
strcpy ( szPDLFileName, argv [ 3 ] );
|
|
strcpy ( szOutputPath, argv [ 4 ] );
|
|
fDebugging = TRUE;
|
|
}
|
|
else if ( argc == 4 && _stricmp( argv[1], "/g") == 0 ||
|
|
_stricmp( argv[1], "-g") == 0 )
|
|
{
|
|
if (_stricmp(argv[2], "win64") == 0)
|
|
{
|
|
gfWin64 = TRUE;
|
|
}
|
|
else if (_stricmp(argv[2], "i386") ==0)
|
|
{
|
|
gfWin64 = FALSE;
|
|
}
|
|
else
|
|
{
|
|
printf ( "Invalid command line params\n" );
|
|
nReturnCode = 3;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Process the funcsig.dat file and produce custsig.hxx file:
|
|
if (!ProcessDatFile ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GenerateVTableHeader ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GenerateVTableCXX ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
FILE *fpMaxLenFile = NULL;
|
|
|
|
strcpy(szOutputPath, argv [ 3 ]);
|
|
strcat(szOutputPath, FILENAME_SEPARATOR_STR "maxlen.txt");
|
|
|
|
fpMaxLenFile = fopen(szOutputPath, "r+");
|
|
if (fpMaxLenFile)
|
|
{
|
|
char chMarker[6];
|
|
strcpy(chMarker, "Const");
|
|
fwrite(chMarker, sizeof(char), 5, fpMaxLenFile);
|
|
fclose(fpMaxLenFile);
|
|
}
|
|
|
|
#ifdef COMPLUS_SHIM
|
|
|
|
if (!GenerateNDirectHeader ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GenerateNDirectCXX ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GenerateComPlusHeader ( argv [ 3] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!GenerateComPlusCXX ( argv [ 3 ] ))
|
|
{
|
|
nReturnCode = 4;
|
|
goto Cleanup;
|
|
}
|
|
|
|
#endif // COMPLUS_SHIM
|
|
|
|
nReturnCode = 0;
|
|
goto Cleanup;
|
|
}
|
|
else if ( argc > 1 )
|
|
{
|
|
if ( !ScanBuildFile ( argv[ 1 ],
|
|
szInputFile,
|
|
szOutputFileRoot,
|
|
szPDLFileName,
|
|
szOutputPath ) )
|
|
{
|
|
printf ( "Cant scan build file\n" );
|
|
nReturnCode = 2;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf ( "Invalid command line params\n" );
|
|
nReturnCode = 3;
|
|
goto Cleanup;
|
|
}
|
|
|
|
nReturnCode = Parser.Parse ( szInputFile, szOutputFileRoot,
|
|
szPDLFileName, szOutputPath, fDebugging );
|
|
|
|
}
|
|
|
|
Cleanup:
|
|
if ( nReturnCode != 0 )
|
|
printf ( "Error %d building PDL file\n", nReturnCode );
|
|
exit ( nReturnCode );
|
|
}
|
|
|
|
#ifndef X_DATA_CXX_
|
|
#define X_DATA_CXX_
|
|
#include "data.cxx"
|
|
#endif
|
|
|
|
#ifndef X_ASSOC_CXX_
|
|
#define X_ASSOC_CXX_
|
|
#include "assoc.cxx"
|
|
#endif
|
|
|
|
#ifndef X_PARSER_CXX_
|
|
#define X_PARSER_CXX_
|
|
#include "parser.cxx"
|
|
#endif
|