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.
923 lines
22 KiB
923 lines
22 KiB
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// File: cys.cpp
|
|
//
|
|
// Synopsis: Configure Your Server Wizard main
|
|
//
|
|
// History: 02/02/2001 JeffJon Created
|
|
|
|
#include "pch.h"
|
|
#include "resource.h"
|
|
|
|
#include "InstallationUnitProvider.h"
|
|
|
|
// include the wizard pages
|
|
#include "BeforeBeginPage.h"
|
|
#include "CustomServerPage.h"
|
|
#include "DecisionPage.h"
|
|
#include "DnsForwarderPage.h"
|
|
#include "DomainPage.h"
|
|
#include "ExpressDHCPPage.h"
|
|
#include "ExpressDNSPage.h"
|
|
#include "ExpressRebootPage.h"
|
|
#include "FileServerPage.h"
|
|
#include "FinishPage.h"
|
|
#include "IndexingPage.h"
|
|
#include "InstallationProgressPage.h"
|
|
#include "MilestonePage.h"
|
|
#include "NetbiosPage.h"
|
|
#include "POP3Page.h"
|
|
#include "PrintServerPage.h"
|
|
#include "RemoteDesktopPage.h"
|
|
#include "UninstallMilestonePage.h"
|
|
#include "UninstallProgressPage.h"
|
|
#include "WebApplicationPage.h"
|
|
#include "WelcomePage.h"
|
|
|
|
#include "ExpressRebootPage.h"
|
|
|
|
|
|
|
|
HINSTANCE hResourceModuleHandle = 0;
|
|
const wchar_t* HELPFILE_NAME = 0; // no context help available
|
|
|
|
|
|
// This is the name of a mutex that is used to see if CYS is running
|
|
|
|
const wchar_t* RUNTIME_NAME = L"cysui";
|
|
|
|
DWORD DEFAULT_LOGGING_OPTIONS =
|
|
Log::OUTPUT_TO_FILE
|
|
| Log::OUTPUT_FUNCCALLS
|
|
| Log::OUTPUT_LOGS
|
|
| Log::OUTPUT_ERRORS
|
|
| Log::OUTPUT_HEADER
|
|
| Log::OUTPUT_RUN_TIME;
|
|
|
|
|
|
// a system modal popup thingy
|
|
Popup popup(IDS_WIZARD_TITLE, true);
|
|
|
|
// this is the mutex that indicates that CYS is running.
|
|
|
|
HANDLE cysRunningMutex = INVALID_HANDLE_VALUE;
|
|
|
|
// This is a brush that is used to paint all the backgrounds. It
|
|
// needs to be created and deleted from inside main
|
|
|
|
HBRUSH brush = 0;
|
|
|
|
// these are the valid exit codes returned from the cys.exe process
|
|
|
|
enum ExitCode
|
|
{
|
|
// the operation failed.
|
|
|
|
EXIT_CODE_UNSUCCESSFUL = 0,
|
|
|
|
// the operation succeeded
|
|
|
|
EXIT_CODE_SUCCESSFUL = 1,
|
|
|
|
// other exit codes can be added here...
|
|
};
|
|
|
|
enum StartPages
|
|
{
|
|
CYS_WELCOME_PAGE = 0,
|
|
CYS_BEFORE_BEGIN_PAGE,
|
|
CYS_EXPRESS_REBOOT_PAGE,
|
|
CYS_FINISH_PAGE
|
|
};
|
|
|
|
|
|
UINT
|
|
TerminalServerPostBoot()
|
|
{
|
|
LOG_FUNCTION(TerminalServerPostBoot);
|
|
|
|
UINT startPage = CYS_WELCOME_PAGE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
SetCurrentInstallationUnit(TERMINALSERVER_SERVER);
|
|
|
|
// Create the log file
|
|
|
|
bool logFileAvailable = false;
|
|
String logName;
|
|
HANDLE logfileHandle = AppendLogFile(
|
|
CYS_LOGFILE_NAME,
|
|
logName);
|
|
if (logfileHandle &&
|
|
logfileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
LOG(String::format(L"New log file was created: %1", logName.c_str()));
|
|
logFileAvailable = true;
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Unable to create the log file!!!");
|
|
logFileAvailable = false;
|
|
}
|
|
|
|
// Prepare the finish dialog
|
|
|
|
TerminalServerInstallationUnit& tsInstallationUnit =
|
|
InstallationUnitProvider::GetInstance().GetTerminalServerInstallationUnit();
|
|
|
|
// Make sure the installation unit knows we are doing an install
|
|
|
|
tsInstallationUnit.SetInstalling(true);
|
|
|
|
if (tsInstallationUnit.GetApplicationMode() == 1)
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_TERMINAL_SERVER_REBOOT_SUCCESS));
|
|
|
|
tsInstallationUnit.SetInstallResult(INSTALL_SUCCESS);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
else
|
|
{
|
|
// Failed to install Terminal Server
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_TERMINAL_SERVER_REBOOT_FAILED));
|
|
|
|
tsInstallationUnit.SetInstallResult(INSTALL_FAILURE);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
|
|
CYS_APPEND_LOG(L"\r\n");
|
|
|
|
// Close the log file
|
|
|
|
Win::CloseHandle(logfileHandle);
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
TerminalServerUninstallPostBoot()
|
|
{
|
|
LOG_FUNCTION(TerminalServerUninstallPostBoot);
|
|
|
|
UINT startPage = CYS_WELCOME_PAGE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
SetCurrentInstallationUnit(TERMINALSERVER_SERVER);
|
|
|
|
// Create the log file
|
|
|
|
bool logFileAvailable = false;
|
|
String logName;
|
|
HANDLE logfileHandle = AppendLogFile(
|
|
CYS_LOGFILE_NAME,
|
|
logName);
|
|
if (logfileHandle &&
|
|
logfileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
LOG(String::format(L"New log file was created: %1", logName.c_str()));
|
|
logFileAvailable = true;
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Unable to create the log file!!!");
|
|
logFileAvailable = false;
|
|
}
|
|
|
|
// Prepare the finish dialog
|
|
|
|
TerminalServerInstallationUnit& tsInstallationUnit =
|
|
InstallationUnitProvider::GetInstance().GetTerminalServerInstallationUnit();
|
|
|
|
// Make sure the installation unit knows we are doing an uninstall
|
|
|
|
tsInstallationUnit.SetInstalling(false);
|
|
|
|
if (tsInstallationUnit.GetApplicationMode() == 0)
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_TERMINAL_SERVER_SUCCESS));
|
|
|
|
tsInstallationUnit.SetUninstallResult(UNINSTALL_SUCCESS);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
else
|
|
{
|
|
// Failed to uninstall Terminal Server
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_TERMINAL_SERVER_FAILED));
|
|
|
|
tsInstallationUnit.SetUninstallResult(UNINSTALL_FAILURE);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
|
|
CYS_APPEND_LOG(L"\r\n");
|
|
|
|
// Close the log file
|
|
|
|
Win::CloseHandle(logfileHandle);
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
FirstServerPostBoot()
|
|
{
|
|
LOG_FUNCTION(FirstServerPostBoot);
|
|
|
|
UINT startPage = CYS_EXPRESS_REBOOT_PAGE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
SetCurrentInstallationUnit(EXPRESS_SERVER);
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
DCPromoPostBoot()
|
|
{
|
|
LOG_FUNCTION(DCPromoPostBoot);
|
|
|
|
UINT startPage = CYS_WELCOME_PAGE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
SetCurrentInstallationUnit(DC_SERVER);
|
|
|
|
// Create the log file
|
|
|
|
bool logFileAvailable = false;
|
|
String logName;
|
|
HANDLE logfileHandle = AppendLogFile(
|
|
CYS_LOGFILE_NAME,
|
|
logName);
|
|
if (logfileHandle &&
|
|
logfileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
LOG(String::format(L"New log file was created: %1", logName.c_str()));
|
|
logFileAvailable = true;
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Unable to create the log file!!!");
|
|
logFileAvailable = false;
|
|
}
|
|
|
|
// Make sure the installation unit knows we are doing an install
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetCurrentInstallationUnit().SetInstalling(true);
|
|
|
|
// Prepare the finish page
|
|
|
|
if (State::GetInstance().IsDC())
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DOMAIN_CONTROLLER_SUCCESS));
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetADInstallationUnit().SetInstallResult(INSTALL_SUCCESS);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
else
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_DOMAIN_CONTROLLER_FAILED));
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetADInstallationUnit().SetInstallResult(INSTALL_FAILURE);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
CYS_APPEND_LOG(L"\r\n");
|
|
|
|
// Close the log file
|
|
|
|
Win::CloseHandle(logfileHandle);
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
DCDemotePostBoot()
|
|
{
|
|
LOG_FUNCTION(DCDemotePostBoot);
|
|
|
|
UINT startPage = CYS_WELCOME_PAGE;
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
SetCurrentInstallationUnit(DC_SERVER);
|
|
|
|
// Create the log file
|
|
|
|
bool logFileAvailable = false;
|
|
String logName;
|
|
HANDLE logfileHandle = AppendLogFile(
|
|
CYS_LOGFILE_NAME,
|
|
logName);
|
|
if (logfileHandle &&
|
|
logfileHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
LOG(String::format(L"New log file was created: %1", logName.c_str()));
|
|
logFileAvailable = true;
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Unable to create the log file!!!");
|
|
logFileAvailable = false;
|
|
}
|
|
|
|
// Make sure the installation unit knows we are doing an uninstall
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetCurrentInstallationUnit().SetInstalling(false);
|
|
|
|
// Prepare the finish page
|
|
|
|
if (!State::GetInstance().IsDC())
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DOMAIN_CONTROLLER_SUCCESS));
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetADInstallationUnit().SetUninstallResult(UNINSTALL_SUCCESS);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
else
|
|
{
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DOMAIN_CONTROLLER_FAILED));
|
|
|
|
InstallationUnitProvider::GetInstance().
|
|
GetADInstallationUnit().SetUninstallResult(UNINSTALL_FAILURE);
|
|
|
|
startPage = CYS_FINISH_PAGE;
|
|
}
|
|
CYS_APPEND_LOG(L"\r\n");
|
|
|
|
// Close the log file
|
|
|
|
Win::CloseHandle(logfileHandle);
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
DoRebootOperations()
|
|
{
|
|
LOG_FUNCTION(DoRebootOperations);
|
|
|
|
UINT startPage = 0;
|
|
|
|
// Check to see if we are in a reboot scenario
|
|
|
|
String homeKeyValue;
|
|
if (State::GetInstance().GetHomeRegkey(homeKeyValue))
|
|
{
|
|
// Now set the home regkey back to "home" so that we won't run
|
|
// through these again. This has to be done before doing the
|
|
// operation because the user could leave this dialog up
|
|
// and cause a reboot (like demoting a DC) and then the
|
|
// post reboot operations would run again
|
|
|
|
if (homeKeyValue.icompare(CYS_HOME_REGKEY_DEFAULT_VALUE) != 0)
|
|
{
|
|
bool result =
|
|
State::GetInstance().SetHomeRegkey(CYS_HOME_REGKEY_DEFAULT_VALUE);
|
|
|
|
ASSERT(result);
|
|
}
|
|
|
|
// Reset the must run key now that we have done the reboot stuff
|
|
|
|
bool regkeyResult = SetRegKeyValue(
|
|
CYS_HOME_REGKEY,
|
|
CYS_HOME_REGKEY_MUST_RUN,
|
|
CYS_HOME_RUN_KEY_DONT_RUN,
|
|
HKEY_LOCAL_MACHINE,
|
|
true);
|
|
ASSERT(regkeyResult);
|
|
|
|
// Set the reboot scenario in the state object so that we know we
|
|
// are running in that context
|
|
|
|
State::GetInstance().SetRebootScenario(true);
|
|
|
|
// Now run the post reboot operations if necessary
|
|
|
|
if (homeKeyValue.icompare(CYS_HOME_REGKEY_TERMINAL_SERVER_VALUE) == 0)
|
|
{
|
|
startPage = TerminalServerPostBoot();
|
|
}
|
|
else if (homeKeyValue.icompare(CYS_HOME_REGKEY_UNINSTALL_TERMINAL_SERVER_VALUE) == 0)
|
|
{
|
|
startPage = TerminalServerUninstallPostBoot();
|
|
}
|
|
else if (homeKeyValue.icompare(CYS_HOME_REGKEY_FIRST_SERVER_VALUE) == 0)
|
|
{
|
|
startPage = FirstServerPostBoot();
|
|
}
|
|
else if (homeKeyValue.icompare(CYS_HOME_REGKEY_DCPROMO_VALUE) == 0)
|
|
{
|
|
startPage = DCPromoPostBoot();
|
|
}
|
|
else if (homeKeyValue.icompare(CYS_HOME_REGKEY_DCDEMOTE_VALUE) == 0)
|
|
{
|
|
startPage = DCDemotePostBoot();
|
|
}
|
|
else
|
|
{
|
|
// We are NOT running a reboot scenario
|
|
|
|
State::GetInstance().SetRebootScenario(false);
|
|
}
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
GetStartPageFromCommandLine()
|
|
{
|
|
LOG_FUNCTION(GetStartPageFromCommandLine);
|
|
|
|
UINT startPage = 0;
|
|
|
|
StringVector args;
|
|
int argc = Win::GetCommandLineArgs(std::back_inserter(args));
|
|
|
|
if (argc > 1)
|
|
{
|
|
const String skipWelcome(L"/skipWelcome");
|
|
|
|
for (
|
|
StringVector::iterator itr = args.begin();
|
|
itr != args.end();
|
|
++itr)
|
|
{
|
|
if (itr &&
|
|
(*itr).icompare(skipWelcome) == 0)
|
|
{
|
|
startPage = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
UINT
|
|
GetStartPage()
|
|
{
|
|
LOG_FUNCTION(GetStartPage);
|
|
|
|
UINT startPage = 0;
|
|
|
|
// First check for the reboot scenarios
|
|
|
|
startPage = DoRebootOperations();
|
|
if (startPage == 0)
|
|
{
|
|
// Now look at the commandline to see if any
|
|
// switches were provided
|
|
|
|
startPage = GetStartPageFromCommandLine();
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"startPage = %1!d!",
|
|
startPage));
|
|
|
|
return startPage;
|
|
}
|
|
|
|
// This is the DlgProc of the property sheet that we are subclassing. I need
|
|
// to hold on to it so I can call it if we don't handle the message in our
|
|
// replacement DlgProc.
|
|
|
|
static WNDPROC replacedSheetWndProc = 0;
|
|
|
|
// This is the DlgProc that we will use to replace the property sheet
|
|
// DlgProc. It handles the WM_CTLCOLORDLG message to paint the background
|
|
// color
|
|
|
|
LRESULT
|
|
ReplacementWndProc(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wparam,
|
|
LPARAM lparam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLORSTATIC:
|
|
case WM_CTLCOLOREDIT:
|
|
case WM_CTLCOLORLISTBOX:
|
|
case WM_CTLCOLORSCROLLBAR:
|
|
{
|
|
HDC deviceContext = reinterpret_cast<HDC>(wparam);
|
|
|
|
ASSERT(deviceContext);
|
|
if (deviceContext)
|
|
{
|
|
SetTextColor(deviceContext, GetSysColor(COLOR_WINDOWTEXT));
|
|
SetBkColor(deviceContext, GetSysColor(COLOR_WINDOW));
|
|
}
|
|
|
|
return
|
|
reinterpret_cast<LRESULT>(
|
|
Win::GetSysColorBrush(COLOR_WINDOW));
|
|
}
|
|
|
|
default:
|
|
if (replacedSheetWndProc)
|
|
{
|
|
return ::CallWindowProc(
|
|
replacedSheetWndProc,
|
|
hwnd,
|
|
message,
|
|
wparam,
|
|
lparam);
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// This callback function is called by the property sheet. During initialization
|
|
// I use this to subclass the property sheet, replacing their DlgProc with my
|
|
// own so that I can change the background color.
|
|
|
|
int
|
|
CALLBACK
|
|
SheetCallbackProc(
|
|
HWND hwnd,
|
|
UINT message,
|
|
LPARAM /*lparam*/)
|
|
{
|
|
LOG_FUNCTION(SheetCallbackProc);
|
|
|
|
if (message == PSCB_INITIALIZED)
|
|
{
|
|
LONG_PTR ptr = 0;
|
|
HRESULT hr = Win::GetWindowLongPtr(
|
|
hwnd,
|
|
GWLP_WNDPROC,
|
|
ptr);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
replacedSheetWndProc = reinterpret_cast<WNDPROC>(ptr);
|
|
|
|
hr = Win::SetWindowLongPtr(
|
|
hwnd,
|
|
GWLP_WNDPROC,
|
|
reinterpret_cast<LONG_PTR>(ReplacementWndProc));
|
|
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ExitCode
|
|
RunWizard()
|
|
{
|
|
LOG_FUNCTION(RunWizard);
|
|
|
|
|
|
ExitCode exitCode = EXIT_CODE_SUCCESSFUL;
|
|
|
|
UINT startPage = GetStartPage();
|
|
|
|
State::GetInstance().SetStartPage(startPage);
|
|
|
|
// Create the wizard and add all the pages
|
|
|
|
Wizard wiz(
|
|
IDS_WIZARD_TITLE,
|
|
IDB_BANNER16,
|
|
IDB_BANNER256,
|
|
IDB_WATERMARK16,
|
|
IDB_WATERMARK256);
|
|
|
|
// NOTE: Do not change the order of the following
|
|
// page additions. They are important for being able
|
|
// to start the wizard at one of these pages directly.
|
|
// The order of these pages cooresponds directly to
|
|
// the order of the StartPages enum above
|
|
|
|
wiz.AddPage(new WelcomePage()); // CYS_WELCOME_PAGE
|
|
wiz.AddPage(new BeforeBeginPage()); // CYS_BEFORE_BEGIN_PAGE
|
|
wiz.AddPage(new ExpressRebootPage()); // CYS_EXPRESS_REBOOT_PAGE
|
|
wiz.AddPage(new FinishPage()); // CYS_FINISH_PAGE
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
wiz.AddPage(new DecisionPage());
|
|
wiz.AddPage(new CustomServerPage());
|
|
wiz.AddPage(new ADDomainPage());
|
|
wiz.AddPage(new NetbiosDomainPage());
|
|
wiz.AddPage(new DNSForwarderPage());
|
|
wiz.AddPage(new ExpressDNSPage());
|
|
wiz.AddPage(new ExpressDHCPPage());
|
|
wiz.AddPage(new PrintServerPage());
|
|
wiz.AddPage(new FileServerPage());
|
|
wiz.AddPage(new IndexingPage());
|
|
wiz.AddPage(new MilestonePage());
|
|
wiz.AddPage(new UninstallMilestonePage());
|
|
wiz.AddPage(new InstallationProgressPage());
|
|
wiz.AddPage(new UninstallProgressPage());
|
|
wiz.AddPage(new WebApplicationPage());
|
|
wiz.AddPage(new POP3Page());
|
|
|
|
// Run the wizard
|
|
switch (wiz.ModalExecute(
|
|
0,
|
|
startPage,
|
|
SheetCallbackProc))
|
|
{
|
|
case -1:
|
|
{
|
|
/* popup.Error(
|
|
Win::GetDesktopWindow(),
|
|
E_FAIL,
|
|
IDS_PROP_SHEET_FAILED);
|
|
|
|
*/
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
case ID_PSREBOOTSYSTEM:
|
|
{
|
|
// we can infer that if we are supposed to reboot, then the
|
|
// operation was successful.
|
|
|
|
exitCode = EXIT_CODE_SUCCESSFUL;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
// do nothing.
|
|
break;
|
|
}
|
|
}
|
|
|
|
return exitCode;
|
|
}
|
|
|
|
ExitCode
|
|
Start()
|
|
{
|
|
LOG_FUNCTION(Start);
|
|
|
|
ExitCode exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
do
|
|
{
|
|
// Put any checks that should stop the wizard from running here...
|
|
|
|
|
|
// User must be an Administrator
|
|
|
|
bool isAdmin = ::IsCurrentUserAdministrator();
|
|
if (!isAdmin)
|
|
{
|
|
LOG(L"Current user is not an Administrator");
|
|
|
|
// Since the user is not an administrator
|
|
// close the mutex so that a non-admin can't
|
|
// leave this message box up and prevent
|
|
// an administrator from running CYS
|
|
|
|
Win::CloseHandle(cysRunningMutex);
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_NOT_ADMIN,
|
|
MB_OK);
|
|
|
|
// State::GetInstance().SetRerunWizard(false);
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
// The Sys OC Manager cannot be running
|
|
|
|
if (State::GetInstance().IsWindowsSetupRunning())
|
|
{
|
|
LOG(L"Windows setup is running");
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_WINDOWS_SETUP_RUNNING_DURING_CYS_STARTUP,
|
|
MB_OK);
|
|
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
// Machine cannot be in the middle of a DC upgrade
|
|
|
|
if (State::GetInstance().IsUpgradeState())
|
|
{
|
|
LOG(L"Machine needs to complete DC upgrade");
|
|
|
|
String commandline = Win::GetCommandLine();
|
|
|
|
// If we were launched from explorer then
|
|
// don't show the message, just exit silently
|
|
|
|
if (commandline.find(EXPLORER_SWITCH) == String::npos)
|
|
{
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_DC_UPGRADE_NOT_COMPLETE,
|
|
MB_OK);
|
|
}
|
|
|
|
// State::GetInstance().SetRerunWizard(false);
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
// Machine cannot have DCPROMO running or a reboot pending
|
|
|
|
if (State::GetInstance().IsDCPromoRunning())
|
|
{
|
|
LOG(L"DCPROMO is running");
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_DCPROMO_RUNNING,
|
|
MB_OK);
|
|
|
|
// State::GetInstance().SetRerunWizard(false);
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
else if (State::GetInstance().IsDCPromoPendingReboot())
|
|
{
|
|
LOG(L"DCPROMO was run, pending reboot");
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_DCPROMO_PENDING_REBOOT,
|
|
MB_OK);
|
|
|
|
// State::GetInstance().SetRerunWizard(false);
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
DWORD productSKU = State::GetInstance().RetrieveProductSKU();
|
|
if (CYS_UNSUPPORTED_SKU == productSKU)
|
|
{
|
|
LOG(L"Cannot run CYS on any SKU but servers");
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_SERVER_ONLY,
|
|
MB_OK);
|
|
|
|
// State::GetInstance().SetRerunWizard(false);
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
// The machine cannot be a member of a cluster
|
|
|
|
if (IsClusterServer())
|
|
{
|
|
LOG(L"Machine is a member of a cluster");
|
|
|
|
Win::CloseHandle(cysRunningMutex);
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_CLUSTER,
|
|
MB_OK);
|
|
|
|
exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
|
|
// We can run the wizard. Yea!!!
|
|
|
|
exitCode = RunWizard();
|
|
}
|
|
while (0);
|
|
|
|
LOG(String::format(L"exitCode = %1!d!", static_cast<int>(exitCode)));
|
|
|
|
return exitCode;
|
|
}
|
|
|
|
int WINAPI
|
|
WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE /* hPrevInstance */ ,
|
|
PSTR /* lpszCmdLine */ ,
|
|
int /* nCmdShow */)
|
|
{
|
|
hResourceModuleHandle = hInstance;
|
|
|
|
ExitCode exitCode = EXIT_CODE_UNSUCCESSFUL;
|
|
|
|
String mutexName = L"Global\\";
|
|
mutexName += RUNTIME_NAME;
|
|
|
|
HRESULT hr = Win::CreateMutex(0, true, mutexName, cysRunningMutex);
|
|
if (hr == Win32ToHresult(ERROR_ALREADY_EXISTS))
|
|
{
|
|
// First close the handle so that the owner can reacquire if they
|
|
// restart
|
|
|
|
Win::CloseHandle(cysRunningMutex);
|
|
|
|
// Now show the error message
|
|
|
|
popup.MessageBox(
|
|
Win::GetDesktopWindow(),
|
|
IDS_ALREADY_RUNNING,
|
|
MB_OK);
|
|
}
|
|
else
|
|
{
|
|
|
|
do
|
|
{
|
|
hr = ::CoInitialize(0);
|
|
if (FAILED(hr))
|
|
{
|
|
ASSERT(SUCCEEDED(hr));
|
|
break;
|
|
}
|
|
|
|
// Initialize the common controls so that we can use
|
|
// animation in the NetDetectProgressDialog
|
|
|
|
INITCOMMONCONTROLSEX commonControlsEx;
|
|
commonControlsEx.dwSize = sizeof(commonControlsEx);
|
|
commonControlsEx.dwICC = ICC_ANIMATE_CLASS;
|
|
|
|
BOOL init = ::InitCommonControlsEx(&commonControlsEx);
|
|
ASSERT(init);
|
|
|
|
// For now there is no more rerunning CYS
|
|
// do
|
|
// {
|
|
exitCode = Start();
|
|
|
|
// } while(State::GetInstance().RerunWizard());
|
|
|
|
InstallationUnitProvider::Destroy();
|
|
State::Destroy();
|
|
|
|
CoUninitialize();
|
|
} while(false);
|
|
}
|
|
|
|
if (brush)
|
|
{
|
|
// delete the background brush
|
|
|
|
(void)Win::DeleteObject(brush);
|
|
}
|
|
|
|
return static_cast<int>(exitCode);
|
|
}
|