#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 #endif #ifndef X_ASSERT_H_ #define X_ASSERT_H_ #include #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 "-" - 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 \n"); fprintf(fpCPCXXFile, "#include \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