Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

680 lines
16 KiB

/*++
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 //