/*++ Copyright (c) 1992 Microsoft Corporation Module Name: instutil.c Abstract: Common code for INSTALER.EXE, DISPINST.EXE, COMPINST.EXE and UNDOINST.EXE Author: Steve Wood (stevewo) 14-Jan-1996 Revision History: --*/ #include "instutil.h" #include "iml.h" LPSTR SavedModuleName; LPSTR SavedModuleUsage1; LPSTR SavedModuleUsage2; WCHAR AltTempFilePathBuffer[ MAX_PATH ]; PWSTR AltTempFilePathFileName; WCHAR TempFilePathBuffer[ MAX_PATH ]; PWSTR TempFilePathFileName; USHORT TempFileNextUniqueId; BOOL WINAPI CtrlCHandler( ULONG CtrlType ) { // // Ignore control C interrupts. Let child process deal with them // if it wants. If it doesn't then it will terminate and we will // get control and terminate ourselves // return TRUE; } void InitCommonCode( LPSTR ModuleName, LPSTR ModuleUsage1, LPSTR ModuleUsage2 ) { SavedModuleName = ModuleName; SavedModuleUsage1 = ModuleUsage1; SavedModuleUsage2 = ModuleUsage2; GetTempPath( sizeof( TempFilePathBuffer ) / sizeof( WCHAR ), TempFilePathBuffer ); TempFilePathFileName = TempFilePathBuffer + wcslen( TempFilePathBuffer ); TempFileNextUniqueId = (USHORT)0x0001; InstalerDirectory[ 0 ] = UNICODE_NULL; return; } void DisplayIndentedString( ULONG IndentAmount, PCHAR sBegin ) { PCHAR sEnd; while (sBegin != NULL) { sEnd = sBegin; while (*sEnd && *sEnd != '\n') { sEnd += 1; } fprintf( stderr, "%.*s%.*s\n", IndentAmount, " ", sEnd - sBegin, sBegin ); if (*sEnd == '\0') { break; } else { sBegin = ++sEnd; } } return; } void Usage( LPSTR Message, ULONG MessageParameter ) { ULONG n; LPSTR sBegin, sEnd; n = fprintf( stderr, "usage: %s ", SavedModuleName ); fprintf( stderr, "InstallationName\n" ); DisplayIndentedString( n, SavedModuleUsage1 ); fprintf( stderr, "\n" ); n = fprintf( stderr, "where: " ); fprintf( stderr, "InstallationName specifies a name for the installation. This is a required parameter.\n" ); DisplayIndentedString( n, "-? Displays this message." ); fprintf( stderr, "\n" ); DisplayIndentedString( n, SavedModuleUsage2 ); if (Message != NULL) { fprintf( stderr, "\n" ); } // // No return from FatalError // FatalError( Message, MessageParameter, 0 ); } void FatalError( LPSTR Message, ULONG MessageParameter1, ULONG MessageParameter2 ) { if (Message != NULL) { fprintf( stderr, "%s: ", SavedModuleName ); fprintf( stderr, Message, MessageParameter1, MessageParameter2 ); fprintf( stderr, "\n" ); } exit( 1 ); } PWSTR GetArgAsUnicode( LPSTR s ) { ULONG n; PWSTR ps; n = strlen( s ); ps = HeapAlloc( GetProcessHeap(), 0, (n + 1) * sizeof( WCHAR ) ); if (ps == NULL) { FatalError( "Out of memory", 0, 0 ); } if (MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, s, n, ps, n ) != (LONG)n ) { FatalError( "Unable to convert parameter '%s' to Unicode (%u)", (ULONG)s, GetLastError() ); } ps[ n ] = UNICODE_NULL; return ps; } void CommonSwitchProcessing( PULONG argc, PCHAR **argv, CHAR c ) { DWORD dwFileAttributes; PWSTR s; switch( c = (CHAR)tolower( c ) ) { case 'd': DebugOutput = TRUE; break; case '?': Usage( NULL, 0 ); break; default: Usage( "Invalid switch (-%c)", (ULONG)c ); break; } return; } BOOLEAN CommonArgProcessing( PULONG argc, PCHAR **argv ) { PWSTR s; if (InstallationName == NULL) { if (GetCurrentDirectory( MAX_PATH, InstalerDirectory ) != 0) { s = wcschr( InstalerDirectory, UNICODE_NULL ); if (s && s > InstalerDirectory && s[-1] != L'\\') { *s++ = L'\\'; *s = UNICODE_NULL; } InstallationName = GetArgAsUnicode( **argv ); ImlPath = FormatImlPath( InstalerDirectory, InstallationName ); return TRUE; } } return FALSE; } PWSTR FormatTempFileName( PWSTR Directory, PUSHORT TempFileUniqueId ) { ULONG remainingLen; if (*TempFileUniqueId == 0) { *TempFileUniqueId = (USHORT)(TempFileNextUniqueId++); if (TempFileNextUniqueId == 0) { return NULL; } } else if (*TempFileUniqueId == 0xFFFF) { return NULL; } if (Directory != NULL) { GetFullPathName( Directory, MAX_PATH, AltTempFilePathBuffer, &AltTempFilePathFileName ); AltTempFilePathFileName = wcsrchr( AltTempFilePathBuffer, TEXT('\\') ); if (NULL == AltTempFilePathFileName) { return NULL; } AltTempFilePathFileName += 1; // // Calculate how much space we have left // remainingLen = MAX_PATH - 1 - (AltTempFilePathFileName - AltTempFilePathBuffer); _snwprintf( AltTempFilePathFileName, remainingLen, L"~INS%04x.TMP", *TempFileUniqueId ); return AltTempFilePathBuffer; } else { if (TempFilePathFileName < TempFilePathBuffer || TempFilePathFileName >= TempFilePathBuffer + MAX_PATH) { return NULL; } remainingLen = MAX_PATH - 1 - (TempFilePathFileName - TempFilePathBuffer); _snwprintf( TempFilePathFileName, remainingLen, L"~INS%04x.TMP", *TempFileUniqueId ); return TempFilePathBuffer; } } PWSTR CreateBackupFileName( PUSHORT TempFileUniqueId ) { PWSTR BackupFileName; while (BackupFileName = FormatTempFileName( NULL, TempFileUniqueId )) { if (GetFileAttributesW( BackupFileName ) == 0xFFFFFFFF) { break; } else { *TempFileUniqueId = 0; // Temp file name existed, try next unique id } } return BackupFileName; } UCHAR EnumTypeBuffer0[ 512 ]; UCHAR EnumTypeBuffer1[ 512 ]; UCHAR EnumTypeBuffer2[ 512 ]; UCHAR EnumTypeBuffer3[ 512 ]; LPSTR EnumTypeBuffers[ 4 ] = { EnumTypeBuffer0, EnumTypeBuffer1, EnumTypeBuffer2, EnumTypeBuffer3 }; LPSTR FormatEnumType( ULONG BufferIndex, PENUM_TYPE_NAMES Table, ULONG Value, BOOLEAN FlagFormat ) { LPSTR s, FlagsBuffer = EnumTypeBuffers[ BufferIndex ]; ULONG remainingLen; // // 02/19/2002 - BogdanA - make some calculations so // we do not overflow the static buffers... // remainingLen = sizeof(FlagsBuffer)/sizeof(FlagsBuffer[0]) - 1; FlagsBuffer[ 0 ] = '\0'; FlagsBuffer[remainingLen] = 0; while (Table->Value != 0xFFFFFFFF) { if (FlagFormat) { if (Table->Value & Value) { if (FlagsBuffer[ 0 ] != '\0') { // // Check that we can still add stuff... // if (remainingLen < strlen(" | ")) { return FlagsBuffer; } remainingLen -= strlen(" | "); strcat( FlagsBuffer, " | " ); } if (remainingLen < strlen(Table->Name)) { return FlagsBuffer; } remainingLen -= strlen(Table->Name); strcat( FlagsBuffer, Table->Name ); Value &= ~Table->Value; if (Value == 0) { return FlagsBuffer; } } } else if (Table->Value == Value) { if (Value == 0) { if (!strcmp( Table->Name, "STATUS_WAIT_0" )) { return "STATUS_SUCCESS"; } else if (!strcmp( Table->Name, "ERROR_SUCCESS" )) { return "NO_ERROR"; } } return Table->Name; } Table += 1; } s = FlagsBuffer; // // remainingLen should be computed above, use it here again // if (FlagFormat) { if (s[ 0 ] != '\0') { if (remainingLen < strlen(" | ")) { return FlagsBuffer; } remainingLen -= strlen(" | "); strcat( s, " | " ); s += strlen( s ); } } _snprintf( s, remainingLen, Table->Name ? Table->Name : "%x", Value ); return FlagsBuffer; } ENUM_TYPE_NAMES ValueDataTypeNames[] = { REG_NONE, "REG_NONE", REG_SZ, "REG_SZ", REG_EXPAND_SZ, "REG_EXPAND_SZ", REG_BINARY, "REG_BINARY", REG_DWORD, "REG_DWORD", REG_DWORD_BIG_ENDIAN, "REG_DWORD_BIG_ENDIAN", REG_LINK, "REG_LINK", REG_MULTI_SZ, "REG_MULTI_SZ", REG_RESOURCE_LIST, "REG_RESOURCE_LIST", REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR", REG_RESOURCE_REQUIREMENTS_LIST,"REG_RESOURCE_REQUIREMENTS_LIST", 0xFFFFFFFF, "%x" };