Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2714 lines
82 KiB

#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)++;
}
}