810 lines
20 KiB
C++
810 lines
20 KiB
C++
|
/****************************************************************************
|
||
|
|
||
|
Copyright (c) Microsoft Corporation 1998
|
||
|
All rights reserved
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "utils.h"
|
||
|
#include "callback.h"
|
||
|
#include "welcome.h"
|
||
|
#include "compat.h"
|
||
|
#include "serverdlg.h"
|
||
|
#include "directory.h"
|
||
|
#include "sif.h"
|
||
|
#include "complete.h"
|
||
|
#include "summary.h"
|
||
|
#include "tasks.h"
|
||
|
#include "setupdlg.h"
|
||
|
#include "appldlg.h"
|
||
|
#include "setup.h"
|
||
|
#include "errorlog.h"
|
||
|
|
||
|
// Must have this...
|
||
|
extern "C" {
|
||
|
#include <sysprep_.h>
|
||
|
#include <spapip.h>
|
||
|
//
|
||
|
// SYSPREP globals
|
||
|
//
|
||
|
BOOL NoSidGen = FALSE; // always generate new SID
|
||
|
BOOL PnP = FALSE; // always PNP the system
|
||
|
BOOL FactoryPreinstall = FALSE; // NOT a Factory Pre-Install case
|
||
|
BOOL bMiniSetup = TRUE; // Run Mini-Setup, not MSOOBE
|
||
|
HINSTANCE ghInstance = NULL; // Global instance handle
|
||
|
}
|
||
|
|
||
|
DEFINE_MODULE("RIPREP");
|
||
|
|
||
|
// Globals
|
||
|
HINSTANCE g_hinstance = NULL;
|
||
|
WCHAR g_ServerName[ MAX_PATH ];
|
||
|
WCHAR g_MirrorDir[ MAX_PATH ];
|
||
|
WCHAR g_Language[ MAX_PATH ];
|
||
|
WCHAR g_ImageName[ MAX_PATH ];
|
||
|
WCHAR g_Architecture[ 16 ];
|
||
|
WCHAR g_Description[ REMOTE_INSTALL_MAX_DESCRIPTION_CHAR_COUNT ];
|
||
|
WCHAR g_HelpText[ REMOTE_INSTALL_MAX_HELPTEXT_CHAR_COUNT ];
|
||
|
WCHAR g_SystemRoot[ MAX_PATH ] = L"Mirror1\\userdata\\winnt";
|
||
|
WCHAR g_WinntDirectory[ MAX_PATH ];
|
||
|
WCHAR g_HalName[32];
|
||
|
WCHAR g_ProductId[4];
|
||
|
DWORD g_dwWinntDirLength;
|
||
|
BOOLEAN g_fQuietFlag = FALSE;
|
||
|
BOOLEAN g_fErrorOccurred = FALSE;
|
||
|
BOOLEAN g_fRebootOnExit = FALSE;
|
||
|
DWORD g_dwLogFileStartLow;
|
||
|
DWORD g_dwLogFileStartHigh;
|
||
|
PCRITICAL_SECTION g_pLogCritSect = NULL;
|
||
|
HANDLE g_hLogFile = INVALID_HANDLE_VALUE;
|
||
|
OSVERSIONINFO OsVersion;
|
||
|
BOOLEAN g_CommandLineArgsValid = TRUE;
|
||
|
BOOLEAN g_OEMDesktop = FALSE;
|
||
|
|
||
|
|
||
|
// Constants
|
||
|
#define NUMBER_OF_PAGES 15
|
||
|
#define SMALL_BUFFER_SIZE 256
|
||
|
#define OPTION_UNKNOWN 0
|
||
|
#define OPTION_DEBUG 1
|
||
|
#define OPTION_FUNC 2
|
||
|
#define OPTION_QUIET 3
|
||
|
#define OPTION_PNP 4
|
||
|
#define OPTION_OEMDESKTOP 5
|
||
|
|
||
|
//
|
||
|
// Adds a page to the dialog.
|
||
|
//
|
||
|
void
|
||
|
AddPage(
|
||
|
LPPROPSHEETHEADER ppsh,
|
||
|
UINT id,
|
||
|
DLGPROC pfn,
|
||
|
UINT idTitle,
|
||
|
UINT idSubtitle )
|
||
|
{
|
||
|
PROPSHEETPAGE psp;
|
||
|
TCHAR szTitle[ SMALL_BUFFER_SIZE ];
|
||
|
TCHAR szSubTitle[ SMALL_BUFFER_SIZE ];
|
||
|
|
||
|
ZeroMemory( &psp, sizeof(psp) );
|
||
|
psp.dwSize = sizeof(psp);
|
||
|
psp.dwFlags = PSP_DEFAULT | PSP_USETITLE;
|
||
|
if ( id == IDD_WELCOME || id == IDD_COMPLETE )
|
||
|
{
|
||
|
psp.dwFlags |= PSP_HIDEHEADER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
psp.dwFlags |= PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
|
||
|
|
||
|
if ( idTitle )
|
||
|
{
|
||
|
DWORD dw;
|
||
|
|
||
|
dw = LoadString( g_hinstance, idTitle, szTitle, ARRAYSIZE(szTitle) );
|
||
|
Assert( dw );
|
||
|
psp.pszHeaderTitle = szTitle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
psp.pszHeaderTitle = NULL;
|
||
|
}
|
||
|
|
||
|
if ( idSubtitle )
|
||
|
{
|
||
|
DWORD dw;
|
||
|
|
||
|
dw = LoadString( g_hinstance, idSubtitle , szSubTitle, ARRAYSIZE(szSubTitle) );
|
||
|
Assert( dw );
|
||
|
psp.pszHeaderSubTitle = szSubTitle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
psp.pszHeaderSubTitle = NULL;
|
||
|
}
|
||
|
}
|
||
|
psp.pszTitle = MAKEINTRESOURCE( IDS_APPNAME );
|
||
|
psp.hInstance = ppsh->hInstance;
|
||
|
psp.pszTemplate = MAKEINTRESOURCE(id);
|
||
|
psp.pfnDlgProc = pfn;
|
||
|
|
||
|
ppsh->phpage[ ppsh->nPages ] = CreatePropertySheetPage( &psp );
|
||
|
if ( ppsh->phpage[ ppsh->nPages ] )
|
||
|
ppsh->nPages++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Creates the UI pages and kicks off the property sheet.
|
||
|
//
|
||
|
HRESULT
|
||
|
WizardPages( )
|
||
|
{
|
||
|
TraceFunc( "WizardPages( )\n" );
|
||
|
|
||
|
HRESULT hr;
|
||
|
HPROPSHEETPAGE rPages[ NUMBER_OF_PAGES ];
|
||
|
PROPSHEETHEADER pshead;
|
||
|
INT_PTR iResult;
|
||
|
|
||
|
ZeroMemory( &pshead, sizeof(pshead) );
|
||
|
pshead.dwSize = sizeof(pshead);
|
||
|
pshead.dwFlags = PSH_WIZARD97 | PSH_PROPTITLE | PSH_USEHICON
|
||
|
| PSH_WATERMARK | PSH_HEADER;
|
||
|
pshead.hInstance = g_hinstance;
|
||
|
pshead.pszCaption = MAKEINTRESOURCE( IDS_APPNAME );
|
||
|
pshead.phpage = rPages;
|
||
|
pshead.pszbmWatermark = MAKEINTRESOURCE( IDB_TITLEPAGE );
|
||
|
pshead.pszbmHeader = MAKEINTRESOURCE( IDB_HEADER );
|
||
|
|
||
|
|
||
|
AddPage( &pshead, IDD_WELCOME, WelcomeDlgProc, 0, 0 );
|
||
|
AddPage( &pshead, IDD_SERVER, ServerDlgProc, IDS_SERVER_TITLE, IDS_SERVER_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_OSDIRECTORY, DirectoryDlgProc, IDS_DIRECTORY_TITLE, IDS_DIRECTORY_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_DEFAULTSIF, SIFDlgProc, IDS_SIF_TITLE, IDS_SIF_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_COMPAT, CompatibilityDlgProc, IDS_COMPAT_TITLE, IDS_COMPAT_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_STOPSVCWRN, StopServiceWrnDlgProc, IDS_STOPSVC_TITLE, IDS_STOPSVC_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_STOPSVC, DoStopServiceDlgProc, IDS_STOPSVC_TITLE, IDS_STOPSVC_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_APPLICATIONS_RUNNING, ApplicationDlgProc, IDS_APPLICATION_TITLE, IDS_APPLICATION_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_SUMMARY, SummaryDlgProc, IDS_FINISH_TITLE, IDS_FINISH_SUBTITLE );
|
||
|
AddPage( &pshead, IDD_COMPLETE, CompleteDlgProc, 0, 0 );
|
||
|
|
||
|
iResult = PropertySheet( &pshead );
|
||
|
switch(iResult)
|
||
|
{
|
||
|
case 0:
|
||
|
hr = E_FAIL;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = S_OK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
RETURN(hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// IsWhiteSpace()
|
||
|
//
|
||
|
BOOL
|
||
|
IsWhiteSpace( WCHAR ch )
|
||
|
{
|
||
|
if ( ch <=32 )
|
||
|
return TRUE;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CheckWhichOption()
|
||
|
DWORD
|
||
|
CheckWhichOption(
|
||
|
LPWSTR pszOption )
|
||
|
{
|
||
|
WCHAR szOptions[ 32 ];
|
||
|
DWORD dw;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if ( StrCmpNI( pszOption, L"debug", 5 ) == 0 )
|
||
|
return OPTION_DEBUG;
|
||
|
if ( StrCmpNI( pszOption, L"func", 4 ) == 0 )
|
||
|
return OPTION_FUNC;
|
||
|
#endif
|
||
|
|
||
|
// Check for quiet flag
|
||
|
dw = LoadString( g_hinstance, IDS_QUIET, szOptions, ARRAYSIZE( szOptions ) );
|
||
|
Assert( dw );
|
||
|
if ( StrCmpNI( pszOption, szOptions, wcslen(szOptions) ) == 0 )
|
||
|
return OPTION_QUIET;
|
||
|
|
||
|
if ( StrCmpNI( pszOption, L"PNP", 3 ) == 0 )
|
||
|
return OPTION_PNP;
|
||
|
|
||
|
//
|
||
|
// By default, the Setup guys are going to remove all the desktop icons
|
||
|
// during MiniSetup. We'd like to keep those around for riprep installs,
|
||
|
// so by default, we're going to set some registry keys to keep the
|
||
|
// user's desktop around. However, if the user gives us a -OEMDesktop flag,
|
||
|
// then don't set these flags and allow the desktop to be cleaned up.
|
||
|
//
|
||
|
if( StrCmpNI( pszOption, L"OEMDesktop", 10 ) == 0 ) {
|
||
|
return OPTION_OEMDESKTOP;
|
||
|
}
|
||
|
|
||
|
return OPTION_UNKNOWN;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ParseCommandLine()
|
||
|
//
|
||
|
void
|
||
|
ParseCommandLine( LPWSTR lpCmdLine )
|
||
|
{
|
||
|
WCHAR szPath[ MAX_PATH ];
|
||
|
LPWSTR psz = NULL;
|
||
|
BOOL endOfCommandLine;
|
||
|
|
||
|
//
|
||
|
// Check to see if the command line has the servername on it.
|
||
|
//
|
||
|
g_ServerName[0] = L'\0';
|
||
|
if ( lpCmdLine[0] == L'\\' && lpCmdLine[1] == L'\\' )
|
||
|
{
|
||
|
psz = StrChr( &lpCmdLine[2], L'\\' );
|
||
|
if ( psz && psz != &lpCmdLine[2] )
|
||
|
{
|
||
|
ZeroMemory( g_ServerName, sizeof(g_ServerName) );
|
||
|
wcsncpy( g_ServerName, &lpCmdLine[2], (DWORD)(psz - &lpCmdLine[2]) );
|
||
|
}
|
||
|
}
|
||
|
// See if it is a quoted path as well
|
||
|
if ( lpCmdLine[0] == L'\"' && lpCmdLine[1] == L'\\' && lpCmdLine[2] == L'\\' )
|
||
|
{
|
||
|
psz = StrChr( &lpCmdLine[3], L'\\' );
|
||
|
if ( psz && psz != &lpCmdLine[3] )
|
||
|
{
|
||
|
ZeroMemory( g_ServerName, sizeof(g_ServerName) );
|
||
|
wcsncpy( g_ServerName, &lpCmdLine[3], (DWORD)(psz - &lpCmdLine[3]) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// See if there is a whitespace break
|
||
|
psz = StrChr( lpCmdLine, L' ' );
|
||
|
if ( psz )
|
||
|
{ // yes... search backwards from the whitespace for a slash.
|
||
|
psz = StrRChr( lpCmdLine, psz, L'\\' );
|
||
|
}
|
||
|
else
|
||
|
{ // no... search backwards from the end of the command line for a slash.
|
||
|
psz = StrRChr( lpCmdLine, &lpCmdLine[ wcslen( lpCmdLine ) ], L'\\' );
|
||
|
}
|
||
|
|
||
|
// Found the starting path, now try to set the current directory
|
||
|
// to this.
|
||
|
if ( psz )
|
||
|
{
|
||
|
ZeroMemory( szPath, sizeof(szPath) );
|
||
|
wcsncpy( szPath, lpCmdLine, (DWORD)(psz - lpCmdLine) );
|
||
|
|
||
|
// If quoted, add a trailing quote to the path
|
||
|
if ( lpCmdLine[0] == L'\"' ) {
|
||
|
wcscat( szPath, L"\"" );
|
||
|
}
|
||
|
|
||
|
DebugMsg( "Set CD to %s\n", szPath );
|
||
|
SetCurrentDirectory( szPath );
|
||
|
}
|
||
|
|
||
|
// Parse for command line arguments
|
||
|
if (!psz) {
|
||
|
psz = lpCmdLine;
|
||
|
}
|
||
|
endOfCommandLine = FALSE;
|
||
|
while (!endOfCommandLine && (*psz != L'\0'))
|
||
|
{
|
||
|
if ( *psz == '/' || *psz == '-' )
|
||
|
{
|
||
|
LPWSTR pszStartOption = ++psz;
|
||
|
|
||
|
while (*psz && !IsWhiteSpace( *psz ) )
|
||
|
psz++;
|
||
|
|
||
|
if (*psz == L'\0') {
|
||
|
endOfCommandLine = TRUE;
|
||
|
} else {
|
||
|
*psz = '\0'; // terminate
|
||
|
}
|
||
|
|
||
|
switch ( CheckWhichOption( pszStartOption ) )
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
case OPTION_DEBUG:
|
||
|
g_dwTraceFlags |= 0x80000000; // not defined, but not zero either
|
||
|
break;
|
||
|
case OPTION_FUNC:
|
||
|
g_dwTraceFlags |= TF_FUNC;
|
||
|
break;
|
||
|
#endif
|
||
|
case OPTION_QUIET:
|
||
|
g_fQuietFlag = TRUE;
|
||
|
break;
|
||
|
|
||
|
case OPTION_PNP:
|
||
|
PnP = !PnP; // toggle
|
||
|
break;
|
||
|
|
||
|
case OPTION_OEMDESKTOP:
|
||
|
g_OEMDesktop = TRUE; // The user want to clean the desktop.
|
||
|
break;
|
||
|
|
||
|
case OPTION_UNKNOWN:
|
||
|
|
||
|
MessageBoxFromMessage(
|
||
|
NULL,
|
||
|
MSG_USAGE,
|
||
|
FALSE,
|
||
|
MAKEINTRESOURCE(IDS_APPNAME),
|
||
|
MB_OK );
|
||
|
|
||
|
g_CommandLineArgsValid = FALSE;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
psz++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// GetWorkstationLanguage( )
|
||
|
//
|
||
|
DWORD
|
||
|
GetWorkstationLanguage( )
|
||
|
{
|
||
|
TraceFunc( "GetWorkstationLanguage( )\n" );
|
||
|
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
LANGID langID = GetSystemDefaultLangID( );
|
||
|
UINT uResult = GetLocaleInfo( langID, LOCALE_SENGLANGUAGE, g_Language, ARRAYSIZE(g_Language) );
|
||
|
if ( uResult == 0 )
|
||
|
{
|
||
|
DWORD dw;
|
||
|
dwErr = GetLastError( );
|
||
|
dw = LoadString( g_hinstance, IDS_DEFAULT_LANGUAGE, g_Language, ARRAYSIZE(g_Language));
|
||
|
Assert( dw );
|
||
|
}
|
||
|
|
||
|
RETURN(dwErr);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
GetInstalledProductType(
|
||
|
PDWORD Type,
|
||
|
PDWORD Mask );
|
||
|
|
||
|
//
|
||
|
// GetProductSKUNumber
|
||
|
//
|
||
|
DWORD
|
||
|
GetProductSKUNumber(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determine SKU number of installation, which should match the
|
||
|
producttype value in txtsetup.sif
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none.
|
||
|
|
||
|
Return value:
|
||
|
|
||
|
product sku number. if it fails, we set the return value to 0, which
|
||
|
is the sku code for professional.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TraceFunc( "GetProductSKUNumber( )\n" );
|
||
|
|
||
|
DWORD ProductType, ProductSuiteMask;
|
||
|
|
||
|
if (!GetInstalledProductType( &ProductType, &ProductSuiteMask )) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (ProductType == VER_NT_SERVER) {
|
||
|
if (ProductSuiteMask & VER_SUITE_DATACENTER) {
|
||
|
return 3;
|
||
|
}
|
||
|
|
||
|
if (ProductSuiteMask & VER_SUITE_ENTERPRISE) {
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (ProductSuiteMask & VER_SUITE_PERSONAL) {
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// GetHalName( )
|
||
|
//
|
||
|
DWORD
|
||
|
GetHalName(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determine the actual name of the HAL running on the system.
|
||
|
|
||
|
The actual name of the hal is stored in the originalfilename
|
||
|
in the version resource.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none.
|
||
|
|
||
|
Return value:
|
||
|
|
||
|
Win32 error code indicating outcome.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TraceFunc( "GetHalName( )\n" );
|
||
|
|
||
|
DWORD dwErr = ERROR_GEN_FAILURE;
|
||
|
WCHAR HalPath[MAX_PATH];
|
||
|
DWORD VersionHandle;
|
||
|
DWORD FileVersionInfoSize;
|
||
|
PVOID VersionInfo = NULL;
|
||
|
DWORD *Language,LanguageSize;
|
||
|
WCHAR OriginalFileNameString[64];
|
||
|
PWSTR ActualHalName;
|
||
|
|
||
|
|
||
|
//
|
||
|
// the hal is in system32 directory, build a path to it.
|
||
|
//
|
||
|
if (!GetSystemDirectory(HalPath,ARRAYSIZE(HalPath))) {
|
||
|
dwErr = GetLastError();
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
wcscat(HalPath, L"\\hal.dll" );
|
||
|
|
||
|
//
|
||
|
// you must call GetFileVersionInfoSize,GetFileVersionInfo before
|
||
|
// you can call VerQueryValue()
|
||
|
//
|
||
|
FileVersionInfoSize = GetFileVersionInfoSize(HalPath, &VersionHandle);
|
||
|
if (FileVersionInfoSize == 0) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize );
|
||
|
if (VersionInfo == NULL) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (!GetFileVersionInfo(
|
||
|
HalPath,
|
||
|
0, //ignored
|
||
|
FileVersionInfoSize,
|
||
|
VersionInfo)) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ok, get the language of the file so we can look in the correct
|
||
|
// StringFileInfo section for the file name
|
||
|
//
|
||
|
if (!VerQueryValue(
|
||
|
VersionInfo,
|
||
|
L"\\VarFileInfo\\Translation",
|
||
|
(LPVOID*)&Language,
|
||
|
(PUINT)&LanguageSize)) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
wsprintf(
|
||
|
OriginalFileNameString,
|
||
|
L"\\StringFileInfo\\%04x%04x\\OriginalFilename",
|
||
|
LOWORD(*Language),
|
||
|
HIWORD(*Language));
|
||
|
|
||
|
//
|
||
|
// now retreive the actual OriginalFilename.
|
||
|
//
|
||
|
if (!VerQueryValue(
|
||
|
VersionInfo,
|
||
|
OriginalFileNameString,
|
||
|
(LPVOID*)&ActualHalName,
|
||
|
(PUINT)&LanguageSize)) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// store this off in a global so we can use it later on
|
||
|
//
|
||
|
wcscpy(g_HalName ,ActualHalName);
|
||
|
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
exit:
|
||
|
if (VersionInfo) {
|
||
|
LocalFree( VersionInfo );
|
||
|
}
|
||
|
RETURN(dwErr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// VerifyWorkstation( )
|
||
|
//
|
||
|
BOOL
|
||
|
VerifyWorkstation( )
|
||
|
{
|
||
|
TraceFunc( "VerifyWorkstation( )\n" );
|
||
|
|
||
|
HKEY hkey;
|
||
|
LONG lResult;
|
||
|
WCHAR szProductType[50] = { 0 };
|
||
|
DWORD dwType;
|
||
|
DWORD dwSize = ARRAYSIZE(szProductType);
|
||
|
BOOL fReturn = TRUE; // assume that we are not on NTServer.
|
||
|
|
||
|
// Query the registry for the product type.
|
||
|
lResult = RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
|
||
|
L"System\\CurrentControlSet\\Control\\ProductOptions",
|
||
|
0,
|
||
|
KEY_READ,
|
||
|
&hkey);
|
||
|
Assert( lResult == ERROR_SUCCESS );
|
||
|
if ( lResult != ERROR_SUCCESS )
|
||
|
goto Error;
|
||
|
|
||
|
lResult = RegQueryValueEx ( hkey,
|
||
|
L"ProductType",
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) szProductType,
|
||
|
&dwSize);
|
||
|
Assert( lResult == ERROR_SUCCESS );
|
||
|
RegCloseKey (hkey);
|
||
|
if (lResult != ERROR_SUCCESS)
|
||
|
goto Error;
|
||
|
|
||
|
if ( StrCmpI( szProductType, L"ServerNT" ) == 0 )
|
||
|
{
|
||
|
fReturn = FALSE; // NT Server
|
||
|
}
|
||
|
|
||
|
if ( StrCmpI( szProductType, L"LanmanNT" ) == 0 )
|
||
|
{
|
||
|
fReturn = FALSE; // NT Server
|
||
|
}
|
||
|
|
||
|
Error:
|
||
|
RETURN(fReturn);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// CheckUserPermissions( )
|
||
|
//
|
||
|
BOOL
|
||
|
CheckUserPermissions( )
|
||
|
{
|
||
|
TraceFunc( "CheckUserPermissions( )\n" );
|
||
|
if( !pSetupIsUserAdmin()
|
||
|
|| !pSetupDoesUserHavePrivilege(SE_SHUTDOWN_NAME)
|
||
|
|| !pSetupDoesUserHavePrivilege(SE_BACKUP_NAME)
|
||
|
|| !pSetupDoesUserHavePrivilege(SE_RESTORE_NAME)
|
||
|
|| !pSetupDoesUserHavePrivilege(SE_SYSTEM_ENVIRONMENT_NAME)) {
|
||
|
RETURN(FALSE);
|
||
|
}
|
||
|
RETURN(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// GetProcessorType( )
|
||
|
//
|
||
|
DWORD
|
||
|
GetProcessorType( )
|
||
|
{
|
||
|
TraceFunc( "GetProcessorType( )\n" );
|
||
|
|
||
|
DWORD dwErr = ERROR_INVALID_PARAMETER;
|
||
|
SYSTEM_INFO si;
|
||
|
|
||
|
GetSystemInfo( &si );
|
||
|
switch (si.wProcessorArchitecture)
|
||
|
{
|
||
|
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||
|
wcscpy( g_Architecture, L"Alpha" );
|
||
|
break;
|
||
|
|
||
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
||
|
dwErr = ERROR_SUCCESS;
|
||
|
wcscpy( g_Architecture, L"i386" );
|
||
|
break;
|
||
|
case PROCESSOR_ARCHITECTURE_IA64:
|
||
|
//dwErr = ERROR_SUCCESS;
|
||
|
wcscpy( g_Architecture, L"ia64" );
|
||
|
break;
|
||
|
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
RETURN(dwErr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// WinMain()
|
||
|
//
|
||
|
int APIENTRY
|
||
|
WinMain(
|
||
|
HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInstance,
|
||
|
LPSTR lpCmdLine,
|
||
|
int nCmdShow)
|
||
|
{
|
||
|
TraceFunc( "WinMain( ... )\n" );
|
||
|
|
||
|
HANDLE hMutex;
|
||
|
HRESULT hr = E_FAIL;
|
||
|
IMIRROR_CALLBACK Callbacks;
|
||
|
HWND hwndTasks = NULL;
|
||
|
LPWSTR pszCommandLine = GetCommandLine( );
|
||
|
BOOL fDC = FALSE;
|
||
|
|
||
|
g_hinstance = hInstance;
|
||
|
ghInstance = hInstance;
|
||
|
|
||
|
INITIALIZE_TRACE_MEMORY_PROCESS;
|
||
|
|
||
|
pSetupInitializeUtils();
|
||
|
|
||
|
// allow only one instance running at a time
|
||
|
hMutex = CreateMutex( NULL, TRUE, L"RIPREP.Mutext");
|
||
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||
|
{
|
||
|
MessageBoxFromStrings( NULL,
|
||
|
IDS_ALREADY_RUNNING_TITLE,
|
||
|
IDS_ALREADY_RUNNING_MESSAGE,
|
||
|
MB_OK | MB_ICONSTOP );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
// parse command line arguments
|
||
|
ParseCommandLine( pszCommandLine );
|
||
|
if (!g_CommandLineArgsValid) {
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Gather os version info.
|
||
|
//
|
||
|
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
GetVersionEx(&OsVersion);
|
||
|
|
||
|
// determine the language of the workstation
|
||
|
GetWorkstationLanguage( );
|
||
|
|
||
|
if (ERROR_SUCCESS != GetHalName()) {
|
||
|
MessageBoxFromStrings( NULL, IDS_INVALID_ARCHITECTURE_TITLE, IDS_INVALID_ARCHITECTURE_TEXT, MB_OK );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
wsprintf( g_ProductId, L"%d", GetProductSKUNumber() );
|
||
|
|
||
|
ProcessCompatibilityData();
|
||
|
|
||
|
// determine the processor type
|
||
|
if ( GetProcessorType( ) != ERROR_SUCCESS )
|
||
|
{
|
||
|
MessageBoxFromStrings( NULL, IDS_INVALID_ARCHITECTURE_TITLE, IDS_INVALID_ARCHITECTURE_TEXT, MB_OK );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if ( !CheckUserPermissions( ) )
|
||
|
{
|
||
|
MessageBoxFromStrings( NULL, IDS_MUST_BE_ADMINISTRATOR_TITLE, IDS_MUST_BE_ADMINISTRATOR_TEXT, MB_OK );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//
|
||
|
// No longer limited to only workstation - adamba 4/6/00
|
||
|
//
|
||
|
if ( !VerifyWorkstation( ) )
|
||
|
{
|
||
|
MessageBoxFromStrings( NULL, IDS_MUST_BE_WORKSTATION_TITLE, IDS_MUST_BE_WORKSTATION_TEXT, MB_OK );
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|
||
|
// get the name of the "Winnt" directory
|
||
|
GetEnvironmentVariable( L"windir", g_WinntDirectory, ARRAYSIZE(g_WinntDirectory));
|
||
|
g_dwWinntDirLength = wcslen( g_WinntDirectory );
|
||
|
|
||
|
// setup IMIRROR.DLL callbacks
|
||
|
Callbacks.Context = 0;
|
||
|
Callbacks.ErrorFn = &ConvTestErrorFn;
|
||
|
Callbacks.GetSetupFn = &ConvTestGetSetupFn;
|
||
|
Callbacks.NowDoingFn = &ConvTestNowDoingFn;
|
||
|
Callbacks.FileCreateFn = &ConvTestFileCreateFn;
|
||
|
Callbacks.RegSaveErrorFn = NULL;
|
||
|
Callbacks.ReinitFn = &ConvTestReinitFn;
|
||
|
Callbacks.GetMirrorDirFn = &ConvTestGetMirrorDirFn;
|
||
|
Callbacks.SetSystemDirFn = &ConvTestSetSystemFn;
|
||
|
Callbacks.AddToDoFn = &ConvAddToDoItemFn;
|
||
|
Callbacks.RemoveToDoFn = &ConvRemoveToDoItemFn;
|
||
|
Callbacks.RebootFn = &ConvRebootFn;
|
||
|
IMirrorInitCallback(&Callbacks);
|
||
|
|
||
|
// show property pages
|
||
|
hr = WizardPages( );
|
||
|
|
||
|
if ( hr != S_OK )
|
||
|
goto Cleanup;
|
||
|
|
||
|
// complete tasks... ignore the return code, not important
|
||
|
BeginProcess( hwndTasks );
|
||
|
|
||
|
// Display any errors recorded in the log, unless we are supposed
|
||
|
// to reboot now.
|
||
|
if ( g_fErrorOccurred && !g_fRebootOnExit )
|
||
|
{
|
||
|
HINSTANCE hRichedDLL;
|
||
|
|
||
|
// Make sure the RichEdit control has been initialized.
|
||
|
// Simply LoadLibbing it does this for us.
|
||
|
hRichedDLL = LoadLibrary( L"RICHED32.DLL" );
|
||
|
if ( hRichedDLL != NULL )
|
||
|
{
|
||
|
DialogBox( g_hinstance, MAKEINTRESOURCE( IDD_VIEWERRORS ), g_hMainWindow, ErrorsDlgProc );
|
||
|
FreeLibrary (hRichedDLL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
|
||
|
if (g_hCompatibilityInf != INVALID_HANDLE_VALUE) {
|
||
|
SetupCloseInfFile( g_hCompatibilityInf );
|
||
|
}
|
||
|
|
||
|
CleanupCompatibilityData();
|
||
|
|
||
|
if ( hMutex )
|
||
|
CloseHandle( hMutex );
|
||
|
|
||
|
pSetupUninitializeUtils();
|
||
|
|
||
|
UNINITIALIZE_TRACE_MEMORY;
|
||
|
|
||
|
if ( g_fRebootOnExit ) {
|
||
|
(VOID)DoShutdown(TRUE); // TRUE tells it to restart
|
||
|
}
|
||
|
|
||
|
RETURN(hr);
|
||
|
}
|