windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/detect1.c
2020-09-26 16:20:57 +08:00

1125 lines
22 KiB
C

#include "precomp.h"
#pragma hdrstop
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
detect1.c
Abstract:
Detect module for Win32 PDK Setup.
This module has no external dependencies and is not statically linked
to any part of Setup.
Author:
Ted Miller (tedm) June 1991
--*/
#define PROCESSOR_NONE ""
#define PROCESSOR_I386 "I386"
#define PROCESSOR_I486 "I486"
#define PROCESSOR_I586 "I586"
#define PROCESSOR_R4000 "R4000"
#define PROCESSOR_ALPHA "Alpha_AXP"
#define PROCESSOR_PPC601 "PPC601"
#define PROCESSOR_PPC603 "PPC603"
#define PROCESSOR_PPC604 "PPC604"
#define PROCESSOR_PPC620 "PPC620"
#define PLATFORM_NONE ""
#define PLATFORM_I386 "I386"
#define PLATFORM_MIPS "Mips"
#define PLATFORM_ALPHA "Alpha"
#define PLATFORM_PPC "ppc"
//
// Local prototypes
//
BOOL MatchNtPathToDosPath( PUNICODE_STRING, PUNICODE_STRING, SZ, SZ, CB );
VOID ConvertUnicodeToAnsi( PUNICODE_STRING, SZ );
/*
oemcp as a string
*/
CB
GetOemCodepage(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
UINT cp;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
cp = GetOEMCP();
wsprintf(ReturnBuffer,"%u",cp);
return(lstrlen(ReturnBuffer)+1);
}
/*
ansicp as a string
*/
CB
GetAnsiCodepage(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
UINT cp;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
cp = GetACP();
wsprintf(ReturnBuffer,"%u",cp);
return(lstrlen(ReturnBuffer)+1);
}
/*
langauge type as a string
*/
CB
GetLanguage(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
//
// bugbug ramonsa - enable when GetQualifiedLocale returns something
// meaningful
#ifdef LOCALE_STUFF
LCID LcId = {0,0,0};
LCSTRINGS LcStrings;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
ReturnBuffer[0] = '\0';
if ( GetQualifiedLocale( QF_LCID,
&LcId,
NULL,
&LcStrings ) ) {
lstrcpy(ReturnBuffer,LcStrings.szLanguage);
return(lstrlen(ReturnBuffer)+1);
}
return 0;
#else
#define TEMP_LANGUAGE "ENG"
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
lstrcpy(ReturnBuffer,TEMP_LANGUAGE);
return(lstrlen(ReturnBuffer)+1);
#endif
}
/*
* GetSystemDate - returns a list of date information in the following
* order:
* sec after 1-1-1970, year, month, day, hour, minute, second, millisecond
*
*/
CB
GetSystemDate(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
SYSTEMTIME systime;
time_t timet;
Unused( Args );
Unused( cArgs );
Unused( cbReturnBuffer );
GetSystemTime( &systime );
time( &timet );
wsprintf(ReturnBuffer, "{\"%d\",\"%d\",\"%d\",\"%d\",\"%d\",\"%d\",\"%d\",\"%d\"}",
timet,
systime.wYear,
systime.wMonth,
systime.wDay,
systime.wHour,
systime.wMinute,
systime.wSecond,
systime.wMilliseconds
);
return(lstrlen(ReturnBuffer)+1);
}
/*
Country type as a string
*/
CB
GetCountry(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
//
// bugbug ramonsa - enable when GetQualifiedLocale returns something
// meaningful
#ifdef LOCALE_STUFF
LCID LcId = {0,0,0};
LCSTRINGS LcStrings;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
ReturnBuffer[0] = '\0';
if ( GetQualifiedLocale( QF_LCID,
&LcId,
NULL,
&LcStrings ) ) {
lstrcpy(ReturnBuffer,LcStrings.szCountry);
return(lstrlen(ReturnBuffer)+1);
}
return 0;
#else
#define TEMP_COUNTRY "US"
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
lstrcpy(ReturnBuffer,TEMP_COUNTRY);
return(lstrlen(ReturnBuffer)+1);
#endif
}
CB
GetProcessor(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
SYSTEM_INFO SystemInfo;
SZ szProcessor;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
GetSystemInfo( &SystemInfo );
switch ( SystemInfo.wProcessorArchitecture ) {
case PROCESSOR_ARCHITECTURE_INTEL:
if (SystemInfo.wProcessorLevel == 3) {
szProcessor = PROCESSOR_I386;
} else
if (SystemInfo.wProcessorLevel == 4) {
szProcessor = PROCESSOR_I486;
} else {
szProcessor = PROCESSOR_I586;
}
break;
case PROCESSOR_ARCHITECTURE_MIPS:
szProcessor = PROCESSOR_R4000;
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
szProcessor = PROCESSOR_ALPHA;
break;
case PROCESSOR_ARCHITECTURE_PPC:
if (SystemInfo.wProcessorLevel == 1) {
szProcessor = PROCESSOR_PPC601;
} else
if (SystemInfo.wProcessorLevel == 3) {
szProcessor = PROCESSOR_PPC603;
} else
if (SystemInfo.wProcessorLevel == 4) {
szProcessor = PROCESSOR_PPC604;
} else
if (SystemInfo.wProcessorLevel == 6) {
szProcessor = PROCESSOR_PPC603;
} else
if (SystemInfo.wProcessorLevel == 7) {
szProcessor = PROCESSOR_PPC603;
} else
if (SystemInfo.wProcessorLevel == 9) {
szProcessor = PROCESSOR_PPC604;
} else
if (SystemInfo.wProcessorLevel == 20) {
szProcessor = PROCESSOR_PPC620;
}
else {
szProcessor = PROCESSOR_PPC601;
}
break;
default:
//
// There could be processors we don't know about.
// Try to make sure we'll at least set up on them
// by defaulting to a known processor. This also eliminates
// the need to keep updating the INFs to know about all the
// processors we support.
//
szProcessor = PROCESSOR_NONE;
#ifdef _X86_
//
// Probably a P6 or greater.
//
szProcessor = PROCESSOR_I586;
#endif
#ifdef _MIPS_
//
// Probably something that came after the R4000.
// Assume R4000 to be safe.
//
szProcessor = PROCESSOR_R4000;
#endif
#ifdef _ALPHA_
//
// Just recognize that it's an Alpha.
//
szProcessor = PROCESSOR_ALPHA;
#endif
#ifdef _PPC_
//
// Just call it a 601, which is assumed to be
// the lowest common denominator.
//
szProcessor = PROCESSOR_PPC601;
#endif
break;
}
lstrcpy( ReturnBuffer, szProcessor );
return lstrlen( ReturnBuffer)+1;
}
CB
GetPlatform(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
SYSTEM_INFO SystemInfo;
SZ szPlatform;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
GetSystemInfo( &SystemInfo );
switch ( SystemInfo.wProcessorArchitecture ) {
case PROCESSOR_ARCHITECTURE_INTEL:
szPlatform = PLATFORM_I386;
break;
case PROCESSOR_ARCHITECTURE_MIPS:
szPlatform = PLATFORM_MIPS;
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
szPlatform = PLATFORM_ALPHA;
break;
case PROCESSOR_ARCHITECTURE_PPC:
szPlatform = PLATFORM_PPC;
break;
default:
szPlatform = PLATFORM_NONE;
//
// Try really hard to return a reasonable value by
// assuming that the code is running on a machine of the
// platform for which the it was compiled.
// This lets us run on processors we haven't invented yet
// and whose ids are thus not accounted for in the aboce
// cases.
//
#ifdef _X86_
szPlatform = PLATFORM_I386;
#endif
#ifdef _MIPS_
szPlatform = PLATFORM_MIPS;
#endif
#ifdef _ALPHA_
szPlatform = PLATFORM_ALPHA;
#endif
#ifdef _PPC_
szPlatform = PLATFORM_PPC;
#endif
break;
}
lstrcpy( ReturnBuffer, szPlatform );
return lstrlen( ReturnBuffer)+1;
}
/*
Memory size as an ASCII string (Kb)
*/
CB
GetMemorySize(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
MEMORYSTATUS MemoryStatus;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
GlobalMemoryStatus(&MemoryStatus);
_ultoa((ULONG)(MemoryStatus.dwTotalPhys/1024),ReturnBuffer,10);
return(lstrlen(ReturnBuffer)+1);
}
/*
Minimum pagefile size necessary for crash dump support (MB)
*/
CB
GetCrashDumpSize(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
MEMORYSTATUS ms;
SYSTEM_INFO si;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
GlobalMemoryStatus(&ms);
GetSystemInfo(&si);
//
// We need a pagefile as large as physical memory + 1 page.
//
_ultoa(
(ULONG)((ms.dwTotalPhys + si.dwPageSize + 0xFFFFF) >> 20),
ReturnBuffer,
10);
return(lstrlen(ReturnBuffer)+1);
}
/*
list of paths on which a given file appears.
*/
CB
FindFileInstances(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CB rc = 0;
SZ sz;
RGSZ rgszFiles;
HANDLE hff;
WIN32_FIND_DATA FindFileData;
Unused(cbReturnBuffer);
//
// If no file specified then return 0
//
if (cArgs != 1) {
return rc;
}
//
// If invalid filename then return 0
if ((lstrlen(Args[0]) + 1) > MAX_PATH) {
return rc;
}
//
// Allocate just the NULL terminator for the rgsz structure
//
rgszFiles = RgszAlloc(1);
if (!rgszFiles) {
return rc;
}
//
// Do find first, find next adding files found to the rgsz structure
//
if ((hff = FindFirstFile( Args[0], &FindFileData )) != (HANDLE)-1) {
do {
if (!RgszAdd( &rgszFiles, SzDup( (SZ)FindFileData.cFileName ) )) {
FindClose( hff );
return rc;
}
}
while (FindNextFile(hff, &FindFileData));
FindClose( hff );
}
//
// Convert the rgsz structure to a sz list value and copy this over
// to the return buffer.
//
sz = SzListValueFromRgsz( rgszFiles );
if ( sz ) {
lstrcpy( ReturnBuffer, sz );
rc = lstrlen(sz) + 1;
SFree( sz );
}
RgszFree( rgszFiles );
return ( rc );
}
//
// Get Windows version
//
CB
GetWindowsNtVersion(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
DWORD Version;
DWORD WinMaj;
DWORD WinMin;
DWORD OsMaj;
DWORD OsMin;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
Version = GetVersion();
WinMaj = FIRSTBYTE(Version);
WinMin = SECONDBYTE(Version);
OsMin = THIRDBYTE(Version);
OsMaj = FOURTHBYTE(Version);
sprintf(ReturnBuffer, "{%lu,%lu,%lu,%lu}", WinMaj, WinMin, OsMaj, OsMin );
return(lstrlen(ReturnBuffer)+1);
}
//
// Get Windows directory
//
CB
GetWindowsNtDir(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
DWORD cbRet;
Unused(Args);
Unused(cArgs);
cbRet = GetWindowsDirectory( ReturnBuffer, cbReturnBuffer );
if ( (cbRet == 0) || (cbRet > cbReturnBuffer) ) {
ReturnBuffer[0] = '\0';
return 0;
}
return cbRet + 1;
}
//
// Get Windows system directory
//
CB
GetWindowsNtSysDir(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
DWORD cbRet;
Unused(Args);
Unused(cArgs);
cbRet = GetSystemDirectory( ReturnBuffer, cbReturnBuffer );
if ( (cbRet == 0) || (cbRet > cbReturnBuffer) ) {
ReturnBuffer[0] = '\0';
return 0;
}
return cbRet + 1;
}
//
// Get NT directory
//
CB
GetNtDir(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
#define SYSTEMROOT "\\SystemRoot"
#define DRIVEROOT "\\DosDevices\\?:"
#define LINKBUFFERSIZE (MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR))
ANSI_STRING SystemRoot;
ANSI_STRING DriveRoot;
WCHAR SysLinkBuffer[LINKBUFFERSIZE];
WCHAR DrvLinkBuffer[LINKBUFFERSIZE];
WCHAR DriveLetter;
CHAR DriveBuffer[] = DRIVEROOT;
NTSTATUS Status;
UNICODE_STRING SystemRootU;
UNICODE_STRING SystemRootLinkU;
UNICODE_STRING DriveRootU;
UNICODE_STRING DriveRootLinkU;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
ReturnBuffer[0] = '\0';
SystemRootLinkU.Length = 0;
SystemRootLinkU.MaximumLength = LINKBUFFERSIZE;
SystemRootLinkU.Buffer = SysLinkBuffer;
DriveRootLinkU.Length = 0;
DriveRootLinkU.MaximumLength = LINKBUFFERSIZE;
DriveRootLinkU.Buffer = DrvLinkBuffer;
RtlInitAnsiString(&SystemRoot, SYSTEMROOT);
Status = RtlAnsiStringToUnicodeString(
&SystemRootU,
&SystemRoot,
TRUE
);
//
// Get the value of the "SystemRoot" symbolic link.
//
if ( GetSymbolicLinkTarget( &SystemRootU, &SystemRootLinkU ) ) {
for ( DriveLetter = (WCHAR)'A';
DriveLetter <= (WCHAR)'Z';
DriveLetter++ ) {
DriveBuffer[12] = (CHAR)DriveLetter;
RtlInitAnsiString(&DriveRoot, DriveBuffer);
Status = RtlAnsiStringToUnicodeString(
&DriveRootU,
&DriveRoot,
TRUE
);
//
// If there is a symbolic link for the drive, see if it
// matches the symbolic link of "SystemRoot"
//
if ( GetSymbolicLinkTarget( &DriveRootU, &DriveRootLinkU ) ) {
if ( MatchNtPathToDosPath( &SystemRootLinkU,
&DriveRootLinkU,
&DriveBuffer[12],
ReturnBuffer,
cbReturnBuffer ) ) {
return lstrlen(ReturnBuffer)+1;
}
}
RtlFreeUnicodeString(&DriveRootU);
}
}
RtlFreeUnicodeString(&SystemRootU);
return 0;
}
//
// Convert an NT path to a DOS path
//
BOOL
MatchNtPathToDosPath(
IN PUNICODE_STRING NtPathU,
IN PUNICODE_STRING DosLinkU,
IN SZ DosPath,
OUT SZ ReturnBuffer,
IN CB cbBuffer
)
{
CHAR NtPath[MAX_PATH];
CHAR DosLink[MAX_PATH];
SZ p;
Unused( cbBuffer );
ConvertUnicodeToAnsi( NtPathU, NtPath );
ConvertUnicodeToAnsi( DosLinkU, DosLink );
//
// If DosLink is a substring of NtPath, then subsitute that substring by
// the given DosPath.
//
p = strstr( NtPath, DosLink );
if ( p == NtPath ) {
strcpy( ReturnBuffer, DosPath );
p = NtPath + strlen(DosLink);
strcat( ReturnBuffer, p );
return fTrue;
}
return fFalse;
}
//
// Convert Unicode string to ansi string
//
VOID
ConvertUnicodeToAnsi(
IN PUNICODE_STRING UnicodeString,
OUT SZ AnsiString
)
{
WCHAR *pw;
SZ pa;
pw = UnicodeString->Buffer;
pa = AnsiString;
while ( *pw != (WCHAR)0 ) {
*pa++ = (CHAR)(*pw++);
}
*pa = '\0';
}
//
// Get NT drive
//
CB
GetNtDrive(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
if ( GetNtDir( Args, cArgs, ReturnBuffer, cbReturnBuffer ) > 0 ) {
ReturnBuffer[2] = '\0';
return 3;
}
return 0;
}
#if i386
//
// Get NT Boot Info - I386 version
//
CB
GetNtBootInfo(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
#define BOOT_INI "C:\\BOOT.INI"
#define MULTIBOOT_SCT "multiboot"
#define FLEXBOOT_SCT "flexboot"
#define OS_SCT "operating systems"
#define TIMEOUT "timeout"
#define DEFAULT "default"
PTAGGEDFILE pBootTxt;
PTFSECTION pSection;
PTFKEYWORD pTimeout;
PTFKEYWORD pDefault;
PTFKEYWORD pKey;
BOOL fOkay = fFalse;
RGSZ rgszInfo;
RGSZ rgszTmp;
SZ sz;
INT cCount = 3;
Unused( Args );
Unused( cArgs );
Unused( cbReturnBuffer );
rgszInfo = RgszAlloc(cCount);
rgszTmp = RgszAlloc(3);
if ( rgszInfo && rgszTmp ) {
//
// Get Boot.txt
//
if ( pBootTxt = GetTaggedFile( BOOT_INI ) ) {
//
// Get multiboot section
//
if ( ( pSection = GetSection( pBootTxt, MULTIBOOT_SCT )) ||
( pSection = GetSection( pBootTxt, FLEXBOOT_SCT ))
) {
//
// Get timeout and default
//
pTimeout = GetKeyword( pSection, TIMEOUT );
pDefault = GetKeyword( pSection, DEFAULT );
if ( pTimeout && pDefault ) {
//
// Get Operating systems section
//
if ( pSection = GetSection( pBootTxt, OS_SCT ) ) {
rgszInfo[0] = SzDup( pTimeout->szValue );
rgszInfo[1] = SzDup( pDefault->szValue );
rgszInfo[2] = NULL;
if ( rgszInfo[0] && rgszInfo[1] ) {
fOkay = fTrue;
pKey = NULL;
while ( pKey = GetNextKeyword( pSection, pKey )) {
rgszTmp[0] = pKey->szName;
rgszTmp[1] = pKey->szValue;
rgszTmp[2] = NULL;
sz = SzListValueFromRgsz( rgszTmp );
if ( !sz ||
!RgszAdd( &rgszInfo, sz ) ) {
fOkay = fFalse;
if ( sz ) {
SFree( sz );
}
break;
}
}
}
}
}
}
CloseTaggedFile( pBootTxt );
}
}
if ( fOkay ) {
sz = SzListValueFromRgsz( rgszInfo );
if ( sz ) {
strcpy( ReturnBuffer, sz );
SFree( sz );
} else {
fOkay = fFalse;
}
}
if ( rgszTmp ) {
rgszTmp[0] = NULL;
RgszFree( rgszTmp );
}
if ( rgszInfo ) {
RgszFreeCount( rgszInfo, cCount );
}
if ( fOkay ) {
return lstrlen(ReturnBuffer)+1;
} else {
return 0;
}
}
#else // if i386
//
// Get NT Boot Info - MIPS version
//
CB
GetNtBootInfo(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
//
// BUGBUG ramonsa - For MIPS currently we fail
//
Unused( Args );
Unused( cArgs );
Unused( ReturnBuffer );
Unused( cbReturnBuffer );
return 0;
}
#endif // if i386
//
// Get value of an environment variable. Returns the value in list form. If the
// value is a path (semicolon-separated components) each component is an element
// of the list.
//
CB
GetLoadedEnvVar(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR EnvValue[ MAX_PATH ];
SZ sz;
Unused( cbReturnBuffer );
ReturnBuffer[0] = '\0';
if (cArgs > 0) {
if ( GetEnvironmentVariable( Args[0], EnvValue, MAX_PATH ) == 0 ) {
//
// Env. Variable not defined, return empty list
//
#define UNDEF_VAR_VALUE "{}"
lstrcpy( ReturnBuffer, UNDEF_VAR_VALUE );
return lstrlen( ReturnBuffer )+1;
} else if ( sz = SzListValueFromPath( EnvValue ) ) {
lstrcpy( ReturnBuffer, sz );
SFree( sz );
return lstrlen( ReturnBuffer)+1;
}
}
return 0;
}
CB
IsUniprocessorSystem(
IN RGSZ Args,
IN USHORT cArgs,
OUT SZ ReturnBuffer,
IN CB cbReturnBuffer
)
{
CHAR Value[256];
HKEY hkey;
LONG l;
DWORD size;
BOOL IsUp;
SYSTEM_INFO SysInfo;
Unused(Args);
Unused(cArgs);
Unused(cbReturnBuffer);
ReturnBuffer[0] = 0;
//
// Look in the registry.
//
l = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
"Software\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_QUERY_VALUE,
&hkey
);
if(l == NO_ERROR) {
size = sizeof(Value);
l = RegQueryValueEx(
hkey,
"CurrentType",
NULL,
NULL,
Value,
&size
);
RegCloseKey(hkey);
}
if(l == NO_ERROR) {
//
// It's UP if the string starts with Uni
// and not Multi
//
IsUp = (Value[0] == 'U');
} else {
//
// Registry didn't tell us for some reason; fall back on
// the # of processors.
//
GetSystemInfo(&SysInfo);
IsUp = (SysInfo.dwNumberOfProcessors == 1);
}
lstrcpy(ReturnBuffer,IsUp ? "YES" : "NO");
return lstrlen(ReturnBuffer)+1;
}