/*++ Copyright (c) 2000 Microsoft Corporation Module Name: app.c Abstract: Implements a set of functions to manage data for an application section. Author: Jim Schmidt (jimschm) 05-Jun-2000 Revision History: --*/ // // Includes // #include "pch.h" #include "v1p.h" #define DBG_FOO "Foo" // // Strings // // None // // Constants // #define MAX_EXPANDED_STRING 4096 // // Macros // // None // // Types // // None // // Globals // PMHANDLE g_AppPool; extern BOOL g_VcmMode; // in sgmqueue.c GROWLIST g_SectionStack = INIT_GROWLIST; // // Macro expansion list // // None // // Private function prototypes // BOOL pParseAppEnvSection ( IN MIG_PLATFORMTYPEID Platform, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ); // // Macro expansion definition // // None // // Code // VOID InitAppModule ( VOID ) { g_AppPool = PmCreateNamedPool ("v1 App"); } VOID TerminateAppModule ( VOID ) { PmDestroyPool (g_AppPool); INVALID_POINTER (g_AppPool); } UINT pSafeTcharCount ( IN PCTSTR String ) { if (String) { return TcharCount (String); } return 0; } PCTSTR GetMostSpecificSection ( IN MIG_PLATFORMTYPEID Platform, IN PINFSTRUCT InfStruct, IN HINF InfFile, IN PCTSTR BaseSection ) { PTSTR specificSection; MIG_OSVERSIONINFO versionInfo; UINT tchars; if (!IsmGetOsVersionInfo (Platform, &versionInfo)) { return NULL; } tchars = TcharCount (BaseSection) + 1; tchars += pSafeTcharCount (versionInfo.OsTypeName) + 1; tchars += pSafeTcharCount (versionInfo.OsMajorVersionName) + 1; tchars += pSafeTcharCount (versionInfo.OsMinorVersionName) + 1; specificSection = AllocText (tchars); if (versionInfo.OsTypeName && versionInfo.OsMajorVersionName && versionInfo.OsMinorVersionName ) { wsprintf ( specificSection, TEXT("%s.%s.%s.%s"), BaseSection, versionInfo.OsTypeName, versionInfo.OsMajorVersionName, versionInfo.OsMinorVersionName ); if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) { return specificSection; } } if (versionInfo.OsTypeName && versionInfo.OsMajorVersionName ) { wsprintf ( specificSection, TEXT("%s.%s.%s"), BaseSection, versionInfo.OsTypeName, versionInfo.OsMajorVersionName ); if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) { return specificSection; } } if (versionInfo.OsTypeName) { wsprintf ( specificSection, TEXT("%s.%s"), BaseSection, versionInfo.OsTypeName ); if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) { return specificSection; } } FreeText (specificSection); return NULL; } BOOL pCheckForRecursion ( IN PCTSTR Section ) { UINT count; UINT u; count = GlGetSize (&g_SectionStack); for (u = 0 ; u < count ; u++) { if (StringIMatch (GlGetString (&g_SectionStack, u), Section)) { return TRUE; } } return FALSE; } VOID pPushSection ( IN PCTSTR Section ) { GlAppendString (&g_SectionStack, Section); } VOID pPopSection ( IN PCTSTR Section ) { UINT u; u = GlGetSize (&g_SectionStack); while (u > 0) { u--; if (StringIMatch (GlGetString (&g_SectionStack, u), Section)) { GlDeleteItem (&g_SectionStack, u); return; } } MYASSERT (FALSE); } UINT pGetDisplayTypeFromString ( IN PCTSTR String ) { if (!String) { return 0; } if (StringIMatch (String, TEXT("EXT"))) { return COMPONENT_EXTENSION; } if (StringIMatch (String, TEXT("FILE"))) { return COMPONENT_FILE; } if (StringIMatch (String, TEXT("DIR"))) { return COMPONENT_FOLDER; } return 0; } BOOL pAddFilesAndFoldersComponent ( IN PCTSTR ComponentString, OPTIONAL IN PCTSTR TypeString, IN PCTSTR MultiSz, IN UINT MasterGroup, IN OUT PBOOL MarkAsPreferred ) { MULTISZ_ENUM e; TCHAR expandBuffer[MAX_PATH]; UINT displayType; displayType = pGetDisplayTypeFromString (TypeString); if (!displayType) { LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_FNF_TYPE, TypeString)); return TRUE; } if (EnumFirstMultiSz (&e, MultiSz)) { do { // // Expand e.CurrentString // MappingSearchAndReplaceEx ( g_EnvMap, e.CurrentString, expandBuffer, 0, NULL, ARRAYSIZE(expandBuffer), 0, NULL, NULL ); // // Add component // IsmAddComponentAlias ( ComponentString, MasterGroup, expandBuffer, displayType, FALSE ); if (ComponentString && *MarkAsPreferred) { IsmSelectPreferredAlias (ComponentString, expandBuffer, displayType); *MarkAsPreferred = FALSE; } } while (EnumNextMultiSz (&e)); } else { LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_FNF_SPEC, TypeString)); } return TRUE; } BOOL pAddFilesAndFoldersSection ( IN HINF InfFile, IN PCTSTR Section, IN UINT MasterGroup, IN BOOL GroupAllUnderSection, IN PBOOL MarkAsPreferred ) { INFSTRUCT is = INITINFSTRUCT_PMHANDLE; PCTSTR type; PCTSTR multiSz; BOOL result = TRUE; PCTSTR decoratedSection = NULL; if (GroupAllUnderSection) { decoratedSection = JoinText (TEXT("$"), Section); } if (InfFindFirstLine (InfFile, Section, NULL, &is)) { do { InfResetInfStruct (&is); type = InfGetStringField (&is, 1); multiSz = InfGetMultiSzField (&is, 2); result = pAddFilesAndFoldersComponent ( decoratedSection, type, multiSz, MasterGroup, MarkAsPreferred ); } while (result && InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); FreeText (decoratedSection); if (!result) { LOG ((LOG_ERROR, (PCSTR) MSG_SECTION_ERROR, Section)); } return result; } BOOL pAddFilesAndFoldersComponentOrSection ( IN HINF InfFile, IN PCTSTR ComponentString, OPTIONAL IN PCTSTR TypeString, IN PCTSTR MultiSz, IN UINT MasterGroup, IN PBOOL MarkAsPreferred ) { MULTISZ_ENUM e; BOOL result = TRUE; if (StringIMatch (TypeString, TEXT("Section"))) { if (EnumFirstMultiSz (&e, MultiSz)) { do { result = pAddFilesAndFoldersSection (InfFile, e.CurrentString, MasterGroup, TRUE, MarkAsPreferred); } while (result && EnumNextMultiSz (&e)); } } else { result = pAddFilesAndFoldersComponent (ComponentString, TypeString, MultiSz, MasterGroup, MarkAsPreferred); } return result; } BOOL AddAppSpecificEnvVar ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR AppTag, IN PCTSTR VariableName, IN PCTSTR VariableData OPTIONAL ) { PTSTR buffer; PTSTR p; PTSTR q; BOOL ignoreLastPercent = FALSE; PCTSTR undefText; // // Verify VariableName is legal // if (_tcsnextc (VariableName) == TEXT('%')) { VariableName++; ignoreLastPercent = TRUE; } if (*VariableName == 0) { LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_APP_ENV_VAR)); return FALSE; } // // Transfer VariableName into %% // buffer = AllocText (SizeOfString (VariableName) + 2); MYASSERT (buffer); if (!buffer) { return FALSE; } p = buffer; *p++ = TEXT('%'); *p = 0; p = StringCat (p, VariableName); if (ignoreLastPercent) { q = _tcsdec (buffer, p); if (q) { if (_tcsnextc (q) == TEXT('%')) { p = q; } } } *p++ = TEXT('%'); *p = 0; // // Add %% -> VariableData to string mapping table // if (VariableData) { // let's check to see if this was already defined. If yes, we will log a warning // but we will still set the env variable if (IsmGetEnvironmentString (Platform, S_SYSENVVAR_GROUP, VariableName, NULL, 0, NULL)) { LOG ((LOG_INFORMATION, (PCSTR) MSG_DUPLICATE_ENV_VAR, buffer)); } if (Platform == PLATFORM_SOURCE) { IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, VariableName, VariableData); AddStringMappingPair (g_EnvMap, buffer, VariableData); } else { IsmSetEnvironmentString (PLATFORM_DESTINATION, S_SYSENVVAR_GROUP, VariableName, VariableData); AddRemappingEnvVar (g_DestEnvMap, g_FileNodeFilterMap, NULL, VariableName, VariableData); } } else { // let's check to see if this was previously defined if (!IsmGetEnvironmentString (Platform, S_SYSENVVAR_GROUP, VariableName, NULL, 0, NULL)) { LOG ((LOG_INFORMATION, (PCSTR) MSG_UNDEF_APP_VAR, buffer)); undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), buffer, 0, NULL); AddStringMappingPair (g_UndefMap, buffer, undefText); FreeText (undefText); } } FreeText (buffer); return TRUE; } BOOL AppCheckAndLogUndefVariables ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Application, IN PCTSTR UnexpandedString ) { TCHAR buffer[MAX_TCHAR_PATH * 4]; PMAPSTRUCT mapArray[1]; UINT mapCount = 0; BOOL updated; mapArray[mapCount] = g_UndefMap; updated = MappingMultiTableSearchAndReplaceEx ( mapArray, mapCount + 1, UnexpandedString, buffer, 0, NULL, ARRAYSIZE(buffer), 0, NULL, NULL ); if (updated) { if (buffer [0]) { LOG ((LOG_INFORMATION, (PCSTR) MSG_UNDEF_BUT_GOOD_VAR, buffer)); } } else { if (buffer [0]) { LOG ((LOG_INFORMATION, (PCSTR) MSG_ENV_VAR_COULD_BE_BAD, buffer)); } } return updated; } BOOL AppSearchAndReplace ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Application, IN PCTSTR UnexpandedString, OUT PTSTR ExpandedString, IN UINT ExpandedStringTchars ) { PMAPSTRUCT mapArray[1]; UINT mapCount = 0; BOOL updated; PCTSTR newString = NULL; PCTSTR percent; PCTSTR endPercent; PCTSTR equals; BOOL result = TRUE; // // Let's expand the incoming string by using the source machine defined environment variables. // newString = IsmExpandEnvironmentString (Platform, S_SYSENVVAR_GROUP, UnexpandedString, NULL); if (Platform == PLATFORM_SOURCE) { mapArray[mapCount] = g_EnvMap; } else { MYASSERT (Platform == PLATFORM_DESTINATION); mapArray[mapCount] = g_DestEnvMap; } updated = MappingMultiTableSearchAndReplaceEx ( mapArray, mapCount + 1, newString, ExpandedString, 0, NULL, ExpandedStringTchars, 0, NULL, NULL ); if (newString) { IsmReleaseMemory (newString); newString = NULL; } // // Alert the user to an unexpanded environment variable // if (!updated) { percent = ExpandedString; do { percent = _tcschr (percent, TEXT('%')); if (percent) { percent = _tcsinc (percent); endPercent = _tcschr (percent, TEXT('%')); if (endPercent > percent) { equals = percent; while (equals < endPercent) { if (_tcsnextc (equals) == TEXT('=')) { break; } equals = _tcsinc (equals); } if (equals >= endPercent) { result = FALSE; break; } } } } while (percent && endPercent); } return result; } BOOL pGetDataFromObjectSpec ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Application, IN PCTSTR InfObjectType, IN PCTSTR InfObjectName, IN PCTSTR ArgumentMultiSz, OPTIONAL OUT PTSTR OutContentBuffer, OPTIONAL IN UINT OutContentBufferTchars, OUT PBOOL TestResults OPTIONAL ) { ATTRIB_DATA attribData; BOOL test; MYASSERT (Application); MYASSERT (InfObjectType); MYASSERT (InfObjectName); ZeroMemory (&attribData, sizeof (ATTRIB_DATA)); attribData.Platform = Platform; attribData.ScriptSpecifiedType = InfObjectType; attribData.ScriptSpecifiedObject = InfObjectName; attribData.ApplicationName = Application; if (AllocScriptType (&attribData)) { if (g_VcmMode && attribData.ObjectName) { if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) { IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName); } } if (attribData.ReturnString) { if (OutContentBuffer) { StringCopyTcharCount ( OutContentBuffer, attribData.ReturnString, OutContentBufferTchars ); } } if (TestResults) { if (ArgumentMultiSz) { test = TestAttributes (g_AppPool, ArgumentMultiSz, &attribData); } else { test = (attribData.ReturnString != NULL); } *TestResults = test; } FreeScriptType (&attribData); } else { return FALSE; } return TRUE; } VOID pAddPlatformEnvVar ( IN HINF InfFile, IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Application, IN PCTSTR Section, IN PCTSTR Variable, IN PCTSTR Type, IN PCTSTR Data, IN PCTSTR ArgMultiSz, IN PINFSTRUCT InfStruct ) { MIG_OBJECTSTRINGHANDLE objectName; MIG_OBJECTSTRINGHANDLE objectNameLong; PCTSTR nativeNameLong; BOOL exists; BOOL validString; PCTSTR p; PCTSTR end; TCHAR variableData[MAX_PATH + 1]; PCTSTR varDataLong = NULL; ZeroMemory (&variableData, sizeof (variableData)); // // Variable data is specified in the object represented by // if (!pGetDataFromObjectSpec ( Platform, Application, Type, Data, ArgMultiSz, variableData, ARRAYSIZE(variableData) - 1, &exists )) { switch (GetLastError()) { case ERROR_INVALID_DATA: LOG (( LOG_WARNING, (PCSTR) MSG_DETECT_DATA_OBJECT_IS_BAD, Data, Variable )); InfLogContext (LOG_WARNING, InfFile, InfStruct); break; case ERROR_INVALID_DATATYPE: LOG (( LOG_ERROR, (PCSTR) MSG_DETECT_DATA_TYPE_IS_BAD, Type, Variable )); InfLogContext (LOG_ERROR, InfFile, InfStruct); break; } } else { validString = FALSE; if (exists) { p = variableData; end = variableData + MAX_PATH; while (p < end) { if (_tcsnextc (p) < 32) { break; } p = _tcsinc (p); } if (*p == 0 && p < end && p > variableData) { validString = TRUE; } } if (validString) { varDataLong = variableData; if (IsValidFileSpec (variableData)) { // let's get the long file name for this. We need to call // ISM for this because we might be on the wrong platform // Unfortunately we don't know if this is a directory or // a file. We'll just assume it's a directory. ISM will // work fine either way. objectName = IsmCreateObjectHandle (variableData, NULL); if (objectName) { objectNameLong = IsmGetLongName (MIG_FILE_TYPE|Platform, objectName); if (objectNameLong) { nativeNameLong = IsmGetNativeObjectName (MIG_FILE_TYPE|Platform, objectNameLong); if (nativeNameLong) { varDataLong = DuplicatePathString (nativeNameLong, 0); IsmReleaseMemory (nativeNameLong); } IsmDestroyObjectHandle (objectNameLong); } IsmDestroyObjectHandle (objectName); } } } if (!validString && exists) { LOG ((LOG_INFORMATION, (PCSTR) MSG_DATA_IS_NOT_A_STRING, Variable)); } else { LOG_IF (( validString, LOG_INFORMATION, (PCSTR) MSG_APP_ENV_DEF_INFO, Variable, Type, Data, variableData )); LOG_IF (( !validString, LOG_INFORMATION, (PCSTR) MSG_NUL_APP_ENV_DEF_INFO, Variable, Type, Data )); AddAppSpecificEnvVar ( Platform, Application, Variable, validString ? varDataLong : NULL ); } if (varDataLong && (varDataLong != variableData)) { FreePathString (varDataLong); varDataLong = NULL; } } } PCTSTR pProcessArgEnvironmentVars ( IN MIG_PLATFORMTYPEID Platform, IN PCTSTR Application, IN PCTSTR Args, IN BOOL MultiSz, OUT PGROWBUFFER UpdatedData ) { MULTISZ_ENUM e; TCHAR buffer[MAX_EXPANDED_STRING]; UpdatedData->End = 0; if (MultiSz) { if (EnumFirstMultiSz (&e, Args)) { do { AppSearchAndReplace ( Platform, Application, e.CurrentString, buffer, MAX_EXPANDED_STRING ); GbMultiSzAppend (UpdatedData, buffer); } while (EnumNextMultiSz (&e)); } } else { AppSearchAndReplace ( Platform, Application, Args, buffer, MAX_EXPANDED_STRING ); GbMultiSzAppend (UpdatedData, buffer); } return (PCTSTR) UpdatedData->Buf; } BOOL pParseAppEnvSectionWorker ( IN MIG_PLATFORMTYPEID Platform, IN PINFSTRUCT InfStruct, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ) { BOOL result = FALSE; PCTSTR variable; PCTSTR type; PCTSTR data; PCTSTR args; PCTSTR updatedData; PCTSTR updatedArgs; PTSTR lastChar; GROWBUFFER dataBuf = INIT_GROWBUFFER; GROWBUFFER argBuf = INIT_GROWBUFFER; // // Section must not be on the stack // if (pCheckForRecursion (Section)) { LOG ((LOG_ERROR, (PCSTR) MSG_ENV_SECTION_RECURSION, Section)); // Assume success return TRUE; } // // Format is // // = , [, ] // // specifies one of the supported parse types (see parse.c), // or "Text" when is arbitrary text // // is specific to // // specify qualifiers. If they evaluate to FALSE, then // the variable is not set. // __try { if (InfFindFirstLine (InfFile, Section, NULL, InfStruct)) { do { if (IsmCheckCancel()) { __leave; } InfResetInfStruct (InfStruct); variable = InfGetStringField (InfStruct, 0); type = InfGetStringField (InfStruct, 1); if (variable && StringIMatch (variable, TEXT("ProcessSection"))) { if (type && *type) { pPushSection (Section); result = pParseAppEnvSection (Platform, InfFile, Application, type); pPopSection (Section); if (!result) { __leave; } continue; } } data = InfGetStringField (InfStruct, 2); args = InfGetMultiSzField (InfStruct, 3); if (variable) { // // Remove %s from the variable name // if (_tcsnextc (variable) == TEXT('%')) { lastChar = _tcsdec2 (variable, GetEndOfString (variable)); if (lastChar > variable && _tcsnextc (lastChar) == TEXT('%')) { variable = _tcsinc (variable); *lastChar = 0; } } } if (!variable || !(*variable) || !type || !(*type) || !data) { LOG ((LOG_WARNING, (PCSTR) MSG_GARBAGE_LINE_IN_INF, Section)); InfLogContext (LOG_WARNING, InfFile, InfStruct); continue; } // // Update all environment variables in data and args // updatedData = pProcessArgEnvironmentVars ( Platform, Application, data, FALSE, &dataBuf ); if (args && *args) { updatedArgs = pProcessArgEnvironmentVars ( Platform, Application, args, TRUE, &argBuf ); } else { updatedArgs = NULL; } // // Add the app-specific environment variables. If we are // on the destination, add both a source and destination // value (as they might be different). // pAddPlatformEnvVar ( InfFile, Platform, Application, Section, variable, type, updatedData, updatedArgs, InfStruct ); } while (InfFindNextLine (InfStruct)); } result = TRUE; } __finally { GbFree (&dataBuf); GbFree (&argBuf); } return result; } BOOL pParseAppEnvSection ( IN MIG_PLATFORMTYPEID Platform, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ) { PCTSTR osSpecificSection; BOOL b; INFSTRUCT is = INITINFSTRUCT_PMHANDLE; b = pParseAppEnvSectionWorker (Platform, &is, InfFile, Application, Section); if (b) { osSpecificSection = GetMostSpecificSection (Platform, &is, InfFile, Section); if (osSpecificSection) { b = pParseAppEnvSectionWorker (Platform, &is, InfFile, Application, osSpecificSection); FreeText (osSpecificSection); } } InfCleanUpInfStruct (&is); return b; } BOOL pParseAppDetectSectionPart ( IN MIG_PLATFORMTYPEID Platform, IN PINFSTRUCT InfStruct, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ) { BOOL result = TRUE; PCTSTR type; PCTSTR data; PCTSTR args; GROWBUFFER dataBuf = INIT_GROWBUFFER; GROWBUFFER argBuf = INIT_GROWBUFFER; PCTSTR updatedData; PCTSTR updatedArgs; PTSTR buffer; BOOL test; // // Section must not be on the stack // if (pCheckForRecursion (Section)) { LOG ((LOG_ERROR, (PCSTR) MSG_DETECT_SECTION_RECURSION, Section)); // Assume successful detection return TRUE; } // // Format is // // , [, ] // // specifies one of the supported parse types (see parse.c), // and may include environment variables specified in the // app's [App.Environment] section. // // is specific to . If begins with a !, then the // existence of the object fails the detect test // // specify qualifiers // __try { buffer = AllocText (MAX_EXPANDED_STRING); // arbitrary big text buffer if (InfFindFirstLine (InfFile, Section, NULL, InfStruct)) { do { if (IsmCheckCancel()) { __leave; } InfResetInfStruct (InfStruct); // // Obtain the line data // type = InfGetStringField (InfStruct, 0); if (type && StringIMatch (type, TEXT("ProcessSection"))) { data = InfGetStringField (InfStruct, 1); if (data && *data) { pPushSection (Section); result = ParseAppDetectSection (Platform, InfFile, Application, data); pPopSection (Section); continue; } } type = InfGetStringField (InfStruct, 1); data = InfGetStringField (InfStruct, 2); args = InfGetMultiSzField (InfStruct, 3); if (!type || !data) { LOG ((LOG_WARNING, (PCSTR) MSG_GARBAGE_LINE_IN_INF, Section)); InfLogContext (LOG_WARNING, InfFile, InfStruct); continue; } // // Update all environment variables in data and args // updatedData = pProcessArgEnvironmentVars ( PLATFORM_SOURCE, Application, data, FALSE, &dataBuf ); if (args && *args) { updatedArgs = pProcessArgEnvironmentVars ( PLATFORM_SOURCE, Application, args, TRUE, &argBuf ); } else { updatedArgs = NULL; } // // Now try to obtain the data // if (pGetDataFromObjectSpec ( Platform, Application, type, updatedData, updatedArgs, NULL, 0, &test )) { if (test) { LOG ((LOG_INFORMATION, (PCSTR) MSG_DETECT_INFO, type, updatedData)); } else { LOG ((LOG_INFORMATION, (PCSTR) MSG_NOT_DETECT_INFO, type, updatedData)); result = FALSE; break; } } else { result = FALSE; break; } } while (result && InfFindNextLine (InfStruct)); } } __finally { FreeText (buffer); GbFree (&dataBuf); GbFree (&argBuf); } return result; } BOOL pParseOsAppDetectSection ( IN MIG_PLATFORMTYPEID Platform, IN PINFSTRUCT InfStruct, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ) { PCTSTR osSpecificSection; BOOL b; b = pParseAppDetectSectionPart (Platform, InfStruct, InfFile, Application, Section); if (b) { osSpecificSection = GetMostSpecificSection (Platform, InfStruct, InfFile, Section); if (osSpecificSection) { b = pParseAppDetectSectionPart (Platform, InfStruct, InfFile, Application, osSpecificSection); FreeText (osSpecificSection); } } return b; } BOOL ParseAppDetectSection ( IN MIG_PLATFORMTYPEID Platform, IN HINF InfFile, IN PCTSTR Application, IN PCTSTR Section ) { INFSTRUCT is = INITINFSTRUCT_PMHANDLE; TCHAR number[32]; PCTSTR orSection; UINT count; BOOL orSectionProcessed = FALSE; BOOL detected = FALSE; BOOL done = FALSE; // // Process all "or" sections // count = 0; do { count++; wsprintf (number, TEXT(".%u"), count); orSection = JoinText (Section, number); if (orSection) { if (InfFindFirstLine (InfFile, orSection, NULL, &is)) { orSectionProcessed = TRUE; if (pParseOsAppDetectSection (Platform, &is, InfFile, Application, orSection)) { detected = TRUE; done = TRUE; } } else { done = TRUE; } FreeText (orSection); INVALID_POINTER (orSection); } else { done = TRUE; } } while (!done); // // If no "or" sections, process Section itself // if (!orSectionProcessed) { detected = pParseOsAppDetectSection (Platform, &is, InfFile, Application, Section); } InfCleanUpInfStruct (&is); return detected; } BOOL pDoesAppSectionExists ( IN MIG_PLATFORMTYPEID Platform, IN HINF InfFile, IN PCTSTR Application ) { PCTSTR osSpecificSection; BOOL b; INFSTRUCT is = INITINFSTRUCT_GROWBUFFER; b = InfFindFirstLine (InfFile, Application, NULL, &is); if (!b) { osSpecificSection = GetMostSpecificSection (Platform, &is, InfFile, Application); if (osSpecificSection) { b = TRUE; FreeText (osSpecificSection); } } InfCleanUpInfStruct (&is); return b; } BOOL pParseOneDestInstruction ( IN HINF InfHandle, IN PCTSTR Type, IN PCTSTR SectionMultiSz, IN PINFSTRUCT InfStruct, IN PCTSTR Application OPTIONAL ) { MULTISZ_ENUM e; BOOL result = TRUE; // // First thing: look for nested sections // if (StringIMatch (Type, TEXT("ProcessSection"))) { if (EnumFirstMultiSz (&e, SectionMultiSz)) { do { result = result & ParseOneApplication ( PLATFORM_DESTINATION, InfHandle, Application, FALSE, 0, e.CurrentString, NULL, NULL, NULL ); } while (EnumNextMultiSz (&e)); } return result; } return TRUE; } BOOL pParseDestInfInstructionsWorker ( IN PINFSTRUCT InfStruct, IN HINF InfHandle, IN PCTSTR Application, OPTIONAL IN PCTSTR Section ) { PCTSTR type; PCTSTR sections; GROWBUFFER multiSz = INIT_GROWBUFFER; BOOL result = TRUE; if (InfFindFirstLine (InfHandle, Section, NULL, InfStruct)) { do { if (IsmCheckCancel()) { result = FALSE; break; } InfResetInfStruct (InfStruct); type = InfGetStringField (InfStruct, 0); sections = InfGetMultiSzField (InfStruct, 1); if (!type || !sections) { LOG ((LOG_WARNING, (PCSTR) MSG_BAD_INF_LINE, Section)); InfLogContext (LOG_WARNING, InfHandle, InfStruct); continue; } result = pParseOneDestInstruction (InfHandle, type, sections, InfStruct, Application); } while (result && InfFindNextLine (InfStruct)); } InfCleanUpInfStruct (InfStruct); GbFree (&multiSz); return result; } BOOL ParseDestInfInstructions ( IN HINF InfHandle, IN PCTSTR Application, OPTIONAL IN PCTSTR Section ) { PCTSTR osSpecificSection; BOOL b; INFSTRUCT is = INITINFSTRUCT_PMHANDLE; PTSTR instrSection; b = pParseDestInfInstructionsWorker (&is, InfHandle, Application, Section); if (b) { osSpecificSection = GetMostSpecificSection (PLATFORM_SOURCE, &is, InfHandle, Section); if (osSpecificSection) { b = pParseDestInfInstructionsWorker (&is, InfHandle, Application, osSpecificSection); FreeText (osSpecificSection); } } InfCleanUpInfStruct (&is); return b; } BOOL ParseOneApplication ( IN MIG_PLATFORMTYPEID Platform, IN HINF Inf, IN PCTSTR Section, IN BOOL PreParse, IN UINT MasterGroup, IN PCTSTR Application, IN PCTSTR LocSection, IN PCTSTR AliasType, IN PCTSTR MultiSz ) { PCTSTR appSection = NULL; BOOL detected = FALSE; PCTSTR appEnvVar; PCTSTR decoratedSection; BOOL componentized = FALSE; BOOL executeSection = FALSE; BOOL markAsPreferred; __try { if (LocSection || AliasType) { componentized = TRUE; } else { componentized = FALSE; } if (!Application) { __leave; } decoratedSection = JoinText (TEXT("$"), Application); if (Platform == PLATFORM_SOURCE) { // // locSection exists for all applications we want to send to // the UI for approval. PreParse builds the list of apps we // send to the UI. Only do detection if this is PreParsing // localized apps, or not preparsing non-localized apps // if ((PreParse && componentized) || (!PreParse && !componentized) ) { appSection = JoinText (Application, TEXT(".Environment")); if (!pParseAppEnvSection (PLATFORM_SOURCE, Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; GlFree (&g_SectionStack); appSection = JoinText (Application, TEXT(".Detect")); detected = ParseAppDetectSection (Platform, Inf, Application, appSection); FreeText (appSection); appSection = NULL; GlFree (&g_SectionStack); if (!detected && pDoesAppSectionExists (Platform, Inf, Application)) { detected = TRUE; } else if (!detected) { LOG ((LOG_INFORMATION, (PCSTR) MSG_APP_NOT_DETECT_INFO, Application)); } else { LOG ((LOG_INFORMATION, (PCSTR) MSG_APP_DETECT_INFO, Application)); appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL); IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, appEnvVar); FreeText (appEnvVar); } if (componentized && detected) { // // we should put it in the selection list // if (LocSection) { IsmAddComponentAlias ( decoratedSection, MasterGroup, LocSection, COMPONENT_NAME, FALSE ); IsmSelectPreferredAlias (decoratedSection, LocSection, COMPONENT_NAME); } if (AliasType) { markAsPreferred = (LocSection == NULL); pAddFilesAndFoldersComponentOrSection ( Inf, decoratedSection, AliasType, MultiSz, MasterGroup, &markAsPreferred ); } } executeSection = (!PreParse) && detected; } else { executeSection = (!PreParse) && IsmIsComponentSelected (decoratedSection, 0); } // Now actually load the application instructions if it's not preparsing if (executeSection) { appSection = DuplicateText (Application); if (!ParseInfInstructions (Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL); if (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, appEnvVar)) { appSection = JoinText (Application, TEXT(".Instructions")); if (!ParseInfInstructions (Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; } FreeText (appEnvVar); } else { if (!PreParse) { appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL); IsmDeleteEnvironmentVariable (PLATFORM_SOURCE, NULL, appEnvVar); FreeText (appEnvVar); } } } else { MYASSERT (Platform == PLATFORM_DESTINATION); appSection = JoinText (Application, TEXT(".Environment")); if (!pParseAppEnvSection (PLATFORM_DESTINATION, Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; GlFree (&g_SectionStack); appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL); if (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, appEnvVar)) { appSection = DuplicateText (Application); if (!ParseDestInfInstructions (Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; appSection = JoinText (Application, TEXT(".Instructions")); if (!ParseDestInfInstructions (Inf, Application, appSection)) { __leave; } FreeText (appSection); appSection = NULL; } FreeText (appEnvVar); } FreeText (decoratedSection); decoratedSection = NULL; } __finally { if (appSection) { FreeText (appSection); appSection = NULL; } GlFree (&g_SectionStack); } return TRUE; } BOOL ParseApplications ( IN MIG_PLATFORMTYPEID Platform, IN HINF Inf, IN PCTSTR Section, IN BOOL PreParse, IN UINT MasterGroup ) { INFSTRUCT is = INITINFSTRUCT_PMHANDLE; PCTSTR application; BOOL result = FALSE; PCTSTR locSection; PCTSTR aliasType; PCTSTR multiSz; __try { if (InfFindFirstLine (Inf, Section, NULL, &is)) { do { if (IsmCheckCancel()) { __leave; } InfResetInfStruct (&is); application = InfGetStringField (&is, 1); locSection = InfGetStringField (&is, 2); aliasType = InfGetStringField (&is, 3); multiSz = InfGetMultiSzField (&is, 4); if (application && !application[0]) { application = NULL; } if (locSection && !locSection[0]) { locSection = NULL; } if (aliasType && !aliasType[0]) { aliasType = NULL; } if (multiSz && !multiSz[0]) { multiSz = NULL; } if (!aliasType || !multiSz) { aliasType = NULL; multiSz = NULL; } ParseOneApplication ( Platform, Inf, Section, PreParse, MasterGroup, application, locSection, aliasType, multiSz ); } while (InfFindNextLine (&is)); } result = TRUE; } __finally { InfCleanUpInfStruct (&is); } return result; } BOOL ProcessFilesAndFolders ( IN HINF InfHandle, IN PCTSTR Section, IN BOOL PreParse ) { BOOL b = TRUE; BOOL markAsPreferred = TRUE; if (PreParse) { b = pAddFilesAndFoldersSection (InfHandle, Section, MASTERGROUP_FILES_AND_FOLDERS, FALSE, &markAsPreferred); } return b; }