/*++ Copyright (c) 1997 Microsoft Corporation Module Name: utils.c Abstract: Contains some functions used by all modules. Author: Bogdan Andreiu (bogdana) 10-Feb-1997 Jason Allor (jasonall) 24-Feb-1998 (took over the project) Revision History: 10-Feb-1997 bogdana First draft: the greatest part of the functions 20_Feb-1997 bogdana Added three multistring processing functions 19-Mar-1997 bogdana Added LogLine and modified LogOCFunction 12-Apr-1997 bogdana Modified the multistring processing routines --*/ #include "octest.h" /*++ Routine Description: (3.1) Logs information about the OC Function received from the OC Manager Arguments: lpcvComponentId: the name of the component (PVOID because it might be ANSI or Unicode) lpcvSubcomponentId: the subcomponent's name (NULL if none) uiFunction: one of OC_XXX functions uiParam1: the first param of the call pvParam2: the second param of the call Return Value: void --*/ VOID LogOCFunction(IN LPCVOID lpcvComponentId, IN LPCVOID lpcvSubcomponentId, IN UINT uiFunction, IN UINT uiParam1, IN PVOID pvParam2) { double fn = 3.1; UINT uiCount; TCHAR tszMsg[MAX_MSG_LEN]; WCHAR wszFromANSI[MAX_MSG_LEN]; CHAR cszFromUnicode[MAX_MSG_LEN]; DWORD dwEndVariation; PSETUP_INIT_COMPONENT psicInitComp; SYSTEMTIME st; // // Don't log OC_PRIVATE_BASE calls. There are too many of them // and they just clutter up the log. Failures will still be logged. // if (uiFunction >= OC_PRIVATE_BASE) return; // // Display the current time. This is a way of checking if the // notifications are received in the proper sequence. // GetLocalTime(&st); _stprintf (tszMsg, TEXT("[%02.2d:%02.2d:%02.2d] "), (INT)st.wHour, (INT)st.wMinute, (INT)st.wSecond); // // The second line contains the function and the return value // for (uiCount = 0; uiCount < MAX_OC_FUNCTIONS; uiCount++) { if (octFunctionNames[uiCount].uiOCFunction == uiFunction) { _stprintf(tszMsg, TEXT("%s %s"), tszMsg, octFunctionNames[uiCount].tszOCText); break; } } Log(fn, INFO, TEXT("-----------------------------------")); LogBlankLine(); Log(fn, INFO, tszMsg); if (uiFunction != OC_PREINITIALIZE) { if (!lpcvComponentId || _tcscmp((PTSTR)lpcvComponentId, TEXT("")) == 0) { _stprintf(tszMsg, TEXT("Component = (null) ")); } else { _stprintf(tszMsg, TEXT("Component = %s "), (PTSTR)lpcvComponentId); } if (!lpcvSubcomponentId || _tcscmp((PTSTR)lpcvSubcomponentId, TEXT("")) == 0) { _stprintf(tszMsg, TEXT("%sSubcomponent = (null)"), tszMsg); } else { _stprintf(tszMsg, TEXT("%sSubcomponent = %s"), tszMsg, (PTSTR)lpcvSubcomponentId); } } else { // // The SubcomponentId should be the non-native version, // if it is supported by the OC Manager // #ifdef UNICODE if (uiParam1 & OCFLAG_UNICODE) { // // The ComponentId is Unicode // if (uiParam1 & OCFLAG_ANSI) { // // The second param is ANSI, convert to Unicode for // printing it // mbstowcs(wszFromANSI, (PCHAR)lpcvSubcomponentId, strlen((PCHAR)lpcvSubcomponentId)); wszFromANSI[strlen((PCHAR)lpcvSubcomponentId)] = L'\0'; } else { // // Nothing to do if ANSI not supported // wszFromANSI[0] = TEXT('\0'); } _stprintf(tszMsg, TEXT("Component = %s (Unicode) %s (ANSI)"), lpcvComponentId, wszFromANSI); } else { // // Only ANSI supported // mbstowcs(wszFromANSI, (PCHAR)lpcvComponentId, strlen((PCHAR)lpcvComponentId)); wszFromANSI[strlen((PCHAR)lpcvSubcomponentId)] = L'\0'; _stprintf(tszMsg, TEXT("Component = %s (ANSI only)"), wszFromANSI); } #else // // ANSI // if (uiParam1 & OCFLAG_UNICODE) { // // The ComponentId is Unicode // wcstombs(cszFromUnicode, (PWCHAR)lpcvComponentId, wcslen((PWCHAR)lpcvComponentId)); cszFromUnicode[wcslen((PWCHAR)lpcvComponentId)] = '\0'; sprintf(tszMsg, "Component = %s (ANSI) %s (Unicode)", (PCHAR)lpcvSubcomponentId, cszFromUnicode); } else { sprintf(tszMsg, "Component = %s (ANSI only)", (PCHAR)lpcvSubcomponentId); } #endif } // // Log this first line of information // Log(fn, INFO, tszMsg); // // Check if the function is in range // __ASSERT(uiCount < MAX_OC_FUNCTION); // // Now we're ready to print the details // switch (uiFunction) { case OC_PREINITIALIZE: break; case OC_INIT_COMPONENT: // // We have a bunch of information to print here // psicInitComp = (PSETUP_INIT_COMPONENT)pvParam2; // // Assert that the Param2 is not NULL, we can dereference it // __ASSERT(psicInitComp != NULL); Log(fn, INFO, TEXT("OCManagerVersion = %d"), psicInitComp->OCManagerVersion); Log(fn, INFO, TEXT("ComponentVersion = %d"), psicInitComp->ComponentVersion); // // The mode first // _tcscpy(tszMsg, TEXT("Mode ")); switch (psicInitComp->SetupData.SetupMode) { case SETUPMODE_UNKNOWN: _tcscat(tszMsg, TEXT("Unknown")); break; case SETUPMODE_MINIMAL: _tcscat(tszMsg, TEXT("Minimal")); break; case SETUPMODE_TYPICAL: _tcscat(tszMsg, TEXT("Typical")); break; case SETUPMODE_LAPTOP: _tcscat(tszMsg, TEXT("Laptop")); break; case SETUPMODE_CUSTOM: _tcscat(tszMsg, TEXT("Custom")); break; default: break; } // // ... then the product type // _tcscat(tszMsg, TEXT(" ProductType ")); switch (psicInitComp->SetupData.ProductType) { case PRODUCT_WORKSTATION: _tcscat(tszMsg, TEXT("Workstation")); break; case PRODUCT_SERVER_PRIMARY: _tcscat(tszMsg, TEXT("Server Primary")); break; case PRODUCT_SERVER_STANDALONE: _tcscat(tszMsg, TEXT("Server Standalone")); break; case PRODUCT_SERVER_SECONDARY: _tcscat(tszMsg, TEXT("Server Secondary")); break; default: break; } // // ... then the operation // _tcscat(tszMsg, TEXT(" Operation ")); switch (psicInitComp->SetupData.OperationFlags) { case SETUPOP_WIN31UPGRADE: _tcscat(tszMsg, TEXT("Win 3.1")); break; case SETUPOP_WIN95UPGRADE: _tcscat(tszMsg, TEXT("Win95")); break; case SETUPOP_NTUPGRADE: _tcscat(tszMsg, TEXT("NT")); break; case SETUPOP_BATCH: _tcscat(tszMsg, TEXT("Batch")); break; case SETUPOP_STANDALONE: _tcscat(tszMsg, TEXT("Standalone")); break; default: break; } Log(fn, INFO, tszMsg); ZeroMemory(tszMsg, MAX_MSG_LEN); if (psicInitComp->SetupData.SourcePath[0] != TEXT('\0')) { _stprintf(tszMsg, TEXT("Source Path = %s"), psicInitComp->SetupData.SourcePath); } if (psicInitComp->SetupData.UnattendFile[0] != TEXT('\0')) { _stprintf(tszMsg, TEXT("%s, UnattendedFile = %s"), tszMsg, psicInitComp->SetupData.UnattendFile); } break; case OC_SET_LANGUAGE: Log(fn, INFO, TEXT("Primary = %d Secondary = %d"), PRIMARYLANGID((WORD)uiParam1), SUBLANGID((WORD)uiParam1)); break; case OC_QUERY_IMAGE: break; case OC_REQUEST_PAGES: switch (uiParam1) { case WizPagesWelcome: _tcscpy(tszMsg, TEXT("Welcome Pages ")); break; case WizPagesMode: _tcscpy(tszMsg, TEXT("Mode Pages")); break; case WizPagesEarly: _tcscpy(tszMsg, TEXT("Early Pages")); break; case WizPagesPrenet: _tcscpy(tszMsg, TEXT("Prenet Pages")); break; case WizPagesPostnet: _tcscpy(tszMsg, TEXT("Postnet Pages")); break; case WizPagesLate: _tcscpy(tszMsg, TEXT("Late Pages")); break; case WizPagesFinal: _tcscpy(tszMsg, TEXT("Final Pages")); break; default: break; } Log(fn, INFO, TEXT("Maximum %s = %d"), tszMsg, ((PSETUP_REQUEST_PAGES)pvParam2)->MaxPages); break; case OC_QUERY_CHANGE_SEL_STATE: Log(fn, INFO, TEXT("Component %s %s"), ((uiParam1 == 0)?TEXT("unselected"):TEXT("selected")), (((INT)pvParam2 == OCQ_ACTUAL_SELECTION)?TEXT("Now"):TEXT(""))); break; default: break; } LogBlankLine(); return; } // LogOCFunction // /*++ Routine Description: Check if a radio button is checked or not. Arguments: hwndDialog - handle to the dialog box. CtrlId - the Control ID. Return Value: TRUE if the button is checked, FALSE if not. --*/ BOOL QueryButtonCheck(IN HWND hwndDlg, IN INT iCtrlID) { HWND hwndCtrl = GetDlgItem(hwndDlg, iCtrlID); INT iCheck = (INT)SendMessage(hwndCtrl, BM_GETCHECK, 0, 0); return (iCheck == BST_CHECKED); } // QueryButtonCheck // /*++ Routine Description: Prints the space required on each drive. Arguments: DiskSpace - the structure that describes the disk space required. Return Value: None. --*/ VOID PrintSpaceOnDrives(IN HDSKSPC DiskSpace) { DWORD dwRequiredSize, dwReturnBufferSize; PTCHAR tszReturnBuffer, tszPointerToStringToFree; TCHAR tszMsg[MAX_MSG_LEN]; LONGLONG llSpaceRequired; SetupQueryDrivesInDiskSpaceList(DiskSpace, NULL, 0, &dwRequiredSize); dwReturnBufferSize = dwRequiredSize; __Malloc(&tszReturnBuffer, (dwReturnBufferSize * sizeof(TCHAR))); SetupQueryDrivesInDiskSpaceList(DiskSpace, tszReturnBuffer, dwReturnBufferSize, &dwRequiredSize); // // We need to do this because we'll modify ReturnBuffer // tszPointerToStringToFree = tszReturnBuffer; if (GetLastError() == NO_ERROR) { // // Parse the ReturnBuffer // while (*tszReturnBuffer != TEXT('\0')) { SetupQuerySpaceRequiredOnDrive(DiskSpace, tszReturnBuffer, &llSpaceRequired, 0, 0); _stprintf(tszMsg, TEXT("Drive: %s Space required = %I64x, %I64d\n"), tszReturnBuffer, llSpaceRequired, llSpaceRequired); OutputDebugString(tszMsg); // // The next string is ahead // tszReturnBuffer += _tcslen(tszReturnBuffer) + 1; } } __Free(&tszPointerToStringToFree); return; } // PrintSpaceOnDrives // // // Routines that deal with multistrings. // All assume that the multistring is double NULL terminated // /*++ Routine Description: Converts a multistring to a string, by replacing the '\0' characters with blanks. Both strings should be properly allocated. Arguments: MultiStr - supplies the multi string. Str - recieves the string. Return Value: None. --*/ VOID MultiStringToString(IN PTSTR tszMultiStr, OUT PTSTR tszStr) { PTSTR tszAux; __ASSERT((tszMultiStr != NULL) && (tszStr != NULL)); tszAux = tszMultiStr; while (*tszAux != TEXT('\0')) { _tcscpy(tszStr, tszAux); // // Replace the '\0' with ' ' and terminate correctly Str // tszStr[tszAux - tszMultiStr + _tcslen(tszAux)] = TEXT(' '); tszStr[tszAux - tszMultiStr + _tcslen(tszAux) + 1] = TEXT('\0'); tszAux += _tcslen(tszAux) + 1; } // // End properly Str (the last ' ' is useless) // tszStr[tszAux - tszMultiStr + _tcslen(tszAux)] = TEXT('\0'); return; } // MultiStringToString // /*++ Routine Description: Calculates the size of a multi string (we can't use _tcslen). Note that the size is in BYTES Arguments: tszMultiStr - the multi string. Return Value: The length (in bytes) of the multi string. --*/ INT MultiStringSize(IN PTSTR tszMultiStr) { PTSTR tszAux; UINT uiLength = 0; __ASSERT(tszMultiStr != NULL); tszAux = tszMultiStr; while (*tszAux != TEXT('\0')) { // // We should count the '\0' after the string // uiLength += _tcslen(tszAux) + 1; tszAux += _tcslen(tszAux) + 1; } // // We didn't count the ending '\0', so add it now // return ((uiLength + 1) * sizeof(TCHAR)); } // MultiStringSize // /*++ Routine Description: Copies a multistring. Arguments: tszMultiStrDestination: the destination multi string. tszMultiStrSource: the source multi string. Return Value: None. --*/ VOID CopyMultiString(OUT PTSTR tszMultiStrDestination, IN PTSTR tszMultiStrSource) { UINT uiCount = 0; PTSTR tszAuxS, tszAuxD; __ASSERT((tszMultiStrSource != NULL) && (tszMultiStrDestination != NULL)); tszAuxS = tszMultiStrSource; tszAuxD = tszMultiStrDestination; // // Copies the multi string // while (*tszAuxS != TEXT('\0')) { _tcscpy(tszAuxD, tszAuxS); tszAuxD += _tcslen(tszAuxD) + 1; tszAuxS += _tcslen(tszAuxS) + 1; } // // Add the terminating NULL // *tszAuxD = TEXT('\0'); return; } // CopyMultiString // /*++ Routine Description: InitGlobals Initializes global variables Arguments: none Return Value: void --*/ VOID InitGlobals() { g_bUsePrivateFunctions = FALSE; g_bFirstTime = TRUE; g_uiCurrentPage = 0; g_bAccessViolation = FALSE; g_bTestExtended = FALSE; nStepsFinal = NO_STEPS_FINAL; g_bNoWizPage = FALSE; g_bCrashUnicode = FALSE; g_bInvalidBitmap = FALSE; g_bHugeSize = FALSE; g_bCloseInf = FALSE; hInfGlobal = NULL; g_bNoNeedMedia = TRUE; g_bCleanReg = FALSE; g_uiFunctionToAV = 32574; g_bNoLangSupport = FALSE; g_bReboot = FALSE; } // InitGlobals //