|
|
#include "pch.h"
#pragma hdrstop
#include <ndisguid.h>
#include "afilexp.h"
#include "edc.h"
#include "lm.h"
#include "nceh.h"
#include "ncerror.h"
#include "ncmisc.h"
#include "ncnetcfg.h"
#include "ncreg.h"
#include "ncsvc.h"
#include "ncsetup.h"
#include "ncatlui.h"
#include "netcfgn.h"
#include "netsetup.h"
#include "nslog.h"
#include "nsres.h"
#include "resource.h"
#include "upgrade.h"
#include "windns.h"
#include "winstall.h"
#include <hnetcfg.h>
extern const WCHAR c_szInfId_MS_Server[]; extern const WCHAR c_szInfId_MS_NwSapAgent[]; extern const WCHAR c_szInfId_MS_DHCPServer[]; extern const WCHAR c_szInfId_MS_NWClient[]; extern const WCHAR c_szAfSectionNetworking[]; // L"Networking";
extern const WCHAR c_szAfBuildNumber[]; // L"BuildNumber";
extern const WCHAR c_szSvcWorkstation[]; // L"LanmanWorkstation";
extern const WCHAR c_szInfId_MS_NetBIOS[]; extern const WCHAR c_szInfId_MS_MSClient[]; // L"ms_msclient";
const WCHAR PSZ_SPOOLER[] = L"Spooler"; const WCHAR c_szSamEventName[] = L"\\SAM_SERVICE_STARTED"; const WCHAR c_szLsaEventName[] = L"\\INSTALLATION_SECURITY_HOLD"; const WCHAR c_szActiveComputerNameKey[] = L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"; const WCHAR c_szComputerNameKey[] = L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName"; const WCHAR c_szComputerNameValue[] = L"ComputerName"; const WCHAR c_szOCMKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\SubComponents"; const WCHAR c_szDHCPServer[] = L"dhcpserver"; const WCHAR c_szSapAgent[] = L"nwsapagent";
// Unattended Mode related strings
//
const WCHAR c_szUnattendSection[] = L"Unattended"; const WCHAR c_szUnattendMode[] = L"UnattendMode"; const WCHAR c_szUMDefaultHide[] = L"DefaultHide"; const WCHAR c_szUMGuiAttended[] = L"GuiAttended"; const WCHAR c_szUMProvideDefault[] = L"ProvideDefault"; const WCHAR c_szUMReadOnly[] = L"ReadOnly"; const WCHAR c_szUMFullUnattended[] = L"FullUnattended";
// Sysprep registry strings
const WCHAR c_szSystemSetupKey[] = L"SYSTEM\\Setup"; const WCHAR c_szMiniSetupInProgress[] = L"MiniSetupInProgress";
const DWORD c_cmsWaitForINetCfgWrite = 120000; const UINT PWM_PROCEED = WM_USER+1202; const UINT PWM_EXIT = WM_USER+1203; const UINT c_uiUpgradeRefreshID = 7719; const UINT c_uiUpgradeRefreshRate = 5000; // Refresh rate in milliseconds
EXTERN_C DWORD InstallUpgradeWorkThrd(InitThreadParam* pitp);
// Setup Wizard Global - Only used during setup.
extern CWizard * g_pSetupWizard; WNDPROC OldProgressProc;
BOOL NewProgessProc( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) { switch (msg) { case PBM_DELTAPOS: case PBM_SETRANGE: case PBM_SETRANGE32: case PBM_STEPIT: case PBM_SETPOS: case PBM_SETSTEP: // Forward to the billboard progress.
g_pSetupWizard->PSetupData()->BillboardProgressCallback(msg, wParam, lParam); break; } // Always call the progress on the wizard page.
return (BOOL)CallWindowProc(OldProgressProc,hdlg,msg,wParam,lParam); }
//
// Function: SignalLsa
//
// Purpose: During initial setup, the winlogon creates a special event
// (unsignalled) before it starts up Lsa. During initialization
// lsa waits on this event. After Gui setup is done with setting
// the AccountDomain sid it can signal the event. Lsa will then
// continue initialization.
//
// Parameters: none
//
// Returns: nothing
//
BOOL SignalLsa(VOID) { TraceFileFunc(ttidGuiModeSetup);
UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Attributes; NTSTATUS Status; HANDLE Event; BOOL b;
//
// If the following event exists, it is an indication that
// LSA is blocked at installation time and that we need to
// signal this event.
//
// Unfortunately we have to use the NT APIs to do this, because
// all events created/accessed via the Win32 APIs will be in the
// BaseNamedObjects directory, and LSA doesn't know to look there.
//
RtlInitUnicodeString(&UnicodeString,c_szLsaEventName); InitializeObjectAttributes(&Attributes,&UnicodeString,0,0,NULL);
Status = NtOpenEvent(&Event,EVENT_MODIFY_STATE,&Attributes); if(NT_SUCCESS(Status)) { Status = NtSetEvent(Event,NULL); if(NT_SUCCESS(Status)) { b = TRUE; } else { b = FALSE; } CloseHandle(Event); } else { b = FALSE; }
return(b); }
//
// Function: CreateSamEvent
//
// Purpose: Create an event that SAM will use to tell us when it's finished
// initializing.
//
// Parameters: phSamEvent [OUT] - Handle to the event object created
//
// Returns: BOOL, TRUE on success
//
BOOL CreateSamEvent(HANDLE * phSamEvent) { TraceFileFunc(ttidGuiModeSetup);
UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Attributes; NTSTATUS Status;
//
// Unfortunately we have to use the NT APIs to do this, because
// all events created/accessed via the Win32 APIs will be in the
// BaseNamedObjects directory, and SAM doesn't know to look there.
//
RtlInitUnicodeString(&UnicodeString,c_szSamEventName); InitializeObjectAttributes(&Attributes,&UnicodeString,0,0,NULL);
Status = NtCreateEvent(phSamEvent,SYNCHRONIZE,&Attributes,NotificationEvent,FALSE); if(!NT_SUCCESS(Status)) { *phSamEvent = NULL; }
return(NT_SUCCESS(Status)); }
//
// Function: WaitForSam
//
// Purpose: Wait for SAM to finish initializing. We can tell when it's done
// because an event we created earlier (see CreateSamEvent()) will
// become signalled.
//
// Parameters: hSamEvent - HANDLE to wait for
//
// Returns: BOOL, TRUE on success
//
BOOL WaitForSam(HANDLE hSamEvent) { DWORD d; BOOL b = false;
if (hSamEvent) { b = TRUE; d = WaitForSingleObject(hSamEvent,INFINITE); if(d != WAIT_OBJECT_0) { b = FALSE; TraceError("WaitForSam",E_UNEXPECTED); } } return(b); }
//
// Function: SyncSAM
//
// Purpose: Sychronize the SAM database and Lsa
//
// Parameters: pWizard [IN] - Ptr to a Wizard Instance
//
// Returns: nothing
//
VOID SyncSAM(CWizard *pWizard) { TraceFileFunc(ttidGuiModeSetup);
HANDLE hSamEvent = NULL;
Assert(!IsPostInstall(pWizard)); TraceTag(ttidWizard,"Beginning SAM/Lsa Sync");
// Sync the SAM DB
CreateSamEvent(&hSamEvent); SignalLsa(); if (hSamEvent) { WaitForSam(hSamEvent); CloseHandle(hSamEvent); }
TraceTag(ttidWizard,"Completed SAM/Lsa Sync"); }
//
// Function: IsComputerNameChanged
//
// Purpose: To determine if the active and intended computer names are the same
//
// Parameters: None.
//
// Returns: TRUE if the active and intended computer names are different.
//
BOOL IsComputerNameChanged (VOID) { TraceFileFunc(ttidGuiModeSetup);
HRESULT hr; HKEY hkeyActive; HKEY hkeyIntended; BOOL fNameChanged; tstring strActive; tstring strIntended;
fNameChanged = FALSE;
// open the keys we need
hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveComputerNameKey, KEY_READ, &hkeyActive ); if (SUCCEEDED(hr)) {
hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szComputerNameKey, KEY_READ, &hkeyIntended ); if ( SUCCEEDED(hr) ) { hr = HrRegQueryString(hkeyIntended, c_szComputerNameValue, &strIntended);
if ( SUCCEEDED(hr) ) { hr = HrRegQueryString(hkeyActive, c_szComputerNameValue, &strActive);
if ( SUCCEEDED(hr) ) { fNameChanged = _wcsicmp( strActive.c_str(), strIntended.c_str() ) != 0; } }
RegCloseKey( hkeyIntended ); }
RegCloseKey( hkeyActive ); }
return fNameChanged; }
//
// Function: HrSetActiveComputerName
//
// Purpose: To make sure the active and intended computer names are the same
//
// Parameters: pszNewName [IN] - the new computer name
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrSetActiveComputerName ( IN PCWSTR pszNewName) { TraceFileFunc(ttidGuiModeSetup);
HRESULT hr; HKEY hkeyActive = NULL; HKEY hkeyIntended = NULL; tstring str;
TraceTag(ttidWizard,"Setting the active computer name");
// open the keys we need
hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveComputerNameKey, KEY_WRITE, &hkeyActive ); if (FAILED(hr)) goto Error;
hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szComputerNameKey, KEY_READ_WRITE, &hkeyIntended ); if (FAILED(hr)) goto Error;
if (pszNewName == NULL) { hr = HrRegQueryString(hkeyIntended, c_szComputerNameValue, &str); pszNewName = str.c_str(); } else { // set the intended computer name
hr = HrRegSetSz(hkeyIntended, c_szComputerNameValue, pszNewName); }
if (FAILED(hr)) goto Error;
// set the active computer name
hr = HrRegSetSz(hkeyActive, c_szComputerNameValue, pszNewName);
Error: // close it all up
RegSafeCloseKey( hkeyActive ); RegSafeCloseKey( hkeyIntended );
TraceHr(ttidWizard, FAL, hr, FALSE, "HrSetActiveComputerName"); return hr; }
//
// Function: HrInitAndGetINetCfg
//
// Purpose: To initialize an INetCfg instance and to do some preliminary
// answerfile work (if an answer file is being used).
//
// Parameters: pWizard [IN] - Ptr to a wizard instance
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrInitAndGetINetCfg(CWizard *pWizard) { TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
Assert(NULL != pWizard);
if (SUCCEEDED(hr)) { PWSTR pszClientDesc = NULL; INetCfg* pNetCfg = NULL; BOOL fInitCom = !pWizard->FCoUninit();
hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg, TRUE, c_cmsWaitForINetCfgWrite, SzLoadIds(IDS_WIZARD_CAPTION), &pszClientDesc); if (SUCCEEDED(hr)) { // Retain our success in initializing COM only if we asked to
// initialize COM in the first place.
if (!pWizard->FCoUninit()) { pWizard->SetCoUninit(fInitCom); } pWizard->SetNetCfg(pNetCfg);
CoTaskMemFree(pszClientDesc); } }
TraceHr(ttidWizard, FAL, hr, FALSE, "HrInitAndGetINetCfg"); return hr; }
//
// Function: OnUpgradeUpdateProgress
//
// Purpose: Update the progress control during setup
//
// Parameters: Standard timer callback parameters
//
// Returns: nothing
//
VOID OnUpgradeUpdateProgress(HWND hwndDlg) { TraceFileFunc(ttidGuiModeSetup);
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
LPARAM lParam = pWizard->GetPageData(IDD_Upgrade); Assert(lParam); UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
if(pData) { // Get current position
//
HWND hwndProgress = GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS); Assert(hwndProgress); UINT nCurPos = (UINT)SendMessage(hwndProgress, PBM_GETPOS, 0, 0);
// If the current position is less then the cap, advance
//
if (nCurPos < pData->nCurrentCap) { SendMessage(hwndProgress, PBM_SETPOS, ++nCurPos, 0); } } }
//
// Function: UpgradeSetProgressCap
//
// Purpose: Update the current cap for the progress control
//
// Parameters: hwndDlg - Handle to the current dialog
// pWizard - Ptr to the wizard data
// nNewCap - The new maximum progress cap
//
// Returns: nothing
//
VOID OnUpgradeUpdateProgressCap ( HWND hwndDlg, CWizard* pWizard, UINT nNewCap) { TraceFileFunc(ttidGuiModeSetup);
LPARAM lParam = pWizard->GetPageData(IDD_Upgrade); Assert(lParam);
UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
if(pData) { // Since we're increasing the progress cap, we need to advance the
// progress indicator to the old cap.
//
SendMessage(GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS), PBM_SETPOS, pData->nCurrentCap, 0);
// Retain the new cap
//
pData->nCurrentCap = nNewCap; } }
//
// Function:
//
// Purpose:
//
// Parameters:
//
// Returns:
//
VOID ReadAnswerFileSetupOptions(CWizard * pWizard) { TraceFileFunc(ttidGuiModeSetup);
if (IsUnattended(pWizard)) { // Get the unattended flags
//
CSetupInfFile csif;
Assert(pWizard->PSetupData()); Assert(pWizard->PSetupData()->UnattendFile);
// Open the answser file
//
if (SUCCEEDED(csif.HrOpen(pWizard->PSetupData()->UnattendFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL))) { tstring str;
// Confirm no one has over written the default
//
Assert(UM_DEFAULTHIDE == pWizard->GetUnattendedMode());
// Locate the UnattendMode string, if it exists
//
if (SUCCEEDED(csif.HrGetString(c_szUnattendSection, c_szUnattendMode, &str))) { struct { PCWSTR pszMode; UM_MODE UMMode; } UMModeMap[] = {{c_szUMDefaultHide,UM_DEFAULTHIDE}, {c_szUMGuiAttended,UM_GUIATTENDED}, {c_szUMProvideDefault,UM_PROVIDEDEFAULT}, {c_szUMReadOnly,UM_READONLY}, {c_szUMFullUnattended,UM_FULLUNATTENDED}};
// Search the map for the unattended flag, note that if
// we don't find it the default is UM_DEFAULTHIDE
//
for (UINT nIdx = 0; nIdx < celems(UMModeMap); nIdx++) { if (0 == _wcsicmp(str.c_str(),UMModeMap[nIdx].pszMode)) { pWizard->SetUnattendedMode(UMModeMap[nIdx].UMMode); break; } } } } } }
//
// Function: StartSpooler
//
// Purpose: Start the spooler process before the components are applied
// as some of the components want to install print monitors, and
// the spooler needs to be running for this to succeed.
//
// Parameters: none
//
// Returns: nothing
//
VOID StartSpooler() { TraceFileFunc(ttidGuiModeSetup);
CServiceManager csm; TraceTag(ttidWizard, "Attempting to start spooler");
HRESULT hr = csm.HrStartServiceNoWait(PSZ_SPOOLER);
TraceHr(ttidWizard, FAL, hr, FALSE, "*** StartSpooler - The spooler failed to start, you probably " "won't have networking ***"); }
//
// Function: HrCommitINetCfgChanges
//
// Purpose: Validate and Commit changes to the INetCfg object
//
// Parameters: hwnd [IN] - Handle of the current window
// pWizard [IN] - Ptr to a wizard instance
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrCommitINetCfgChanges(HWND hwnd, CWizard * pWizard) { TraceFileFunc(ttidGuiModeSetup);
INetCfg * pNetCfg = pWizard->PNetCfg(); Assert(NULL != pNetCfg);
// Commit the changes
TraceTag(ttidWizard,"HrCommitINetCfgChanges - Applying changes");
HRESULT hr = pNetCfg->Apply();
if (S_FALSE == hr) { hr = S_OK; }
TraceHr(ttidWizard, FAL, hr, FALSE, "HrCommitINetCfgChanges"); return hr; }
//
// Function: IsSBS
//
// Purpose: Determine if it is SBS version.
//
// Parameters: None
//
// Returns: BOOL, TRUE if it is Microsoft Small Business Server
//
BOOL IsSBS (VOID) { TraceFileFunc(ttidGuiModeSetup);
OSVERSIONINFOEX ose; BOOL bVersionRet;
ZeroMemory(&ose, sizeof(ose)); ose.dwOSVersionInfoSize = sizeof(ose); bVersionRet = GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&ose));
return (bVersionRet && (ose.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)); } //
// Function: IsMSClientInstalled
//
// Purpose: Determine if MSClient is installed.
//
// Parameters: hwnd [IN] - Handle of the current window
// pWizard [IN] - Ptr to a wizard instance
//
// Returns: BOOL, TRUE if MS Client is installed, otherwise
//
BOOL IsMSClientInstalled(HWND hwnd, CWizard * pWizard) { INetCfg *pNetCfg; INetCfgComponent *pncc; HRESULT hr;
TraceFileFunc(ttidGuiModeSetup);
Assert(NULL != pWizard);
if ( !pWizard ) { return FALSE; }
pNetCfg = pWizard->PNetCfg(); Assert(NULL != pNetCfg);
if ( !pNetCfg ) { return FALSE; }
hr = pNetCfg->FindComponent(c_szInfId_MS_MSClient, &pncc); if ( hr == S_OK ) { ReleaseObj(pncc); }
TraceHr(ttidWizard, FAL, hr, FALSE, "IsMSClientInstalled"); return hr == S_OK; }
//
// Function:
//
// Purpose:
//
// Parameters:
//
// Returns:
//
BOOL OnProcessPrevAdapterPagePrev(HWND hwndDlg, UINT idd) { TraceFileFunc(ttidGuiModeSetup);
BOOL fRet = FALSE; CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard); HPROPSHEETPAGE hPage;
GUID * pguidAdapter = pWizard->PAdapterQueue()->PrevAdapter(); if (NULL != pguidAdapter) { pWizard->SetCurrentProvider(0); CWizProvider * pWizProvider = pWizard->GetCurrentProvider(); Assert(NULL != pWizProvider); Assert(pWizProvider->ULPageCount());
// Reset the providers guard page to point forward
LPARAM ulId = reinterpret_cast<LPARAM>(pWizProvider); pWizard->SetPageDirection(ulId, NWPD_FORWARD);
// Push the adapter guid onto the provider
HRESULT hr = pWizProvider->HrSpecifyAdapterGuid(pguidAdapter); if (SUCCEEDED(hr)) { // Get the last page from the provider
TraceTag(ttidWizard, "Jumping to LAN provider last page..."); hPage = (pWizProvider->PHPropPages())[pWizProvider->ULPageCount() - 1]; Assert(hPage);
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)(HPROPSHEETPAGE)hPage); fRet = TRUE; // We jumped to a provider page
} } else { if (idd) { hPage = pWizard->GetPageHandle(idd); Assert(hPage); ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1); PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)(HPROPSHEETPAGE)hPage); } }
return fRet; }
//
// Function: OBOUserAddRefSpecialCase
//
// Purpose: Handle a special case where when upgrading from NT351 or NT 4
// with MS's "File and Print" and GSNW. In this case we need to
// AddRef OBOUser F&P, so removal of GSNW does not remove F&P.
//
// Parameters: pWizard [IN] - Context information
//
// Returns: Nothing. (this is basically a do it if we can special case.)
//
VOID OBOUserAddRefSpecialCase(CWizard * pWizard) { TraceFileFunc(ttidGuiModeSetup);
CSetupInfFile csif; HRESULT hr = S_OK;
Assert(pWizard->PNetCfg()); Assert(IsUnattended(pWizard)); TraceTag(ttidWizard, "OBOUserAddRefSpecialCase - Start");
// if we're upgrading from NT 3.51 or NT 4
//
if (pWizard->PSetupData()->UnattendFile) { /* DWORD dwBuild = 0;
hr = csif.HrOpen(pWizard->PSetupData()->UnattendFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (SUCCEEDED(hr)) { hr = csif.HrGetDword(c_szAfSectionNetworking, c_szAfBuildNumber, &dwBuild); }
if (SUCCEEDED(hr) && (dwBuild <= wWinNT4BuildNumber)) {*/ PRODUCT_FLAVOR pf;
// If this is an NT server (GSNW is server only)
//
GetProductFlavor(NULL, &pf); if (PF_WORKSTATION != pf) { const GUID * rgguidClass[2] = {&GUID_DEVCLASS_NETSERVICE, &GUID_DEVCLASS_NETCLIENT}; const PCWSTR rgpszComponentId[2] = {c_szInfId_MS_Server, c_szInfId_MS_NWClient}; INetCfgComponent* rgpncc[2] = {NULL, NULL};
hr = HrFindComponents (pWizard->PNetCfg(), 2, rgguidClass, rgpszComponentId, rgpncc); if (SUCCEEDED(hr)) { // Are both "GSNW" and "File and Print" installed?
//
if (rgpncc[0] && rgpncc[1]) { NETWORK_INSTALL_PARAMS nip = {0};
nip.dwSetupFlags = NSF_PRIMARYINSTALL;
// re-install OBOUser "File and Print"
//
TraceTag(ttidWizard, " OBOUser Install of File and Print Services"); TraceTag(ttidWizard, " On upgrade from NT 3.51 or NT 4"); (void)HrInstallComponentsOboUser(pWizard->PNetCfg(), &nip, 1, &rgguidClass[0], &rgpszComponentId[0]); }
ReleaseObj(rgpncc[0]); ReleaseObj(rgpncc[1]); } } /// }
}
TraceTag(ttidWizard, "OBOUserAddRefSpecialCase - End"); TraceError("OBOUserAddRefSpecialCase",hr); }
//
// Function:
//
// Purpose:
//
// Parameters:
//
// Returns:
//
BOOL OnProcessNextAdapterPageNext(HWND hwndDlg, BOOL FOnActivate) { TraceFileFunc(ttidGuiModeSetup);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard); HRESULT hr = S_OK; BOOL fRet = FALSE; HPROPSHEETPAGE hPage; GUID * pguidAdapter;
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
// Refresh the contents of the adapter queue.
// ATM adapters may have been added or removed
if (pWizard->FProcessLanPages()) { // Commit changes and look for any new adapters
(VOID)HrCommitINetCfgChanges(GetParent(hwndDlg), pWizard); (VOID)pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pWizard); }
// If there are adapters left to process prime the pump
pguidAdapter = pWizard->PAdapterQueue()->NextAdapter(); if (NULL != pguidAdapter) { pWizard->SetCurrentProvider(0); CWizProvider * pWizProvider = pWizard->GetCurrentProvider(); Assert(NULL != pWizProvider); Assert(pWizProvider->ULPageCount());
// Push the adapter guid onto the provider
hr = pWizProvider->HrSpecifyAdapterGuid(pguidAdapter); if (SUCCEEDED(hr)) { #if DBG
WCHAR szGuid[c_cchGuidWithTerm]; Assert(pguidAdapter); if (SUCCEEDED(StringFromGUID2(*pguidAdapter, szGuid, c_cchGuidWithTerm))) { TraceTag(ttidWizard, " Calling LAN pages for Adapter Guid: %S", szGuid); } #endif
// Reset the providers guard page to point forward
LPARAM ulId = reinterpret_cast<LPARAM>(pWizProvider); pWizard->SetPageDirection(ulId, NWPD_FORWARD);
// Get the first page from the provider
hPage = (pWizProvider->PHPropPages())[0]; Assert(hPage); PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)(HPROPSHEETPAGE)hPage);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
TraceTag(ttidWizard, "Jumping to LAN provider first page..."); fRet = TRUE; // We processed it
} }
// If there are no adapters left to process, or an error occurred
if ((NULL == pguidAdapter) || FAILED(hr)) { UINT idd = IDD_Exit;
// Commit any changes to INetCfg.
if (SUCCEEDED(hr) && pWizard->FProcessLanPages()) { // Commit changes
(VOID)HrCommitINetCfgChanges(GetParent(hwndDlg), pWizard); }
if (!IsPostInstall(pWizard) && IsMSClientInstalled(GetParent(hwndDlg), pWizard)) { idd = IDD_Join; TraceTag(ttidWizard, "Jumping to Join page...");
} else { TraceTag(ttidWizard, "Jumping to Exit page..."); }
if (FOnActivate) { ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, idd); } else { // else goto the appropriate page
hPage = pWizard->GetPageHandle(idd); Assert(hPage); PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)hPage); } fRet = TRUE; // We processed it
}
Assert(TRUE == fRet); return fRet; }
//
// Function: FixupOldOcComponents
//
// Purpose: Convert SAP and DHCP optional components (if present) into
// regular networking components.
//
// Parameters: pWizard
//
// Returns: nothing
//
void FixupOldOcComponents(CWizard * pWizard) { TraceFileFunc(ttidGuiModeSetup);
HRESULT hr;
static const GUID* c_apguidInstalledComponentClasses [] = { &GUID_DEVCLASS_NETSERVICE, // DHCP
&GUID_DEVCLASS_NETSERVICE, // SAP Agent
};
static const PCWSTR c_apszInstalledComponentIds [] = { c_szInfId_MS_DHCPServer, c_szInfId_MS_NwSapAgent, };
static const PCWSTR c_apszOcNames[] = { c_szDHCPServer, c_szSapAgent, };
// If component was installed as an optional component
//
HKEY hkey; hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szOCMKey, KEY_READ_WRITE, &hkey); if (SUCCEEDED(hr)) { DWORD dw;
for (UINT idx=0; idx<celems(c_apszOcNames); idx++) { // Remove the OC Manager reference
//
hr = HrRegQueryDword (hkey, c_apszOcNames[idx], &dw); if (SUCCEEDED(hr)) { if (dw) { // Install OBO user the component
//
NETWORK_INSTALL_PARAMS nip = {0};
// Note: Claiming it's a server upgrade is a bit bogus,
// but is needed so dhcpsobj.cpp doesn't display
// UI.
//
nip.dwSetupFlags |= NSF_WINNT_SVR_UPGRADE; nip.dwSetupFlags |= NSF_PRIMARYINSTALL;
(void)HrInstallComponentsOboUser(pWizard->PNetCfg(), &nip, 1, &c_apguidInstalledComponentClasses[idx], &c_apszInstalledComponentIds[idx]); }
// Delete the value
//
(VOID)HrRegDeleteValue(hkey, c_apszOcNames[idx]); } }
RegCloseKey(hkey); } }
struct NAME_DATA { PCWSTR pszComputerName; };
//+---------------------------------------------------------------------------
//
// Function: DuplicateNameProc
//
// Purpose: Dialog procedure for the duplicate name dialog
//
// Arguments:
// hwndDlg []
// uMsg [] See MSDN
// wParam []
// lParam []
//
// Returns:
//
// Author: danielwe 16 Feb 1999
//
// Notes:
//
INT_PTR CALLBACK DuplicateNameProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { TraceFileFunc(ttidGuiModeSetup);
BOOL frt = FALSE; WCHAR szBuf[1024]; WCHAR szText[1024]; NAME_DATA * pData;
switch (uMsg) { case WM_INITDIALOG: SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam); pData = (NAME_DATA *)lParam;
Assert(pData->pszComputerName);
GetDlgItemText(hwndDlg, TXT_Caption, szText, celems(szText));
// add computer name to title
wsprintfW(szBuf, szText, pData->pszComputerName); SetDlgItemText(hwndDlg, TXT_Caption, szBuf);
// limit text in edit control
SendDlgItemMessage(hwndDlg, EDT_New_Name, EM_LIMITTEXT, (WPARAM)MAX_COMPUTERNAME_LENGTH, 0); return TRUE;
case WM_COMMAND: switch (HIWORD(wParam)) { case BN_CLICKED: switch (LOWORD(wParam)) { case IDOK: NET_API_STATUS nas;
GetDlgItemText(hwndDlg, EDT_New_Name, szBuf, celems(szBuf)); nas = NetValidateName(NULL, szBuf, NULL, NULL, NetSetupMachine); if (nas != NO_ERROR) { UINT ids;
if (nas == ERROR_DUP_NAME) { ids = IDS_E_COMPUTER_NAME_DUPE; TraceTag(ttidWizard, "Computer name %S" " is a dupe.", szBuf); } else { ids = IDS_E_COMPUTER_NAME_INVALID; TraceTag(ttidWizard, "Computer name %S" " is invalid.", szBuf); }
MessageBeep(MB_ICONSTOP); MessageBox(hwndDlg, SzLoadIds(ids), SzLoadIds(IDS_SETUP_CAPTION), MB_ICONSTOP | MB_OK); SetFocus(GetDlgItem(hwndDlg, EDT_New_Name)); Edit_SetSel(GetDlgItem(hwndDlg, EDT_New_Name), 0, -1); } else { // 398325/406259 : trying to keep DNS names lowercased
//
LowerCaseComputerName(szBuf);
if (!SetComputerNameEx(ComputerNamePhysicalDnsHostname, szBuf)) { TraceLastWin32Error("SetComputerNameEx"); } else { CServiceManager sm;
(VOID)HrSetActiveComputerName(NULL); TraceTag(ttidWizard, "Setting new computer name " "%S.", szBuf);
TraceTag(ttidWizard, "Restarting workstation service" "..."); (VOID) sm.HrStartServiceAndWait(c_szSvcWorkstation); } EndDialog(hwndDlg, 0); } break; } break; } break;
default: frt = FALSE; break; }
return frt; }
//+---------------------------------------------------------------------------
//
// Function: GenerateComputerNameBasedOnOrganizationName
//
// Purpose: Generate a random computer name based on the register user name
// and organization name
//
// Arguments:
// pszGeneratedStringOut Generated Computer Name - allocated by caller
// dwDesiredStrLenIn Desired length of Computer Name
//
// Returns:
//
// Author: deonb 22 April 2000
//
// Notes:
//
VOID GenerateComputerNameBasedOnOrganizationName( LPWSTR pszGeneratedStringOut, // the generated computer name
DWORD dwDesiredStrLenIn // desired length for the computer name
) { TraceFileFunc(ttidGuiModeSetup);
static DWORD dwSeed = 98725757; static LPCWSTR UsableChars = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static LPCWSTR RegKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion"); static LPCWSTR RegOwner = REGSTR_VAL_REGOWNER; static LPCWSTR RegOrganization = REGSTR_VAL_REGORGANIZATION;
WCHAR pszNameOrgNameIn[MAX_PATH+1]; WCHAR pszNameOrgOrgIn[MAX_PATH+1]; // organization the computer is registered to
pszNameOrgNameIn[0] = pszNameOrgNameIn[MAX_PATH] = NULL; pszNameOrgOrgIn[0] = pszNameOrgOrgIn[MAX_PATH] = NULL;
HKEY hkResult = NULL; HRESULT hr;
hr = HrRegOpenKeyBestAccess(HKEY_LOCAL_MACHINE, RegKey, &hkResult); if (SUCCEEDED(hr)) { tstring pstr; hr = HrRegQueryString(hkResult, RegOwner, &pstr); if (SUCCEEDED(hr)) wcsncpy(pszNameOrgNameIn, pstr.c_str(), MAX_PATH);
hr = HrRegQueryString(hkResult, RegOrganization, &pstr); if (SUCCEEDED(hr)) wcsncpy(pszNameOrgOrgIn, pstr.c_str(), MAX_PATH);
RegCloseKey(hkResult); } //
// How many characters will come from the org/name string.
//
DWORD BaseLength = 8; DWORD i,j; DWORD UsableCount;
if( dwDesiredStrLenIn <= BaseLength ) { BaseLength = dwDesiredStrLenIn - 1; }
if( pszNameOrgOrgIn[0] ) { wcsncpy( pszGeneratedStringOut, pszNameOrgOrgIn, dwDesiredStrLenIn ); } else if( pszNameOrgNameIn[0] ) { wcsncpy( pszGeneratedStringOut, pszNameOrgNameIn, dwDesiredStrLenIn ); } else { wcscpy( pszGeneratedStringOut, L"X" ); for( i = 1; i < BaseLength; i++ ) { wcscat( pszGeneratedStringOut, L"X" ); } }
//
// Get him upper-case for our filter...
//
CharUpper( pszGeneratedStringOut );
//
// Now we want to put a '-' at the end
// of our pszGeneratedStringOut. We'd like it to
// be placed in the BASE_LENGTH character, but
// the string may be shorter than that, or may
// even have a ' ' in it. Figure out where to
// put the '-' now.
//
for( i = 0; i <= BaseLength; i++ ) { //
// Check for a short string.
//
if( ( pszGeneratedStringOut[i] == 0 ) || ( pszGeneratedStringOut[i] == L' ' ) || ( ! wcschr(UsableChars, pszGeneratedStringOut[i] ) ) || ( i == BaseLength ) ) { pszGeneratedStringOut[i] = L'-'; pszGeneratedStringOut[i+1] = 0; break; } }
//
// Special case the scenario where we had no usable
// characters.
//
if( pszGeneratedStringOut[0] == L'-' ) { pszGeneratedStringOut[0] = 0; }
UsableCount = wcslen(UsableChars);
GUID gdRandom; CoCreateGuid(&gdRandom); LPBYTE lpGuid = reinterpret_cast<LPBYTE>(&gdRandom);
j = wcslen( pszGeneratedStringOut );
for( i = j; i < dwDesiredStrLenIn; i++ ) { pszGeneratedStringOut[i] = UsableChars[lpGuid[i % sizeof(GUID)] % UsableCount]; }
pszGeneratedStringOut[i] = 0;
CharUpper(pszGeneratedStringOut);
}
//+---------------------------------------------------------------------------
//
// Function: EnsureUniqueComputerName
//
// Purpose: Ensures that the computer name entered in the first part of
// GUI mode setup (note: this UI is not owned by NetCfg) is
// unique. User is prompted to enter a new name if this is not
// the case.
//
// Arguments:
// hwndDlg [in] Parent window
// bIsUnattended Do not pop up dialog box to ask for computer name
// - rather generate a random unique name.
//
// Returns: Nothing
//
// Author: danielwe 16 Feb 1999
//
// Notes: Workstation service is stopped and restarted when new name is
// entered so the change can take effect and domain join can
// succeed.
//
VOID EnsureUniqueComputerName(HWND hwndDlg, BOOL bIsUnattended) { TraceFileFunc(ttidGuiModeSetup);
NET_API_STATUS nas; WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD cchName = celems(szComputerName); NAME_DATA nd = {0};
if (GetComputerNameEx(ComputerNameNetBIOS, reinterpret_cast<PWSTR>(&szComputerName), &cchName)) { CServiceManager sm; CService service; BOOL fRestart = FALSE; DWORD dwState;
// Open the workstation service and figure out if it is running. If
// so we'll need to stop it and note that we need to restart it when
// we're done verifying the computer name.
//
if (SUCCEEDED(sm.HrOpenService(&service, c_szSvcWorkstation))) { if (SUCCEEDED(service.HrQueryState(&dwState)) && (dwState == SERVICE_RUNNING)) { TraceTag(ttidWizard, "Stopping workstation service..."); (VOID) sm.HrStopServiceAndWait(c_szSvcWorkstation); fRestart = TRUE; } }
// NetValidateName() should work without the workstation service
// being started. In fact, it *has* to work like this because otherwise
// the machine will find itself as a duplicate name.. Not good.
//
DWORD dwNumTries = 10; do { nas = NetValidateName(NULL, szComputerName, NULL, NULL, NetSetupMachine); if (nas == ERROR_DUP_NAME) { INT irt;
TraceTag(ttidWizard, "Displaying UI to change duplicate computer " "name %S.", szComputerName);
nd.pszComputerName = szComputerName; if (!bIsUnattended) { irt = (INT)DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_Duplicate_Name), hwndDlg, DuplicateNameProc, (LPARAM)&nd); } else { WCHAR szOldComputerName[MAX_COMPUTERNAME_LENGTH+1];
// In case the computer name is 15 characters long, wcsncpy won't append
// NULL string. So we put one in the last element.
szOldComputerName[MAX_COMPUTERNAME_LENGTH] = NULL;
wcsncpy(szOldComputerName, szComputerName, MAX_COMPUTERNAME_LENGTH);
ZeroMemory( szComputerName, sizeof(WCHAR) * (MAX_COMPUTERNAME_LENGTH+1) );
GenerateComputerNameBasedOnOrganizationName(szComputerName, MAX_COMPUTERNAME_LENGTH);
NetSetupLogStatusV( LogSevWarning, SzLoadIds (IDS_E_UNATTENDED_COMPUTER_NAME_CHANGED), szOldComputerName, szComputerName );
LowerCaseComputerName(szComputerName);
if (!SetComputerNameEx(ComputerNamePhysicalDnsHostname, szComputerName)) { TraceLastWin32Error("SetComputerNameEx"); } else { (VOID)HrSetActiveComputerName(NULL); TraceTag(ttidWizard, "Setting new computer name %S.", szComputerName); } } } else { TraceTag(ttidWizard, "Name is already unique.");
// Restart the workstation service if necessary.
//
if (fRestart) { TraceTag(ttidWizard, "Restarting Workstation service..."); (VOID) sm.HrStartServiceAndWait(c_szSvcWorkstation); } } } while ( (ERROR_DUP_NAME == nas) && (dwNumTries--) && (bIsUnattended) ); } else { TraceLastWin32Error("EnsureUniqueComputerName - GetComputerNameEx"); } }
//+---------------------------------------------------------------------------
//
// Function: ValidateNetBiosName
//
// Purpose: Ensures that the computer name is a valid DNS name e.g. when
// upgrading from a previous O/S. If not it logs an error to the
// setuperr.log
//
// Arguments: nothing
//
// Returns: S_OK if valid
// S_FALSE if invalid
// E_FAIL if failed
//
// Author: deonb 2 May 2000
//
// Notes:
HRESULT ValidateNetBiosName() { TraceFileFunc(ttidGuiModeSetup);
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD cchName = celems(szComputerName);
if (GetComputerNameEx(ComputerNameNetBIOS, reinterpret_cast<PWSTR>(&szComputerName), &cchName)) { DNS_STATUS dnsStatus = DnsValidateName(szComputerName, DnsNameHostnameLabel); switch (dnsStatus) { case ERROR_SUCCESS: return S_OK;
case ERROR_INVALID_NAME: NetSetupLogStatusV( LogSevWarning, SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME)); return S_FALSE;
case DNS_ERROR_INVALID_NAME_CHAR: NetSetupLogStatusV( LogSevWarning, SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME_CHAR)); return S_FALSE;
case DNS_ERROR_NON_RFC_NAME: NetSetupLogStatusV( LogSevWarning, SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME_NONRFC)); return S_FALSE;
default: TraceError("ValidateComputerName - DnsValidateName", dnsStatus); return E_FAIL; } } else { TraceLastWin32Error("ValidateComputerName - GetComputerNameEx"); return E_FAIL; } }
//
// Function: HrSetupGetSourceInfo
//
// Purpose: Allocates, gets, and returns the required Setup info
//
// Parameters: hinf [IN] - setup hinf handle
// SrcId [IN] - source id obtained from setup
// InfoDesired [IN] - indicates what info is desired
// ppsz [OUT] - ptr to string to be filled and returned
//
// Returns: HRESULT
//
HRESULT HrSetupGetSourceInfo( IN HINF hinf, IN UINT SrcId, IN UINT InfoDesired, OUT PWSTR * ppsz) { TraceFileFunc(ttidGuiModeSetup);
Assert(hinf); Assert(SRCINFO_PATH == InfoDesired || SRCINFO_TAGFILE == InfoDesired || SRCINFO_DESCRIPTION == InfoDesired); Assert(ppsz);
HRESULT hr = S_OK; ULONG cch;
// first get the size of the string required
//
if (SetupGetSourceInfo(hinf, SrcId, InfoDesired, NULL, 0, &cch)) { // now get the required info
//
*ppsz = (PWSTR) MemAlloc(cch * sizeof (WCHAR));
if (*ppsz) { if (!SetupGetSourceInfo(hinf, SrcId, InfoDesired, *ppsz, cch, NULL)) { MemFree(*ppsz); hr = HRESULT_FROM_WIN32(GetLastError()); } } else { hr = E_OUTOFMEMORY; } } else { hr = HRESULT_FROM_WIN32(GetLastError()); }
return hr; }
//
// Function: UpgradeEtcServicesFile
//
// Purpose: Performs upgrade of %windir%\system32\drivers\etc\services file
//
// Parameters: pWizard [IN] - wizard info
//
// Returns: void
//
VOID UpgradeEtcServicesFile(CWizard * pWizard) { TraceFileFunc(ttidGuiModeSetup); // find etc\services file, and get size and other data
// compare size/date etc and decide if we should upgrade it.
HRESULT hr = S_OK; DWORD status; BOOL fShouldUpgradeIt = FALSE; WCHAR szWindowsDir[MAX_PATH+1]; tstring strServices; static const WCHAR c_szServicesFile[] = L"\\system32\\drivers\\etc\\services"; static const WCHAR c_szServicesDirSuffix[] = L"\\system32\\drivers\\etc"; static const DWORD c_dwNT4ServicesFileSize = 6007;
DWORD cNumCharsReturned = GetSystemWindowsDirectory(szWindowsDir, MAX_PATH); if (cNumCharsReturned) { HANDLE hFile;
strServices = szWindowsDir; strServices += c_szServicesFile;
// see if file exists
hFile = CreateFile(strServices.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFile) { // get attributes
DWORD dwSize = GetFileSize(hFile, NULL); if (c_dwNT4ServicesFileSize == dwSize) { fShouldUpgradeIt = TRUE; } CloseHandle(hFile); } else { TraceTag(ttidWizard, "services files doesn't exist"); } } else { hr = HrFromLastWin32Error(); }
static const WCHAR c_szServices[] = L"services";
//
// copy over new services file if required
//
if (S_OK == hr && fShouldUpgradeIt) { // copy the file
//
HSPFILEQ q = NULL; HINF hinf = NULL; UINT SrcId; PWSTR pszTagInfo = NULL; PWSTR pszDescription = NULL; tstring strServicesDir = szWindowsDir; PVOID pCtx = NULL;
q = SetupOpenFileQueue(); if (!q) { TraceTag(ttidWizard, "SetupOpenFileQueue failed"); goto cleanup; }
// we need the location of services._ (the compressed file)
// first open layout.inf
//
hinf = SetupOpenMasterInf(); if (!hinf) { TraceTag(ttidWizard, "Failed to open layout.inf"); goto cleanup; }
// get size of needed buffer
//
if (!SetupGetSourceFileLocation(hinf, NULL, c_szServices, &SrcId, NULL, 0, NULL)) { TraceTag(ttidWizard, "SetupGetSourceFileLocation failed."); goto cleanup; }
// get TagInfo
//
if (S_OK != HrSetupGetSourceInfo(hinf, SrcId, SRCINFO_TAGFILE, &pszTagInfo)) { TraceTag(ttidWizard, "Failed to get TagInfo for services file."); goto cleanup; }
// get Description
//
if (S_OK != HrSetupGetSourceInfo(hinf, SrcId, SRCINFO_DESCRIPTION, &pszDescription)) { TraceTag(ttidWizard, "Failed to get Description for services file."); goto cleanup; }
// now copy the file using this info
//
strServicesDir += c_szServicesDirSuffix; if (!SetupQueueCopy(q, pWizard->PSetupData()->LegacySourcePath, NULL, // don't need this since LegacySourcePath covers it
c_szServices, pszDescription, pszTagInfo, strServicesDir.c_str(), NULL, SP_COPY_REPLACEONLY)) { TraceTag(ttidWizard, "SetupQueueCopy failed"); goto cleanup; }
pCtx = SetupInitDefaultQueueCallbackEx(NULL, static_cast<HWND>(INVALID_HANDLE_VALUE), 0, 0, NULL); if (!pCtx) { TraceTag(ttidWizard, "SetupInitDefaultQueueCallbackEx failed."); goto cleanup; }
if (!SetupCommitFileQueue(NULL, q, &SetupDefaultQueueCallback, pCtx)) { TraceTag(ttidWizard, "SetupCommitFileQueue failed, " "did not copy over new services file"); goto cleanup; }
// success!
TraceTag(ttidWizard, "Copied over new services file");
cleanup: if (pCtx) { SetupTermDefaultQueueCallback(pCtx); } MemFree(pszDescription); MemFree(pszTagInfo); if (hinf) { SetupCloseInfFile(hinf); } if (q) { SetupCloseFileQueue(q); } } }
extern BOOL WINAPI FNetSetupApplySysPrep(); //
// Function: InstallUpgradeWorkThrd
//
// Purpose: Perform an network install or upgrade as appropriate
//
// Parameters: pitp [IN] - Thread data
//
// Returns: DWORD, Zero always
//
EXTERN_C DWORD InstallUpgradeWorkThrd ( InitThreadParam* pitp) { TraceFileFunc(ttidGuiModeSetup);
BOOL fUninitCOM = FALSE; BOOL fLockSCM = FALSE; HRESULT hr = S_OK; UINT uMsg = PWM_EXIT; CServiceManager scm;
TraceTag(ttidWizard, "Entering InstallUpgradeWorkThrd..."); Assert(!IsPostInstall(pitp->pWizard)); Assert(pitp->pWizard->PNetCfg());
#if DBG
if (FIsDebugFlagSet (dfidBreakOnStartOfUpgrade)) { AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag " "\"BreakOnStartOfUpgrade\" has been set. Set your breakpoints now."); } #endif // DBG
OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 10);
// If this is in Mini-Setup mode, we will try to restore adapter specific parameters
// saved for SysPrep operation. This has to be done before the normal Answer-File processing.
// There is nothing we can do with any error here, so any error is ignored.
if ( (pitp->pWizard->PSetupData())->OperationFlags & SETUPOPER_MINISETUP ) { FNetSetupApplySysPrep(); }
TraceTag(ttidWizard, "Waiting on Service Controller"); // Wait until service controller can be locked
//
if (SUCCEEDED(scm.HrOpen())) { while (!fLockSCM) { if (SUCCEEDED(scm.HrLock())) { fLockSCM = TRUE; scm.Unlock(); break; }
Sleep( 500 ); } }
// Initialize COM on this thread
//
hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED); if (FAILED(hr)) { TraceTag(ttidWizard, "Failed to initialize COM upgrade work thread"); goto Done; } else { // Remember to uninitialize COM on thread exit
fUninitCOM = TRUE; }
#if DBG
RtlValidateProcessHeaps (); #endif
if (!IsUpgrade(pitp->pWizard)) { // Make sure the computer name is the same for both intended and active
TraceTag(ttidWizard, "Setting Active Computer Name"); (VOID)HrSetActiveComputerName(NULL); }
// Synchronize the SAM database
//
SyncSAM(pitp->pWizard);
// Retrieve NetDevice info for later use
//
NetDevRetrieveInfo(pitp->pWizard);
// Do answer file processing if it is unattended mode.
//
if (IsUnattended(pitp->pWizard)) { hr = HrInitForUnattendedNetSetup( pitp->pWizard->PNetCfg(), pitp->pWizard->PSetupData()); } else if ( IsUpgrade(pitp->pWizard) ) { // Attended upgrade is really a repair mode.
hr = HrInitForRepair(); }
// Join the default workgroup if necessary
//
if (!IsUpgrade(pitp->pWizard)) { //
// In case it is minisetup of an SBS version and the machine is a DC,
// we don't need to join the default workgroup.
// Bug: 659976
//
if ((pitp->pWizard->OperationFlags() & SETUPOPER_MINISETUP) && IsSBS() && ISDC(ProductType(pitp->pWizard))) { TraceTag(ttidWizard, "Skipping joining Default Workgroup"); } else { // Join the default workgroup only fresh install
TraceTag(ttidWizard, "Joining Default Workgroup"); JoinDefaultWorkgroup(pitp->pWizard, pitp->hwndDlg); } }
// Add unbound LAN adapters to the processing queue. For ATM this will
// have the side effect of creating virtual LAN adapters but not creating
// the connections associated with them
//
Assert(pitp->pWizard->FProcessLanPages()); (VOID)pitp->pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pitp->pWizard);
// Commit the changes caused by processing the unbound adapters
//
(VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
// Now for the ATM case create connections for the virtual LAN adapters
// and commit the changes
//
(VOID)pitp->pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pitp->pWizard); (VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
// Now process any problems in loading netcfg
//
if (NETSETUP_E_ANS_FILE_ERROR == hr) { // $REVIEW - LogError ?
// Disable unattended for networking
//
pitp->pWizard->DisableUnattended(); TraceTag(ttidWizard, "Error In answer file, installing default networking"); goto InstallDefNetworking; } else if (NETSETUP_E_NO_ANSWERFILE == hr) { // $REVIEW(tongl, 4/6/99): Raid #310599, if we are in mini-setup, then
// do attended install if no networking section is specified
HKEY hkeySetup = NULL; HRESULT hrReg = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szSystemSetupKey, KEY_READ, &hkeySetup); if (SUCCEEDED(hrReg)) { DWORD dw; hrReg = HrRegQueryDword(hkeySetup, c_szMiniSetupInProgress, &dw); RegCloseKey(hkeySetup); }
if (SUCCEEDED(hrReg)) { pitp->pWizard->DisableUnattended(); TraceTag(ttidWizard, "Mini-setup with no networking section, do attended install"); goto InstallDefNetworking; } else { // Per Raid 199750 - Install default networking when no
// networking is present.
//
TraceTag(ttidWizard, "No network answer file section, minimal network component setup"); InstallDefaultComponents(pitp->pWizard, EDC_DEFAULT, pitp->hwndDlg); goto SkipNetworkComponentInstall; } } else if (FAILED(hr)) { // $REVIEW - logerror
TraceTag(ttidWizard, "Unexpected Error: 0x%08X",(DWORD)hr); pitp->pWizard->SetExitNoReturn(); goto Done; }
if (!IsUpgrade(pitp->pWizard) && !IsUnattended(pitp->pWizard)) { // Attended install
InstallDefNetworking:
StartSpooler();
if (IsFreshInstall(pitp->pWizard)) { InstallDefaultComponents(pitp->pWizard, EDC_DEFAULT, pitp->hwndDlg); } } else { // Unattended install or upgrade
//
HRESULT hr2; EPageDisplayMode i; BOOL j;
Assert(NULL != pitp->pWizard->PNetCfg());
StartSpooler();
// Upgrade installed components
//
TraceTag(ttidWizard, "Processing installed adapters..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 15); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_NetAdapters, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Processing installed adapters failed.");
TraceTag(ttidWizard, "Upgrading Installed Protocols..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 25); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_NetProtocols, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Protocols failed.");
TraceTag(ttidWizard, "Upgrading Installed Clients..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 40); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_NetClients, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Clients failed.");
TraceTag(ttidWizard, "Upgrading Installed Services..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 55); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_NetServices, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Services failed.");
TraceTag(ttidWizard, "Restoring pre-upgrade bindings..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 70); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_NetBindings, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Restoring pre-upgrade bindings failed.");
TraceTag(ttidWizard, "Removing unsupported components..."); OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 85); hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(), UAW_RemoveNetComponents, &i, &j); TraceHr(ttidWizard, FAL, hr2, FALSE, "Removing unsupported components failed.");
// If we are upgrading and have an answerfile, update lana
// configuration using the information in the file.
// Note: This must be done after all the components have been
// installed (Upgraded), so that all the bindings are present
// when we update hte configuration.
//
if (IsUpgrade (pitp->pWizard) && IsUnattended (pitp->pWizard) && (S_OK == pitp->pWizard->PNetCfg()->FindComponent ( c_szInfId_MS_NetBIOS, NULL))) { PWSTR pszAnswerFile; PWSTR pszAnswerSection; hr = HrGetAnswerFileParametersForComponent (c_szInfId_MS_NetBIOS, &pszAnswerFile, &pszAnswerSection);
if (S_OK == hr) { NC_TRY { UpdateLanaConfigUsingAnswerfile (pszAnswerFile, pszAnswerSection); } NC_CATCH_BAD_ALLOC { TraceTag (ttidWizard, "Possible delayload failure of " "netcfgx dll while trying to update lana " "information."); }
CoTaskMemFree (pszAnswerFile); CoTaskMemFree (pszAnswerSection); }
// We can't let the error stop us.
hr = S_OK; }
// Install networking, if no networking is present. "no networking"
// means no visible LAN-enabled protocol installed.
//
// First try to install default components as opposed to
// mandatory components because TCP/IP is both mandatory
// and default. So, if we install mandatory first then,
// default components will never be installed as TCP/IP is
// a visible LAN-enabled protocol.
// Raid bug 337827
InstallDefaultComponentsIfNeeded(pitp->pWizard);
// Install mandatory components.
InstallDefaultComponents(pitp->pWizard, EDC_MANDATORY, pitp->hwndDlg);
// Special Case. Need an extra OBOUser ref-count for File and Print
// when upgrading from NT3.51 or NT4 and GSNW is installed. This is
// because ref-counting didn't exist pre-NT5
//
OBOUserAddRefSpecialCase(pitp->pWizard);
#if DBG
if (FIsDebugFlagSet (dfidBreakOnEndOfUpgrade)) { AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag " "\"BreakOnEndOfUpgrade\" has been set. Set your breakpoints now."); } #endif // DBG
}
// Convert any components which were OC and are now regular networking components
//
if (IsUpgrade(pitp->pWizard)) { FixupOldOcComponents(pitp->pWizard); }
//
// Upgrade system32\drivers\etc\services file if necessary
//
if (IsUpgrade(pitp->pWizard)) { UpgradeEtcServicesFile(pitp->pWizard); }
SkipNetworkComponentInstall: OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, c_nMaxProgressRange);
// Commit any changes
//
(VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
uMsg = PWM_PROCEED;
Done: // Shutdown the progress timer if it's not already stopped
//
{ LPARAM lParam = pitp->pWizard->GetPageData(IDD_Upgrade); Assert(lParam); UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam); ::KillTimer(pitp->hwndDlg, c_uiUpgradeRefreshID);
// Set the progress indicator to its full position
//
HWND hwndProgress = GetDlgItem(pitp->hwndDlg, IDC_UPGRADE_PROGRESS); SendMessage(hwndProgress, PBM_SETPOS, c_nMaxProgressRange, 0); UpdateWindow(hwndProgress); }
// Uninitialize COM for this thread
//
if (fUninitCOM) { CoUninitialize(); }
EnsureUniqueComputerName(pitp->hwndDlg, IsUnattended(pitp->pWizard)); ValidateNetBiosName();
PostMessage(pitp->hwndDlg, uMsg, (WPARAM)0, (LPARAM)0);
delete pitp;
#if DBG
RtlValidateProcessHeaps (); #endif
TraceTag(ttidWizard, "Leaving InstallUpgradeWorkThrd..."); return 0; }
//
// Function: OnUpgradePageActivate
//
// Purpose: Handle the PSN_SETACTIVE notification by either: Creating a
// thread to process install/upgrade requirements or to just
// deny activation of the page.
//
// Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
//
// Returns: BOOL, TRUE on success
//
BOOL OnUpgradePageActivate( HWND hwndDlg ) { TraceFileFunc(ttidGuiModeSetup);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
// Retrieve the page data stashed within the wizard for this page
LPARAM lParam = pWizard->GetPageData(IDD_Upgrade); Assert(lParam); UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
if(!pData) { return false; }
// Based on the page data decide whether focus is acceptable
if (pData->fProcessed) { // Accept focus
::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0); PAGEDIRECTION PageDir = pWizard->GetPageDirection(IDD_Upgrade); if (NWPD_FORWARD == PageDir) { if ( IsComputerNameChanged() ) { HrSetActiveComputerName (NULL);
EnsureUniqueComputerName(hwndDlg, IsUnattended(pWizard)); }
// Get to this page when the user navigates back and forth
// and we already processed InstallUpgradeWorkThrd
if (g_pSetupWizard != NULL) { g_pSetupWizard->PSetupData()->ShowHideWizardPage(TRUE); } pWizard->SetPageDirection(IDD_Upgrade, NWPD_BACKWARD); PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK); } else { // if there are any adapters previous to the current in the queue
// jump to them before accepting focus here
if (!OnProcessPrevAdapterPagePrev(hwndDlg, 0)) { pWizard->SetPageDirection(IDD_Upgrade, NWPD_FORWARD); PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK); } } } else { HANDLE hthrd; DWORD dwThreadId = 0;
PropSheet_SetWizButtons( GetParent( hwndDlg ), 0);
TraceTag(ttidWizard,"Upgrade/Install Page commencing");
// Install the Asyncmac software-enumerated device.
// Important to do this before the INetCfg lock is obtained, because
// the installation of this device causes or class installer to be
// invoked which needs to get its own lock to process the installation.
//
static const GUID DEVICE_GUID_ASYNCMAC = {0xeeab7790,0xc514,0x11d1,{0xb4,0x2b,0x00,0x80,0x5f,0xc1,0x27,0x0e}};
(VOID) HrInstallSoftwareDeviceOnInterface ( &DEVICE_GUID_ASYNCMAC, &GUID_NDIS_LAN_CLASS, L"asyncmac", TRUE, // force installation since this happens during GUI mode.
L"netrasa.inf", hwndDlg);
// Not processed yet, spin up the thread to do the Install/Upgrade
pData->fProcessed = TRUE; ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0);
InitThreadParam * pitp = new InitThreadParam;
HRESULT hr = S_OK;
if(pitp) { pitp->hwndDlg = hwndDlg; pitp->pWizard = pWizard;
TraceTag(ttidWizard, "Creating INetCfg Instance"); hr = HrInitAndGetINetCfg(pitp->pWizard); } else { hr = E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) { // We are installing and only show progress, hide the page
if (g_pSetupWizard != NULL) { g_pSetupWizard->PSetupData()->ShowHideWizardPage(FALSE); }
// Create the work thread
hthrd = CreateThread( NULL, STACK_SIZE_TINY, (LPTHREAD_START_ROUTINE)InstallUpgradeWorkThrd, (LPVOID)pitp, 0, &dwThreadId ); if (NULL != hthrd) { CloseHandle( hthrd ); } else { hr = HRESULT_FROM_WIN32(GetLastError()); Assert(hr);
// Kill the timer we created since the thread won't be around
// to kill it for us.
//
::KillTimer(hwndDlg, c_uiUpgradeRefreshID); } }
if (FAILED(hr) || (NULL == hthrd)) { // Failed to create the required netsetup thread
delete pitp; AssertSz(0,"Unable to create netsetup thread."); TraceHr(ttidWizard, FAL, hr, FALSE, "OnUpgradePageActivate - Create thread failed"); pWizard->SetExitNoReturn(); PostMessage(hwndDlg, PWM_EXIT, (WPARAM)0, (LPARAM)0); } }
return( TRUE ); }
//
// Function: OnUpgradePageExit
//
// Purpose: Handle the PWN_EXIT notification
//
// Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
//
// Returns: BOOL, TRUE if the action was processed internally
//
BOOL OnUpgradePageExit( HWND hwndDlg ) { TraceFileFunc(ttidGuiModeSetup);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
// goto the exit page
HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_Exit); PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)(HPROPSHEETPAGE)hPage);
return (TRUE); }
//
// Function: OnUpgradePageProceed
//
// Purpose: Handle the PWN_PROCEED notification
//
// Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
//
// Returns: BOOL, TRUE if the action was processed internally
//
BOOL OnUpgradePageProceed( HWND hwndDlg ) { TraceFileFunc(ttidGuiModeSetup);
int nIdx; int rgIdcShow[] = { BTN_UPGRADE_TYPICAL, BTN_UPGRADE_CUSTOM, TXT_UPGRADE_TYPICAL_1, TXT_UPGRADE_CUSTOM_1, TXT_UPGRADE_INSTRUCTIONS}; int rgIdcShowWorkstation[] = { BTN_UPGRADE_TYPICAL, BTN_UPGRADE_CUSTOM, TXT_UPGRADE_TYPICAL_1_WS, TXT_UPGRADE_CUSTOM_1, TXT_UPGRADE_INSTRUCTIONS}; int rgIdcHide[] = {TXT_UPGRADE_WAIT, IDC_UPGRADE_PROGRESS};
PRODUCT_FLAVOR pf; GetProductFlavor(NULL, &pf);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
// Expose the typical/custom controls on the upgrade page
// and hide the "working" controls unless there are no adapters
//
if (pWizard->PAdapterQueue()->FAdaptersInstalled()) { for (nIdx=0; nIdx < celems(rgIdcHide); nIdx++) ShowWindow(GetDlgItem(hwndDlg, rgIdcHide[nIdx]), SW_HIDE);
if (PF_WORKSTATION == pf) { for (nIdx=0; nIdx < celems(rgIdcShowWorkstation); nIdx++) ShowWindow(GetDlgItem(hwndDlg, rgIdcShowWorkstation[nIdx]), SW_SHOW); } else { for (nIdx=0; nIdx < celems(rgIdcShow); nIdx++) ShowWindow(GetDlgItem(hwndDlg, rgIdcShow[nIdx]), SW_SHOW); } }
::SetFocus(GetDlgItem(hwndDlg, BTN_UPGRADE_TYPICAL));
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
// If upgrading, or we're in one of the interesting unattended mode,
// or there are no adapters or this is sbs version then automatically
// advance the UI in "typical" mode. In case of sbs, join page also
// advances automatically.
//
// SBS requires a static IP address for the LAN network card and the
// networking configuration is done in SBS setup.
if (IsUpgrade(pWizard) || !pWizard->PAdapterQueue()->FAdaptersInstalled() || (IsUnattended(pWizard) && ((UM_FULLUNATTENDED == pWizard->GetUnattendedMode()) || (UM_DEFAULTHIDE == pWizard->GetUnattendedMode()) || (UM_READONLY == pWizard->GetUnattendedMode()))) || IsSBS()) { PostMessage(GetParent(hwndDlg), PSM_PRESSBUTTON, (WPARAM)(PSBTN_NEXT), 0); } else { // make sure the page is visible.
if (g_pSetupWizard != NULL) { g_pSetupWizard->PSetupData()->ShowHideWizardPage(TRUE); g_pSetupWizard->PSetupData()->BillBoardSetProgressText(TEXT("")); } }
return (TRUE); }
//
// Function: OnUpgradePageNext
//
// Purpose: Handle the PWN_WIZNEXT notification
//
// Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
//
// Returns: BOOL, TRUE if the action was processed internally
//
BOOL OnUpgradePageNext(HWND hwndDlg) { TraceFileFunc(ttidGuiModeSetup);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
pWizard->SetPageDirection(IDD_Upgrade, NWPD_BACKWARD);
// Based on UI selection, hide or unhide new adapters
//
if (IsDlgButtonChecked(hwndDlg, BTN_UPGRADE_TYPICAL)) { pWizard->PAdapterQueue()->HideAllAdapters(); } else { pWizard->PAdapterQueue()->UnhideNewAdapters(); }
return OnProcessNextAdapterPageNext(hwndDlg, FALSE); }
//
// Function: OnUpgradePagePrev
//
// Purpose: Handle the PWN_WIZBACK notification
//
// Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
//
// Returns: BOOL, TRUE if the action was processed internally
//
BOOL OnUpgradePagePrev(HWND hwndDlg) { TraceFileFunc(ttidGuiModeSetup);
// Retrieve the CWizard instance from the dialog
CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER)); Assert(NULL != pWizard);
pWizard->SetPageDirection(IDD_Upgrade, NWPD_FORWARD);
return FALSE; }
//
// Function: OnUpgradeInitDialog
//
// Purpose: Handle the InitDialog message for the upgrade page
//
// Parameters: hwndDlg [IN] - Handle to the upgrade page window
// lParam [IN] - LPARAM value from the WM_INITDIALOG message
//
// Returns: FALSE (let the dialog proc set focus)
//
BOOL OnUpgradeInitDialog(HWND hwndDlg, LPARAM lParam) { TraceFileFunc(ttidGuiModeSetup);
// Initialize our pointers to property sheet info.
//
PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; Assert(psp->lParam); ::SetWindowLongPtr(hwndDlg, DWLP_USER, psp->lParam);
// Cast the property sheet lParam data into the wizard which it is
//
CWizard * pWizard = reinterpret_cast<CWizard *>(psp->lParam); Assert(NULL != pWizard);
// Get the private data we stashed away for this page
//
lParam = pWizard->GetPageData(IDD_Upgrade); Assert(lParam); UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
// Start the progress
//
HWND hwndProgress = GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS);
// Subclass the progress and make it also call the BB callback.
// Only do this if we are called from GUI mode setup.
if (g_pSetupWizard != NULL) { PCWSTR str = SzLoadIds(IDS_BB_NETWORK); OldProgressProc = (WNDPROC)SetWindowLongPtr(hwndProgress,GWLP_WNDPROC,(LONG_PTR)NewProgessProc);
// Set the string for the progress on the billboard.
g_pSetupWizard->PSetupData()->BillBoardSetProgressText(str); }
SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0,c_nMaxProgressRange)); SendMessage(hwndProgress, PBM_SETPOS, 1, 0); SetTimer(hwndDlg, c_uiUpgradeRefreshID, c_uiUpgradeRefreshRate, NULL);
// Disable prev/next until initial work is complete
//
PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
// Default the mode buttons to typical
//
CheckRadioButton(hwndDlg, BTN_UPGRADE_TYPICAL, BTN_UPGRADE_CUSTOM, BTN_UPGRADE_TYPICAL);
// Create the bold font and apply to the mode buttons
//
SetupFonts(hwndDlg, &pData->hBoldFont, FALSE); if (pData->hBoldFont) { SetWindowFont(GetDlgItem(hwndDlg, BTN_UPGRADE_TYPICAL), pData->hBoldFont, FALSE); SetWindowFont(GetDlgItem(hwndDlg, BTN_UPGRADE_CUSTOM), pData->hBoldFont, FALSE); }
HICON hIcon = LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_LB_GEN_M_16)); if (hIcon) { SendMessage(GetDlgItem(hwndDlg, TXT_UPGRADE_ICON), STM_SETICON, (WPARAM)hIcon, 0L); }
return FALSE; }
//
// Function: dlgprocUpgrade
//
// Purpose: Dialog Procedure for the Upgrade wizard page
//
// Parameters: standard dlgproc parameters
//
// Returns: BOOL
//
INT_PTR CALLBACK dlgprocUpgrade(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { TraceFileFunc(ttidGuiModeSetup);
BOOL frt = FALSE;
switch (uMsg) { case PWM_EXIT: frt = OnUpgradePageExit(hwndDlg); break;
case PWM_PROCEED: frt = OnUpgradePageProceed(hwndDlg); break;
case WM_INITDIALOG: frt = OnUpgradeInitDialog(hwndDlg, lParam); break;
case WM_TIMER: OnUpgradeUpdateProgress(hwndDlg); break;
case WM_NOTIFY: { LPNMHDR pnmh = (LPNMHDR)lParam;
switch (pnmh->code) { // propsheet notification
case PSN_HELP: break;
case PSN_SETACTIVE: frt = OnUpgradePageActivate( hwndDlg ); break;
case PSN_APPLY: break;
case PSN_KILLACTIVE: break;
case PSN_RESET: break;
case PSN_WIZBACK: frt = OnUpgradePagePrev(hwndDlg); break;
case PSN_WIZFINISH: break;
case PSN_WIZNEXT: frt = OnUpgradePageNext(hwndDlg); break;
default: break; } } break;
default: break; }
return( frt ); }
//
// Function: UpgradePageCleanup
//
// Purpose: As a callback function to allow any page allocated memory
// to be cleaned up, after the page will no longer be accessed.
//
// Parameters: pWizard [IN] - The wizard against which the page called
// register page
// lParam [IN] - The lParam supplied in the RegisterPage call
//
// Returns: nothing
//
VOID UpgradePageCleanup(CWizard *pWizard, LPARAM lParam) { TraceFileFunc(ttidGuiModeSetup);
UpgradeData * pData; pData = reinterpret_cast<UpgradeData*>(lParam); if (NULL != pData) { DeleteObject(pData->hBoldFont); MemFree(pData); } }
//
// Function: CreateUpgradePage
//
// Purpose: To determine if the upgrade page needs to be shown, and to
// to create the page if requested. Note the upgrade page is
// responsible for initial installs also.
//
// Parameters: pWizard [IN] - Ptr to a Wizard instance
// pData [IN] - Context data to describe the world in
// which the Wizard will be run
// fCountOnly [IN] - If True, only the maximum number of
// pages this routine will create need
// be determined.
// pnPages [IN] - Increment by the number of pages
// to create/created
//
// Returns: HRESULT, S_OK on success
//
HRESULT HrCreateUpgradePage(CWizard *pWizard, PINTERNAL_SETUP_DATA pData, BOOL fCountOnly, UINT *pnPages) { TraceFileFunc(ttidGuiModeSetup);
HRESULT hr = S_OK;
// Batch Mode or for fresh install
if (!IsPostInstall(pWizard)) { (*pnPages)++;
// If not only counting, create and register the page
if (!fCountOnly) { HPROPSHEETPAGE hpsp; PROPSHEETPAGE psp;
TraceTag(ttidWizard, "Creating Upgrade Page");
hr = E_OUTOFMEMORY;
UpgradeData * pData = reinterpret_cast<UpgradeData*> (MemAlloc(sizeof(UpgradeData))); if (NULL == pData) { goto Error; }
pData->fProcessed = FALSE; pData->hBoldFont = NULL; pData->nCurrentCap = 0;
psp.dwSize = sizeof( PROPSHEETPAGE ); psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; psp.hInstance = _Module.GetResourceInstance(); psp.pszTemplate = MAKEINTRESOURCE( IDD_Upgrade ); psp.hIcon = NULL; psp.pfnDlgProc = dlgprocUpgrade; psp.lParam = reinterpret_cast<LPARAM>(pWizard); psp.pszHeaderTitle = SzLoadIds(IDS_T_Upgrade); psp.pszHeaderSubTitle = SzLoadIds(IDS_ST_Upgrade);
hpsp = CreatePropertySheetPage( &psp ); if (hpsp) { pWizard->RegisterPage(IDD_Upgrade, hpsp, UpgradePageCleanup, reinterpret_cast<LPARAM>(pData)); hr = S_OK; } else { MemFree(pData); } } }
Error: TraceHr(ttidWizard, FAL, hr, FALSE, "HrCreateUpgradePage"); return hr; }
//
// Function: AppendUpgradePage
//
// Purpose: Add the Upgrade page, if it was created, to the set of pages
// that will be displayed.
//
// Parameters: pahpsp [IN,OUT] - Array of pages to add our page to
// pcPages [IN,OUT] - Count of pages in pahpsp
//
// Returns: Nothing
//
VOID AppendUpgradePage(CWizard *pWizard, HPROPSHEETPAGE* pahpsp, UINT *pcPages) { TraceFileFunc(ttidGuiModeSetup);
if (!IsPostInstall(pWizard)) { HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_Upgrade); Assert(hPage); pahpsp[*pcPages] = hPage; (*pcPages)++; } }
|