Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1395 lines
39 KiB

/****************************************************************************
Copyright (c) Microsoft Corporation 1997
All rights reserved
***************************************************************************/
#include "pch.h"
DEFINE_MODULE("Utils");
#define SMALL_BUFFER_SIZE 1024
BOOL
x86DetermineSystemPartition(
IN HWND ParentWindow,
OUT PTCHAR SysPartDrive
);
//
// Centers a dialog.
//
void
CenterDialog(
HWND hwndDlg )
{
RECT rc;
RECT rcScreen;
int x, y;
int cxDlg, cyDlg;
int cxScreen;
int cyScreen;
SystemParametersInfo( SPI_GETWORKAREA, 0, &rcScreen, 0 );
cxScreen = rcScreen.right - rcScreen.left;
cyScreen = rcScreen.bottom - rcScreen.top;
GetWindowRect( hwndDlg, &rc );
cxDlg = rc.right - rc.left;
cyDlg = rc.bottom - rc.top;
y = rcScreen.top + ( ( cyScreen - cyDlg ) / 2 );
x = rcScreen.left + ( ( cxScreen - cxDlg ) / 2 );
SetWindowPos( hwndDlg, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE );
}
//
// Eats all mouse and keyboard messages.
//
void
ClearMessageQueue( void )
{
MSG msg;
while ( PeekMessage( (LPMSG)&msg, NULL, WM_KEYFIRST, WM_MOUSELAST,
PM_NOYIELD | PM_REMOVE ) );
}
//
// Create a message box from resource strings.
//
int
MessageBoxFromStrings(
HWND hParent,
UINT idsCaption,
UINT idsText,
UINT uType )
{
TCHAR szText[ SMALL_BUFFER_SIZE ];
TCHAR szCaption[ SMALL_BUFFER_SIZE ];
DWORD dw;
dw = LoadString( g_hinstance, idsCaption, szCaption, ARRAYSIZE( szCaption ));
Assert( dw );
dw = LoadString( g_hinstance, idsText, szText, ARRAYSIZE( szText ));
Assert( dw );
return MessageBox( hParent, szText, szCaption, uType );
}
//
// Creates a error message box
//
void
MessageBoxFromError(
HWND hParent,
LPTSTR pszTitle,
DWORD dwErr )
{
WCHAR szText[ SMALL_BUFFER_SIZE ];
LPTSTR lpMsgBuf;
if ( dwErr == ERROR_SUCCESS ) {
AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
return;
}
if ( !pszTitle ) {
DWORD dw;
szText[0] = L'\0';
dw = LoadString( g_hinstance, IDS_ERROR, szText, ARRAYSIZE( szText ));
Assert( dw );
pszTitle = szText;
}
if (!FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL )) {
lpMsgBuf = NULL;
}
if (lpMsgBuf == NULL) {
AssertMsg( dwErr, "Getting error message failed. Why?" );
return;
}
MessageBox( hParent, lpMsgBuf, pszTitle, MB_OK | MB_ICONERROR );
LocalFree( lpMsgBuf );
}
//
// Creates a error message box
//
void
ErrorBox(
HWND hParent,
LPTSTR pszTitle )
{
DWORD dw;
DWORD dwErr = GetLastError( );
WCHAR szText[ SMALL_BUFFER_SIZE ];
WCHAR szString[ 256 ];
LPTSTR lpMsgBuf;
if ( dwErr == ERROR_SUCCESS ) {
AssertMsg( dwErr, "Why was MessageBoxFromError() called when the dwErr == ERROR_SUCCES?" );
return;
}
if ( !pszTitle ) {
DWORD LoadStringStatus;
LoadStringStatus = LoadString( g_hinstance, IDS_ERROR, szText, ARRAYSIZE( szText ));
Assert( LoadStringStatus );
pszTitle = szText;
}
switch (dwErr) {
case ERROR_LINE_NOT_FOUND:
case ERROR_SECTION_NOT_FOUND:
case ERROR_WRONG_INF_STYLE:
case ERROR_EXPECTED_SECTION_NAME:
case ERROR_BAD_SECTION_NAME_LINE:
case ERROR_SECTION_NAME_TOO_LONG:
case ERROR_GENERAL_SYNTAX:
dw = LoadString( g_hinstance, IDS_INF_ERROR, szText, ARRAYSIZE(szText));
Assert( dw );
MessageBox( hParent, szText, pszTitle, MB_OK | MB_ICONERROR );
break;
default:
dw = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
if ( dw != 0 )
{
MessageBox( hParent, lpMsgBuf, pszTitle, MB_OK | MB_ICONERROR );
LocalFree( lpMsgBuf );
}
else
{
dw = LoadString( g_hinstance, IDS_UNDEFINED_ERROR_STRING, szString, ARRAYSIZE(szString));
Assert( dw );
_snwprintf( szText, ARRAYSIZE(szText), szString, dwErr );
TERMINATE_BUFFER(szText);
MessageBox( hParent, szText, pszTitle, MB_OK | MB_ICONERROR );
}
}
}
VOID
SetDialogFont(
IN HWND hdlg,
IN UINT ControlId,
IN MyDlgFont WhichFont
)
{
static HFONT BigBoldFont = NULL;
static HFONT BoldFont = NULL;
static HFONT NormalFont = NULL;
HFONT Font;
LOGFONT LogFont;
WCHAR FontSizeString[24];
int FontSize;
HDC hdc;
switch(WhichFont) {
case DlgFontTitle:
if(!BigBoldFont) {
Font = (HFONT)SendDlgItemMessage(hdlg, ControlId, WM_GETFONT, 0, 0);
if ( Font )
{
if ( GetObject( Font, sizeof(LOGFONT), &LogFont) )
{
DWORD dw = LoadString( g_hinstance,
IDS_LARGEFONTNAME,
LogFont.lfFaceName,
LF_FACESIZE);
Assert( dw );
dw = LoadString( g_hinstance,
IDS_LARGEFONTSIZE,
FontSizeString,
ARRAYSIZE(FontSizeString));
Assert( dw );
FontSize = wcstoul( FontSizeString, NULL, 10 );
// make sure we at least have some basic font
if (*LogFont.lfFaceName == 0 || FontSize == 0) {
lstrcpy(LogFont.lfFaceName,TEXT("MS Shell Dlg") );
FontSize = 18;
}
LogFont.lfWeight = FW_BOLD;
hdc = GetDC(hdlg);
if ( hdc )
{
LogFont.lfHeight =
0 - (GetDeviceCaps(hdc,LOGPIXELSY) * FontSize / 72);
BigBoldFont = CreateFontIndirect(&LogFont);
ReleaseDC(hdlg,hdc);
}
}
}
}
Font = BigBoldFont;
break;
case DlgFontBold:
if ( !BoldFont )
{
Font = (HFONT)SendDlgItemMessage( hdlg, ControlId, WM_GETFONT, 0, 0 );
if ( Font ) {
if ( GetObject( Font, sizeof(LOGFONT), &LogFont ) )
{
LogFont.lfWeight = FW_BOLD;
hdc = GetDC( hdlg );
if ( hdc )
{
BoldFont = CreateFontIndirect( &LogFont );
ReleaseDC( hdlg, hdc );
}
}
}
}
Font = BoldFont;
break;
default:
//
// Nothing to do here.
//
Font = NULL;
break;
}
if( Font )
{
SendDlgItemMessage( hdlg, ControlId, WM_SETFONT, (WPARAM) Font, 0 );
}
}
//
// Adjusts and draws a bitmap transparently in the RECT prc.
//
void
DrawBitmap(
HANDLE hBitmap,
LPDRAWITEMSTRUCT lpdis,
LPRECT prc )
{
TraceFunc( "DrawBitmap( ... )\n" );
BITMAP bm;
HDC hDCBitmap;
int dy;
GetObject( hBitmap, sizeof(bm), &bm );
hDCBitmap = CreateCompatibleDC( NULL );
if (hDCBitmap == NULL) {
return;
}
SelectObject( hDCBitmap, hBitmap );
// center the image
dy = 2 + prc->bottom - bm.bmHeight;
StretchBlt( lpdis->hDC, prc->left, prc->top + dy, prc->right, prc->bottom,
hDCBitmap, 0, 0, bm.bmWidth, bm.bmHeight, SRCAND );
DeleteDC( hDCBitmap );
TraceFuncExit( );
}
//
// Verifies that the user wanted to cancel setup.
//
BOOL
VerifyCancel( HWND hParent )
{
TraceFunc( "VerifyCancel( ... )\n" );
INT iReturn;
BOOL fAbort = FALSE;
iReturn = MessageBoxFromStrings( hParent,
IDS_CANCELCAPTION,
IDS_CANCELTEXT,
MB_YESNO | MB_ICONQUESTION );
if ( iReturn == IDYES ) {
fAbort = TRUE;
}
SetWindowLongPtr( hParent, DWLP_MSGRESULT, ( fAbort ? 0 : -1 ));
g_Options.fAbort = fAbort;
RETURN(!fAbort);
}
//
// RetrieveWorkstationLanguageFromHive
//
HRESULT
RetrieveWorkstationLanguageFromHive(
HWND hDlg )
{
TraceFunc( "RetrieveWorkstationLanguageFromHive( )\n" );
HRESULT hr = S_FALSE;
HINF hinf;
WCHAR szFilepath[ MAX_PATH ];
INFCONTEXT context;
WCHAR szCodePage[ 32 ];
ULONG uResult;
BOOL b;
UINT uLineNum;
LPWSTR psz;
//
// build the path to hivesys.inf
//
lstrcpyn( szFilepath, g_Options.szSourcePath, ARRAYSIZE(szFilepath) );
ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, L"hivesys.inf", ARRAYSIZE(szFilepath) );
//
// open the file
//
hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
if ( hinf == INVALID_HANDLE_VALUE ) {
DWORD dwErr = GetLastError( );
switch ( dwErr )
{
case ERROR_FILE_NOT_FOUND:
MessageBoxFromStrings( hDlg, IDS_FILE_NOT_FOUND_TITLE, IDS_FILE_NOT_FOUND_TEXT, MB_OK );
break;
default:
ErrorBox( hDlg, szFilepath );
break;
}
hr = HRESULT_FROM_WIN32( dwErr );
goto Cleanup;
}
// Find the "AddReg" section
b = SetupFindFirstLine( hinf, L"Strings", L"Install_Language", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
b = SetupGetStringField( &context, 1, szCodePage, ARRAYSIZE(szCodePage), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
g_Options.dwWksCodePage = (WORD) wcstoul( szCodePage, &psz, 16 );
DebugMsg( "Image CodePage = 0x%04x\n", g_Options.dwWksCodePage );
uResult = GetLocaleInfo( PRIMARYLANGID(g_Options.dwWksCodePage),
LOCALE_SENGLANGUAGE,
g_Options.szLanguage,
ARRAYSIZE(g_Options.szLanguage));
if ( uResult == 0 ) {
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
DebugMsg( "Image Language: %s\n", g_Options.szLanguage );
//
// Fix up the locale string we got back to ensure it
// contains no spaces and non non-ASCII characters.
// The localization guys changed this API so that neither
// of these properties are guarenteed any longer.
//
for( uLineNum = 0; uLineNum < wcslen(g_Options.szLanguage); uLineNum++ ) {
if( (g_Options.szLanguage[uLineNum] <= TEXT(' ')) ||
(g_Options.szLanguage[uLineNum] > TEXT('~')) ) {
g_Options.szLanguage[uLineNum] = TEXT('\0');
break;
}
}
DebugMsg( "Fixed up Image Language: %s\n", g_Options.szLanguage );
// Success!
g_Options.fLanguageSet = TRUE;
hr = S_OK;
Cleanup:
if ( hinf != INVALID_HANDLE_VALUE ) {
SetupCloseInfFile( hinf );
}
HRETURN(hr);
}
//
// CheckImageSource( )
//
HRESULT
CheckImageSource(
HWND hDlg )
{
TraceFunc( "CheckImageSource( ... )\n" );
HRESULT hr = S_FALSE;
WCHAR szFilepath[ MAX_PATH ];
WCHAR szTemp[ 32 ];
BYTE szPidExtraData[ 14 ];
HINF hinf;
UINT uLineNum;
BOOL b;
INFCONTEXT context;
//
// build the path to hivesys.inf
//
lstrcpyn( szFilepath, g_Options.szSourcePath, ARRAYSIZE(szFilepath) );
ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, L"txtsetup.sif", ARRAYSIZE(szFilepath));
//
// open the file
//
hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
if ( hinf == INVALID_HANDLE_VALUE ) {
DWORD dwErr = GetLastError( );
switch ( dwErr )
{
case ERROR_FILE_NOT_FOUND:
MessageBoxFromStrings( hDlg, IDS_FILE_NOT_FOUND_TITLE, IDS_FILE_NOT_FOUND_TEXT, MB_OK );
break;
default:
ErrorBox( hDlg, szFilepath );
break;
}
hr = HRESULT_FROM_WIN32( dwErr );
goto Cleanup;
}
#if 0
//
// Allow server installs - adamba 2/21/00
//
b = SetupFindFirstLine( hinf, L"SetupData", L"ProductType", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
if ( hr == ERROR_LINE_NOT_FOUND ) {
MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
} else {
ErrorBox( hDlg, szFilepath );
}
goto Cleanup;
}
b = SetupGetStringField( &context, 1, szTemp, ARRAYSIZE(szTemp), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
if ( StrCmp( szTemp, L"0" ) )
{
MessageBoxFromStrings( hDlg, IDS_NOT_WORKSTATION_TITLE, IDS_NOT_WORKSTATION_TEXT, MB_OK );
hr = E_FAIL;
goto Cleanup;
}
#endif
b = SetupFindFirstLine( hinf, L"SetupData", L"Architecture", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
if ( hr == HRESULT_FROM_WIN32(ERROR_LINE_NOT_FOUND) ) {
MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
} else {
ErrorBox( hDlg, szFilepath );
}
goto Cleanup;
}
b = SetupGetStringField( &context, 1, szTemp, ARRAYSIZE(szTemp), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
if ( (StrCmp(szTemp,L"i386")) && (StrCmp(szTemp,L"ia64")) )
{
MessageBoxFromStrings( hDlg, IDS_NOT_SUPPORTED_ARCHITECTURE_TITLE, IDS_NOT_SUPPORTED_ARCHITECTURE_TEXT, MB_OK );
hr = E_FAIL;
goto Cleanup;
}
if (StrCmp(g_Options.ProcessorArchitectureString,szTemp))
{
MessageBoxFromStrings( hDlg, IDS_NOT_SUPPORTED_ARCHITECTURE_TITLE, IDS_NOT_SUPPORTED_ARCHITECTURE_TEXT, MB_OK );
hr = E_FAIL;
goto Cleanup;
}
if (!g_Options.fLanguageOverRide) {
hr = RetrieveWorkstationLanguageFromHive( hDlg );
if ( FAILED( hr ) )
goto Cleanup;
}
if (!GetBuildNumberFromImagePath(
&g_Options.dwBuildNumber,
g_Options.szSourcePath,
g_Options.ProcessorArchitectureString)) {
#if 0
MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_NOT_NT5_MEDIA_SOURCE_TEXT, MB_OK );
hr = E_FAIL;
goto Cleanup;
#else
#endif
}
// Get image Major version
b = SetupFindFirstLine( hinf, L"SetupData", L"MajorVersion", &context );
if ( !b )
{
DWORD dwErr = GetLastError( );
switch ( dwErr )
{
case ERROR_LINE_NOT_FOUND:
MessageBoxFromStrings( hDlg, IDS_LINE_MISSING_CAPTION, IDS_LINE_MISSING_TEXT, MB_OK );
break;
default:
ErrorBox( hDlg, szFilepath );
break;
}
hr = HRESULT_FROM_WIN32( dwErr );
goto Cleanup;
}
b = SetupGetStringField( &context, 1, g_Options.szMajorVersion, ARRAYSIZE(g_Options.szMajorVersion), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
// Get image Minor version
b = SetupFindFirstLine( hinf, L"SetupData", L"MinorVersion", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
b = SetupGetStringField( &context, 1, g_Options.szMinorVersion, ARRAYSIZE(g_Options.szMinorVersion), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
// Get image description
if ( !g_Options.fRetrievedWorkstationString )
{
b = SetupFindFirstLine( hinf, L"SetupData", L"LoadIdentifier", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
b = SetupGetStringField(
&context,
1,
g_Options.szDescription,
ARRAYSIZE(g_Options.szDescription),
NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
// if this hasn't been substituted from the strings section, then
// do the lookup manually. to do this skip and remove the "%"s
if (g_Options.szDescription[0] == L'%' &&
g_Options.szDescription[wcslen(g_Options.szDescription)-1] == L'%') {
g_Options.szDescription[wcslen(g_Options.szDescription)-1] = L'\0';
lstrcpyn(szTemp,&g_Options.szDescription[1],ARRAYSIZE(szTemp));
b = SetupFindFirstLine(
hinf,
L"Strings",
szTemp,
&context );
if ( !b ) {
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
b = SetupGetStringField(
&context,
1,
g_Options.szDescription,
ARRAYSIZE(g_Options.szDescription),
NULL );
if ( !b ) {
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
}
DebugMsg( "Image Description: %s\n", g_Options.szDescription );
b = SetupFindFirstLine( hinf, L"SetupData", L"DefaultPath", &context );
if ( b )
{
b = SetupGetStringField(
&context,
1,
szTemp,
ARRAYSIZE(szTemp),
NULL );
if (b) {
PWSTR p;
p = wcschr( szTemp, '\\');
if (p) {
p += 1;
} else {
p = szTemp;
}
lstrcpyn( g_Options.szInstallationName, p, ARRAYSIZE(g_Options.szInstallationName) );
DebugMsg( "Image Path: %s\n", g_Options.szInstallationName );
}
}
}
SetupCloseInfFile( hinf );
//
// build the path to layout.inf
//
lstrcpyn( szFilepath, g_Options.szSourcePath, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, L"layout.inf", ARRAYSIZE(szFilepath) );
//
// open the file
//
hinf = SetupOpenInfFile( szFilepath, NULL, INF_STYLE_WIN4, &uLineNum);
if ( hinf == INVALID_HANDLE_VALUE ) {
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) {
b = SetupFindFirstLine( hinf, L"SourceDisksNames.x86", L"1", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
}
if ( g_Options.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ) {
b = SetupFindFirstLine( hinf, L"SourceDisksNames.ia64", L"1", &context );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
}
if ( b ) {
b = SetupGetStringField( &context, 1, g_Options.szWorkstationDiscName, ARRAYSIZE(g_Options.szWorkstationDiscName), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
DebugMsg( "Workstation Disc Name: %s\n", g_Options.szWorkstationDiscName );
b = SetupGetStringField( &context, 2, g_Options.szWorkstationTagFile, ARRAYSIZE(g_Options.szWorkstationTagFile), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
DebugMsg( "Workstation Tag File: %s\n", g_Options.szWorkstationTagFile);
b = SetupGetStringField( &context, 4, g_Options.szWorkstationSubDir, ARRAYSIZE(g_Options.szWorkstationSubDir), NULL );
if ( !b )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError( ) ) );
ErrorBox( hDlg, szFilepath );
goto Cleanup;
}
DebugMsg( "Workstation Sub Dir: %s\n", g_Options.szWorkstationSubDir );
}
SetupCloseInfFile( hinf );
hinf = INVALID_HANDLE_VALUE;
//
// build the path to setupp.ini
//
lstrcpyn( szFilepath, g_Options.szSourcePath, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, g_Options.ProcessorArchitectureString, ARRAYSIZE(szFilepath));
ConcatenatePaths( szFilepath, L"setupp.ini", ARRAYSIZE(szFilepath));
b = GetPrivateProfileStruct(L"Pid",
L"ExtraData",
szPidExtraData,
sizeof(szPidExtraData),
szFilepath);
if ( !b )
{
MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_SETUP_INI_MISSING_OR_INVALID, MB_OK );
hr = E_FAIL;
goto Cleanup;
}
//
// For a valid full (non-upgrade) PID, the fourth and sixth bytes
// are odd.
//
if (((szPidExtraData[3] % 2) == 0) || ((szPidExtraData[5] % 2) == 0))
{
MessageBoxFromStrings( hDlg, IDS_NOT_NT5_MEDIA_SOURCE_TITLE, IDS_UPGRADE_VERSION_NOT_SUPPORTED, MB_OK );
hr = E_FAIL;
goto Cleanup;
}
hr = S_OK;
Cleanup:
if ( hinf != INVALID_HANDLE_VALUE ) {
SetupCloseInfFile( hinf );
}
HRETURN(hr);
}
HRESULT
GetHelpAndDescriptionTextFromSif(
OUT PWSTR HelpText,
IN DWORD HelpTextSizeInChars,
OUT PWSTR DescriptionText,
IN DWORD DescriptionTextInChars
)
{
WCHAR szSourcePath[MAX_PATH*2];
WCHAR TempPath[MAX_PATH];
WCHAR TempFile[MAX_PATH];
HINF hInf;
UINT uLineNum;
HRESULT hr;
INFCONTEXT context;
PCWSTR szFileName = L"ristndrd.sif" ;
//
// Create the path to the default SIF file
//
_snwprintf( szSourcePath,
ARRAYSIZE(szSourcePath),
L"%s\\%s",
g_Options.szSourcePath,
szFileName );
TERMINATE_BUFFER(szSourcePath);
if (GetTempPath(ARRAYSIZE(TempPath), TempPath) &&
GetTempFileName(TempPath, L"RIS", 0, TempFile ) &&
SetupDecompressOrCopyFile( szSourcePath, TempFile, NULL ) == ERROR_SUCCESS) {
//
// first try INF_STYLE_WIN4, and if that fails, then try
// INF_STYLE_OLDNT (in case the inf doesn't have a [version] section.
//
hInf = SetupOpenInfFile( TempFile, NULL, INF_STYLE_WIN4, &uLineNum);
if (hInf == INVALID_HANDLE_VALUE) {
hInf = SetupOpenInfFile( TempFile, NULL, INF_STYLE_OLDNT, &uLineNum);
if (hInf == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e1;
}
}
if (!SetupFindFirstLine( hInf, L"OSChooser", L"Help", &context )) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e2;
}
if (!SetupGetStringField(
&context,
1,
HelpText,
HelpTextSizeInChars,
NULL )) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e2;
}
if (!SetupFindFirstLine( hInf, L"OSChooser", L"Description", &context )) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e2;
}
if (!SetupGetStringField(
&context,
1,
DescriptionText,
DescriptionTextInChars,
NULL )) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e2;
}
} else {
hr = HRESULT_FROM_WIN32(GetLastError());
goto e0;
}
hr = S_OK;
e2:
SetupCloseInfFile( hInf );
e1:
DeleteFile( TempFile );
e0:
return(hr);
}
//
// CheckIntelliMirrorDrive( )
//
HRESULT
CheckIntelliMirrorDrive(
HWND hDlg )
{
TraceFunc( "CheckIntelliMirrorDrive( )\n" );
HRESULT hr = S_OK;
BOOL b;
DWORD dw;
WCHAR sz[ MAX_PATH ];
WCHAR szExpanded[ MAX_PATH ];
WCHAR szVolumePath[ MAX_PATH ];
WCHAR szVolumeName[ MAX_PATH ];
WCHAR szVolumePath2[ MAX_PATH ];
WCHAR szVolumeName2[ MAX_PATH ];
WCHAR szFileSystemType[ MAX_PATH ];
UINT uDriveType = DRIVE_UNKNOWN;
#ifdef _X86_
WCHAR szBootDir[3];
#endif
//
// Get the real volume name for the target directory.
//
b = GetVolumePathName( g_Options.szIntelliMirrorPath, szVolumePath, ARRAYSIZE( szVolumePath ));
if (b) {
b = GetVolumeNameForVolumeMountPoint( szVolumePath, szVolumeName, ARRAYSIZE( szVolumeName ));
}
//
// Make sure the device is not a removable media, CDROM, RamDisk, etc...
// Only allow fixed disks.
//
if (b) {
uDriveType = GetDriveType( szVolumeName );
}
if ( !b || (uDriveType != DRIVE_FIXED) )
{
MessageBoxFromStrings( hDlg,
IDS_FIXEDDISK_CAPTION,
IDS_FIXEDDISK_TEXT,
MB_OK | MB_ICONSTOP );
goto Error;
}
//
// Get the real volume name for the system volume (%windir%).
//
// Get the default path which happens to be the
// SystemDrive:\IntelliMirror
//
dw = LoadString( g_hinstance, IDS_DEFAULTPATH, sz, ARRAYSIZE( sz ));
Assert( dw );
dw = ExpandEnvironmentStrings( sz, szExpanded, ARRAYSIZE( szExpanded ));
Assert( dw );
b = GetVolumePathName( szExpanded, szVolumePath2, ARRAYSIZE( szVolumePath2 ));
Assert( b );
b = GetVolumeNameForVolumeMountPoint( szVolumePath2, szVolumeName2, ARRAYSIZE( szVolumeName2 ));
Assert( b );
//
// Don't let the target directory volume be the same as the system volume.
//
if ( StrCmpI( szVolumeName, szVolumeName2 ) == 0 )
{
MessageBoxFromStrings( hDlg,
IDS_SAME_DRIVE_AS_SYSTEM_TITLE,
IDS_SAME_DRIVE_AS_SYSTEM_MESSAGE,
MB_OK | MB_ICONSTOP );
goto Error;
}
#ifdef _X86_
//
// See if the system partition (the one with boot.ini on it)
// is the drive the user has selected. We can't allow this
// either since SIS might hide boot.ini.
//
b = x86DetermineSystemPartition( NULL, &szBootDir[0] );
if ( !b )
{
szBootDir[0] = L'C';
}
szBootDir[1] = L':';
szBootDir[2] = L'\\';
b = GetVolumePathName( szBootDir, szVolumePath2, ARRAYSIZE( szVolumePath2 ));
Assert( b );
b = GetVolumeNameForVolumeMountPoint( szVolumePath2, szVolumeName2, ARRAYSIZE( szVolumeName2 ));
Assert( b );
//
// Don't let the target directory volume be the same as the boot volume.
//
if ( StrCmpI( szVolumeName, szVolumeName2 ) == 0 )
{
MessageBoxFromStrings( hDlg,
IDS_SAME_DRIVE_AS_BOOT_PARTITION_TITLE,
IDS_SAME_DRIVE_AS_BOOT_PARTITION,
MB_OK | MB_ICONSTOP );
goto Error;
}
#endif
//
// Check to see if the IMirror directory will live on an NTFS
// file system.
//
b = GetVolumeInformation( szVolumeName,
NULL,
0,
NULL,
NULL,
NULL,
szFileSystemType,
ARRAYSIZE( szFileSystemType ));
if ( !b || StrCmpNI( szFileSystemType, L"NTFS", 4 ) != 0 ) {
MessageBoxFromStrings( hDlg,
IDS_SHOULD_BE_NTFS_TITLE,
IDS_SHOULD_BE_NTFS_MESSAGE,
MB_OK | MB_ICONSTOP );
goto Error;
}
if ( 0xFFFFffff != GetFileAttributes( g_Options.szIntelliMirrorPath ) )
{
INT iResult = MessageBoxFromStrings( hDlg,
IDS_DIRECTORYEXISTS_CAPTION,
IDS_DIRECTORYEXISTS_TEXT,
MB_YESNO | MB_ICONQUESTION );
if ( iResult == IDNO )
goto Error;
}
Cleanup:
HRETURN(hr);
Error:
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 );
hr = E_FAIL;
goto Cleanup;
}
VOID
ConcatenatePaths(
IN OUT LPWSTR Path1,
IN LPCWSTR Path2,
IN ULONG Path1Length
)
/*++
Routine Description:
Concatenate two path strings together, supplying a path separator
character (\) if necessary between the 2 parts.
Arguments:
Path1 - supplies prefix part of path. Path2 is concatenated to Path1.
Path2 - supplies the suffix part of path. If Path1 does not end with a
path separator and Path2 does not start with one, then a path sep
is appended to Path1 before appending Path2.
Path1Length - supplies the size in WCHARs of the buffer pointed to by
Path1. The string will be truncated as necessary to not
overflow that size.
Return Value:
None.
--*/
{
BOOL NeedBackslash = TRUE;
DWORD l = (DWORD)wcslen( Path1 );
//
// Determine whether we need to stick a backslash between the components.
//
if ( (l != 0) && (Path1[l-1] == L'\\') ) {
NeedBackslash = FALSE;
}
if ( *Path2 == L'\\' ) {
if ( NeedBackslash ) {
NeedBackslash = FALSE;
} else {
//
// Not only do we not need a backslash, but we need to eliminate
// one before concatenating.
//
Path2++;
}
}
if ( NeedBackslash ) {
wcsncat( Path1, L"\\", Path1Length - lstrlen(Path1) - 1 );
Path1[Path1Length-1] = 0;
}
wcsncat( Path1, Path2, Path1Length - lstrlen(Path1) - 1);
Path1[Path1Length-1] = 0;
return;
}
//
// FindImageSource( )
//
HRESULT
FindImageSource(
HWND hDlg )
{
TraceFunc( "FindImageSource( )\n" );
HANDLE hFile;
WCHAR szFilePath[ MAX_PATH ];
UNREFERENCED_PARAMETER(hDlg);
//
// Look for txtsetup.sif where we think the files are located.
// txtsetup.sif is in an architecture-specific subdirectory.
//
lstrcpyn( szFilePath, g_Options.szSourcePath, ARRAYSIZE(szFilePath) );
ConcatenatePaths( szFilePath, g_Options.ProcessorArchitectureString, ARRAYSIZE(szFilePath));
ConcatenatePaths( szFilePath, L"\\txtsetup.sif", ARRAYSIZE(szFilePath));
hFile = CreateFile( szFilePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
if ( hFile != INVALID_HANDLE_VALUE )
{
CloseHandle( hFile );
HRETURN(S_OK);
}
HRETURN( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) );
}
HRESULT
GetSetRanFlag(
BOOL bQuery,
BOOL bClear
)
/*++
Routine Description:
Set's or Get's the state of a registry flag that indicates setup has been
run before.
Arguments:
bQuery - if TRUE, indicates that the registry flag should be queried
bClear - only valid if bQuery is FALSE. If this parameter is TRUE,
it indicates that the flag should be set to the cleared state.
FALSE indicates that the flag should be set.
Return Value:
HRESULT indicating outcome.
--*/
{
LONG lResult;
HKEY hkeySetup;
HRESULT Result = E_FAIL;
lResult = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
0,
bQuery
? KEY_QUERY_VALUE
: KEY_SET_VALUE,
&hkeySetup);
if ( lResult == ERROR_SUCCESS ) {
DWORD dwValue = (bClear == FALSE) ? 1 : 0;
DWORD cbValue = sizeof(dwValue);
DWORD type;
if (bQuery) {
lResult = RegQueryValueEx( hkeySetup, L"RemInst", NULL, &type, (LPBYTE)&dwValue, &cbValue );
if (lResult == ERROR_SUCCESS) {
Result = (dwValue == 1)
? S_OK
: E_FAIL;
} else {
Result = HRESULT_FROM_WIN32(lResult);
}
} else {
lResult = RegSetValueEx( hkeySetup, L"RemInst", NULL, REG_DWORD, (LPBYTE)&dwValue, cbValue );
Result = HRESULT_FROM_WIN32(lResult);
}
RegCloseKey( hkeySetup );
} else {
Result = HRESULT_FROM_WIN32(lResult);
}
return(Result);
}
//
// GetNtVersionInfo( )
//
// Retrieves the build version from the kernel
//
DWORD
MyGetFileVersionInfo(
PCWSTR FilePath
)
/*++
Routine Description:
Retrieve the version information from the specified file.
Arguments:
FilePath - Fully qualified path to the file we will be
examining.
Return Value:
DWORD - zero on failure.
--*/
{
DWORD FileVersionInfoSize;
DWORD VersionHandle;
PVOID VersionInfo;
VS_FIXEDFILEINFO * FixedFileInfo;
UINT FixedFileInfoLength;
DWORD Version = 0;
FileVersionInfoSize = GetFileVersionInfoSize(FilePath, &VersionHandle);
if (FileVersionInfoSize == 0) {
goto e0;
}
VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize );
if (VersionInfo == NULL) {
goto e0;
}
if (!GetFileVersionInfo(
FilePath,
VersionHandle,
FileVersionInfoSize,
VersionInfo)) {
goto e1;
}
if (!VerQueryValue(
VersionInfo,
L"\\",
(LPVOID*)&FixedFileInfo,
&FixedFileInfoLength)) {
goto e1;
}
Version = HIWORD(FixedFileInfo->dwFileVersionLS);
e1:
LocalFree( VersionInfo );
e0:
RETURN( Version );
}
BOOLEAN
GetBuildNumberFromImagePath(
PDWORD pdwVersion,
PCWSTR SearchDir,
PCWSTR SubDir OPTIONAL
)
{
WCHAR Path[MAX_PATH];
BOOLEAN fResult = FALSE;
TraceFunc("GetNtVersionInfo( )\n");
*pdwVersion = 0;
//
// build a path to the kernel
//
// Resulting string should be something like:
// "\\server\reminst\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
//
if (!SearchDir) {
RETURN( fResult );
}
lstrcpyn(Path, SearchDir, ARRAYSIZE(Path));
if (SubDir) {
ConcatenatePaths( Path, SubDir, ARRAYSIZE(Path));
}
ConcatenatePaths( Path, L"ntkrnlmp.exe", ARRAYSIZE(Path));
//
// Go get his version info. We'll get zero back on failure.
//
*pdwVersion = MyGetFileVersionInfo( Path );
fResult = (*pdwVersion != 0);
RETURN( fResult );
}
VOID
GetProcessorType(
)
/*++
Routine Description:
This function will pre-populate the g_Options.ProcessorArchitectureString variable
with a default value. This value is based on the processor
architecture we're currently running on.
We'll use this value to determine which backing file should
be used to generate the remote install flat image on the
server.
Arguments:
None.
Return Value:
None.
--*/
{
SYSTEM_INFO si;
if( g_Options.ProcessorArchitectureString[0] == TEXT('\0') ) {
//
// We haven't been initialized yet.
//
GetSystemInfo( &si );
switch (si.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_IA64:
g_Options.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
lstrcpyn( g_Options.ProcessorArchitectureString, L"ia64", ARRAYSIZE(g_Options.ProcessorArchitectureString));
break;
//
// if we get here, assume it's x86
//
default:
g_Options.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
lstrcpyn( g_Options.ProcessorArchitectureString, L"i386", ARRAYSIZE(g_Options.ProcessorArchitectureString));
break;
}
}
}