// // This helper converts a serialized CFG grammar header into an in-memory header // internal static ScriptRef[] LoadScriptRefs(StreamMarshaler streamHelper, CfgSerializedHeader pFH) { // // Because in 64-bit code, pointers != sizeof(ULONG) we copy each member explicitly. // if (pFH.FormatId != CfgGrammar._SPGDF_ContextFree) { return(null); } //We know that in SAPI 5.0 grammar format pszWords follows header immediately. if (pFH.pszWords < Marshal.SizeOf <CfgSerializedHeader>()) { // Must be SAPI 6.0 or above to hold a .NET script return(null); } // Get the symbols StringBlob symbols = LoadStringBlob(streamHelper, pFH.pszSymbols, pFH.cchSymbols); // Get the script refs CfgScriptRef[] cfgScripts = Load <CfgScriptRef>(streamHelper, pFH.pScripts, pFH.cScripts); // Convert the CFG script reference to ScriptRef ScriptRef[] scripts = new ScriptRef[cfgScripts.Length]; for (int i = 0; i < cfgScripts.Length; i++) { CfgScriptRef cfgScript = cfgScripts[i]; scripts[i] = new ScriptRef(symbols[cfgScript._idRule], symbols[cfgScript._idMethod], cfgScript._method); } return(scripts); }
internal static ScriptRef[] LoadIL(Stream stream) { using (StreamMarshaler streamMarshaler = new StreamMarshaler(stream)) { CfgSerializedHeader cfgSerializedHeader = new CfgSerializedHeader(); streamMarshaler.ReadStream(cfgSerializedHeader); return(LoadScriptRefs(streamMarshaler, cfgSerializedHeader)); } }
private static void CheckValidCfgFormat(CfgSerializedHeader pFH, CfgHeader header, bool includeAllGrammarData) { if (pFH.pszWords < 100) { XmlParser.ThrowSrgsException(SRID.UnsupportedFormat); } int start = (int)pFH.pszWords; CheckSetOffsets(pFH.pszWords, pFH.cchWords * 2, ref start, pFH.ulTotalSerializedSize); CheckSetOffsets(pFH.pszSymbols, pFH.cchSymbols * 2, ref start, pFH.ulTotalSerializedSize); if (pFH.cRules > 0) { CheckSetOffsets(pFH.pRules, pFH.cRules * Marshal.SizeOf(typeof(CfgRule)), ref start, pFH.ulTotalSerializedSize); } if (pFH.cArcs > 0) { CheckSetOffsets(pFH.pArcs, pFH.cArcs * Marshal.SizeOf(typeof(CfgArc)), ref start, pFH.ulTotalSerializedSize); } if (pFH.pWeights != 0) { CheckSetOffsets(pFH.pWeights, pFH.cArcs * Marshal.SizeOf(typeof(float)), ref start, pFH.ulTotalSerializedSize); } if (pFH.cTags > 0) { CheckSetOffsets(pFH.tags, pFH.cTags * Marshal.SizeOf(typeof(CfgSemanticTag)), ref start, pFH.ulTotalSerializedSize); if (includeAllGrammarData) { for (int i = 0; i < header.tags.Length; i++) { int startArcIndex = (int)header.tags[i].StartArcIndex; int endArcIndex = (int)header.tags[i].EndArcIndex; int num = header.arcs.Length; if (startArcIndex == 0 || startArcIndex >= num || endArcIndex == 0 || endArcIndex >= num || (header.tags[i].PropVariantType != 0 && header.tags[i].PropVariantType == VarEnum.VT_BSTR && header.tags[i].PropVariantType == VarEnum.VT_BOOL && header.tags[i].PropVariantType == VarEnum.VT_R8 && header.tags[i].PropVariantType == VarEnum.VT_I4)) { XmlParser.ThrowSrgsException(SRID.UnsupportedFormat); } } } } if (pFH.cScripts > 0) { CheckSetOffsets(pFH.pScripts, pFH.cScripts * Marshal.SizeOf(typeof(CfgScriptRef)), ref start, pFH.ulTotalSerializedSize); } if (pFH.cIL > 0) { CheckSetOffsets(pFH.pIL, pFH.cIL * Marshal.SizeOf(typeof(byte)), ref start, pFH.ulTotalSerializedSize); } if (pFH.cPDB > 0) { CheckSetOffsets(pFH.pPDB, pFH.cPDB * Marshal.SizeOf(typeof(byte)), ref start, pFH.ulTotalSerializedSize); } }
internal static CfgHeader ConvertCfgHeader(StreamMarshaler streamHelper, bool includeAllGrammarData, bool loadSymbols, out CfgSerializedHeader cfgSerializedHeader) { cfgSerializedHeader = new CfgSerializedHeader(streamHelper.Stream); CfgHeader cfgHeader = default(CfgHeader); cfgHeader.FormatId = cfgSerializedHeader.FormatId; cfgHeader.GrammarGUID = cfgSerializedHeader.GrammarGUID; cfgHeader.langId = cfgSerializedHeader.LangID; cfgHeader.pszGlobalTags = cfgSerializedHeader.pszSemanticInterpretationGlobals; cfgHeader.cArcsInLargestState = cfgSerializedHeader.cArcsInLargestState; cfgHeader.rules = Load <CfgRule>(streamHelper, cfgSerializedHeader.pRules, cfgSerializedHeader.cRules); if (includeAllGrammarData || loadSymbols) { cfgHeader.pszSymbols = LoadStringBlob(streamHelper, cfgSerializedHeader.pszSymbols, cfgSerializedHeader.cchSymbols); } if (includeAllGrammarData) { cfgHeader.pszWords = LoadStringBlob(streamHelper, cfgSerializedHeader.pszWords, cfgSerializedHeader.cchWords); cfgHeader.arcs = Load <CfgArc>(streamHelper, cfgSerializedHeader.pArcs, cfgSerializedHeader.cArcs); cfgHeader.tags = Load <CfgSemanticTag>(streamHelper, cfgSerializedHeader.tags, cfgSerializedHeader.cTags); cfgHeader.weights = Load <float>(streamHelper, cfgSerializedHeader.pWeights, cfgSerializedHeader.cArcs); } if (cfgSerializedHeader.pszWords < Marshal.SizeOf(typeof(CfgSerializedHeader))) { cfgHeader.ulRootRuleIndex = uint.MaxValue; cfgHeader.GrammarOptions = GrammarOptions.KeyValuePairs; cfgHeader.BasePath = null; cfgHeader.GrammarMode = GrammarType.VoiceGrammar; } else { cfgHeader.ulRootRuleIndex = cfgSerializedHeader.ulRootRuleIndex; cfgHeader.GrammarOptions = cfgSerializedHeader.GrammarOptions; cfgHeader.GrammarMode = (GrammarType)cfgSerializedHeader.GrammarMode; if (includeAllGrammarData) { cfgHeader.scripts = Load <CfgScriptRef>(streamHelper, cfgSerializedHeader.pScripts, cfgSerializedHeader.cScripts); } if (cfgSerializedHeader.cBasePath != 0) { streamHelper.Stream.Position = (int)cfgSerializedHeader.pRules + cfgHeader.rules.Length * Marshal.SizeOf(typeof(CfgRule)); cfgHeader.BasePath = streamHelper.ReadNullTerminatedString(); } } CheckValidCfgFormat(cfgSerializedHeader, cfgHeader, includeAllGrammarData); return(cfgHeader); }
internal static ScriptRef[] LoadScriptRefs(StreamMarshaler streamHelper, CfgSerializedHeader pFH) { if (pFH.FormatId != _SPGDF_ContextFree) { return(null); } if (pFH.pszWords < Marshal.SizeOf(typeof(CfgSerializedHeader))) { return(null); } StringBlob stringBlob = LoadStringBlob(streamHelper, pFH.pszSymbols, pFH.cchSymbols); CfgScriptRef[] array = Load <CfgScriptRef>(streamHelper, pFH.pScripts, pFH.cScripts); ScriptRef[] array2 = new ScriptRef[array.Length]; for (int i = 0; i < array.Length; i++) { CfgScriptRef cfgScriptRef = array[i]; array2[i] = new ScriptRef(stringBlob[cfgScriptRef._idRule], stringBlob[cfgScriptRef._idMethod], cfgScriptRef._method); } return(array2); }
internal static bool LoadIL(Stream stream, out byte[] assemblyContent, out byte[] assemblyDebugSymbols, out ScriptRef[] scripts) { assemblyContent = (assemblyDebugSymbols = null); scripts = null; using (StreamMarshaler streamMarshaler = new StreamMarshaler(stream)) { CfgSerializedHeader cfgSerializedHeader = new CfgSerializedHeader(); streamMarshaler.ReadStream(cfgSerializedHeader); scripts = LoadScriptRefs(streamMarshaler, cfgSerializedHeader); if (scripts == null) { return(false); } if (cfgSerializedHeader.cIL == 0) { return(false); } assemblyContent = Load <byte>(streamMarshaler, cfgSerializedHeader.pIL, cfgSerializedHeader.cIL); assemblyDebugSymbols = ((cfgSerializedHeader.cPDB > 0) ? Load <byte>(streamMarshaler, cfgSerializedHeader.pPDB, cfgSerializedHeader.cPDB) : null); } return(true); }
private static void CheckValidCfgFormat(CfgSerializedHeader pFH, CfgHeader header, bool includeAllGrammarData) { //See backend commit method to understand the layout of cfg format if (pFH.pszWords < SP_SPCFGSERIALIZEDHEADER_500) { XmlParser.ThrowSrgsException(SRID.UnsupportedFormat); } int ullStartOffset = (int)pFH.pszWords; //Check the word offset //See stringblob implementation. pFH.cchWords * sizeof(WCHAR) isn't exactly the serialized size, but it is close and must be less than the serialized size CheckSetOffsets(pFH.pszWords, pFH.cchWords * Helpers._sizeOfChar, ref ullStartOffset, pFH.ulTotalSerializedSize); //Check the symbol offset //symbol is right after word //pFH.pszSymbols is very close to pFH.pszWords + pFH.cchWords * sizeof(WCHAR) CheckSetOffsets(pFH.pszSymbols, pFH.cchSymbols * Helpers._sizeOfChar, ref ullStartOffset, pFH.ulTotalSerializedSize); //Check the rule offset if (pFH.cRules > 0) { CheckSetOffsets(pFH.pRules, pFH.cRules * Marshal.SizeOf <CfgRule>(), ref ullStartOffset, pFH.ulTotalSerializedSize); } //Check the arc offset if (pFH.cArcs > 0) { CheckSetOffsets(pFH.pArcs, pFH.cArcs * Marshal.SizeOf <CfgArc>(), ref ullStartOffset, pFH.ulTotalSerializedSize); } //Check the weight offset if (pFH.pWeights > 0) { CheckSetOffsets(pFH.pWeights, pFH.cArcs * sizeof(float), ref ullStartOffset, pFH.ulTotalSerializedSize); } //Check the semantic tag offset if (pFH.cTags > 0) { CheckSetOffsets(pFH.tags, pFH.cTags * Marshal.SizeOf <CfgSemanticTag>(), ref ullStartOffset, pFH.ulTotalSerializedSize); if (includeAllGrammarData) { //Validate the SPCFGSEMANTICTAG array pointed to by tags //We use header for easy array access //The first arc is dummy, so the start and end arcindex for semantic tag won't be zero for (int i = 0; i < header.tags.Length; i++) { int startArc = (int)header.tags[i].StartArcIndex; int endArc = (int)header.tags[i].EndArcIndex; int cArcs = header.arcs.Length; #pragma warning disable 0618 // VarEnum is obsolete if (startArc == 0 || startArc >= cArcs || endArc == 0 || endArc >= cArcs || ( header.tags[i].PropVariantType != VarEnum.VT_EMPTY && header.tags[i].PropVariantType != VarEnum.VT_BSTR && header.tags[i].PropVariantType != VarEnum.VT_BOOL && header.tags[i].PropVariantType != VarEnum.VT_R8 && header.tags[i].PropVariantType != VarEnum.VT_I4) ) { XmlParser.ThrowSrgsException(SRID.UnsupportedFormat); } #pragma warning restore 0618 } } } //Check the offset for the scripts if (pFH.cScripts > 0) { CheckSetOffsets(pFH.pScripts, pFH.cScripts * Marshal.SizeOf <CfgScriptRef>(), ref ullStartOffset, pFH.ulTotalSerializedSize); } if (pFH.cIL > 0) { CheckSetOffsets(pFH.pIL, pFH.cIL * sizeof(byte), ref ullStartOffset, pFH.ulTotalSerializedSize); } if (pFH.cPDB > 0) { CheckSetOffsets(pFH.pPDB, pFH.cPDB * sizeof(byte), ref ullStartOffset, pFH.ulTotalSerializedSize); } }
internal static CfgHeader ConvertCfgHeader(StreamMarshaler streamHelper, bool includeAllGrammarData, bool loadSymbols, out CfgSerializedHeader cfgSerializedHeader) { cfgSerializedHeader = new CfgSerializedHeader(streamHelper.Stream); // // Because in 64-bit code, pointers != sizeof(ULONG) we copy each member explicitly. // CfgHeader header = new(); header.FormatId = cfgSerializedHeader.FormatId; header.GrammarGUID = cfgSerializedHeader.GrammarGUID; header.langId = cfgSerializedHeader.LangID; header.pszGlobalTags = cfgSerializedHeader.pszSemanticInterpretationGlobals; header.cArcsInLargestState = cfgSerializedHeader.cArcsInLargestState; // read all the common fields header.rules = Load <CfgRule>(streamHelper, cfgSerializedHeader.pRules, cfgSerializedHeader.cRules); if (includeAllGrammarData || loadSymbols) { header.pszSymbols = LoadStringBlob(streamHelper, cfgSerializedHeader.pszSymbols, cfgSerializedHeader.cchSymbols); } if (includeAllGrammarData) { header.pszWords = LoadStringBlob(streamHelper, cfgSerializedHeader.pszWords, cfgSerializedHeader.cchWords); header.arcs = Load <CfgArc>(streamHelper, cfgSerializedHeader.pArcs, cfgSerializedHeader.cArcs); header.tags = Load <CfgSemanticTag>(streamHelper, cfgSerializedHeader.tags, cfgSerializedHeader.cTags); header.weights = Load <float>(streamHelper, cfgSerializedHeader.pWeights, cfgSerializedHeader.cArcs); } //We know that in SAPI 5.0 grammar format pszWords follows header immediately. if (cfgSerializedHeader.pszWords < Marshal.SizeOf <CfgSerializedHeader>()) { //This is SAPI 5.0 and SAPI 5.1 grammar format header.ulRootRuleIndex = 0xFFFFFFFF; header.GrammarOptions = GrammarOptions.KeyValuePairs; header.BasePath = null; header.GrammarMode = GrammarType.VoiceGrammar; } else { //This is SAPI 5.2 and beyond grammar format header.ulRootRuleIndex = cfgSerializedHeader.ulRootRuleIndex; header.GrammarOptions = cfgSerializedHeader.GrammarOptions; header.GrammarMode = (GrammarType)cfgSerializedHeader.GrammarMode; if (includeAllGrammarData) { header.scripts = Load <CfgScriptRef>(streamHelper, cfgSerializedHeader.pScripts, cfgSerializedHeader.cScripts); } // The BasePath string is written after the rules - no offset is provided // Get the chars and build the string if (cfgSerializedHeader.cBasePath > 0) { streamHelper.Stream.Position = (int)cfgSerializedHeader.pRules + (header.rules.Length * Marshal.SizeOf <CfgRule>()); header.BasePath = streamHelper.ReadNullTerminatedString(); } } // Check the content - should be valid for both SAPI 5.0 and SAPI 5.2 grammars CheckValidCfgFormat(cfgSerializedHeader, header, includeAllGrammarData); return(header); }
// // This helper converts a serialized CFG grammar header into an in-memory header // internal static CfgHeader ConvertCfgHeader(StreamMarshaler streamHelper) { CfgSerializedHeader cfgSerializedHeader = null; return(ConvertCfgHeader(streamHelper, true, true, out cfgSerializedHeader)); }