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

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include <ndisguid.h>
  4. #include "afilexp.h"
  5. #include "edc.h"
  6. #include "lm.h"
  7. #include "nceh.h"
  8. #include "ncerror.h"
  9. #include "ncmisc.h"
  10. #include "ncnetcfg.h"
  11. #include "ncreg.h"
  12. #include "ncsvc.h"
  13. #include "ncsetup.h"
  14. #include "ncatlui.h"
  15. #include "netcfgn.h"
  16. #include "netsetup.h"
  17. #include "nslog.h"
  18. #include "nsres.h"
  19. #include "resource.h"
  20. #include "upgrade.h"
  21. #include "windns.h"
  22. #include "winstall.h"
  23. #include <hnetcfg.h>
  24. extern const WCHAR c_szInfId_MS_Server[];
  25. extern const WCHAR c_szInfId_MS_NwSapAgent[];
  26. extern const WCHAR c_szInfId_MS_DHCPServer[];
  27. extern const WCHAR c_szInfId_MS_NWClient[];
  28. extern const WCHAR c_szAfSectionNetworking[]; // L"Networking";
  29. extern const WCHAR c_szAfBuildNumber[]; // L"BuildNumber";
  30. extern const WCHAR c_szSvcWorkstation[]; // L"LanmanWorkstation";
  31. extern const WCHAR c_szInfId_MS_NetBIOS[];
  32. extern const WCHAR c_szInfId_MS_MSClient[]; // L"ms_msclient";
  33. const WCHAR PSZ_SPOOLER[] = L"Spooler";
  34. const WCHAR c_szSamEventName[] = L"\\SAM_SERVICE_STARTED";
  35. const WCHAR c_szLsaEventName[] = L"\\INSTALLATION_SECURITY_HOLD";
  36. const WCHAR c_szActiveComputerNameKey[] = L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName";
  37. const WCHAR c_szComputerNameKey[] = L"SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
  38. const WCHAR c_szComputerNameValue[] = L"ComputerName";
  39. const WCHAR c_szOCMKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\SubComponents";
  40. const WCHAR c_szDHCPServer[] = L"dhcpserver";
  41. const WCHAR c_szSapAgent[] = L"nwsapagent";
  42. // Unattended Mode related strings
  43. //
  44. const WCHAR c_szUnattendSection[] = L"Unattended";
  45. const WCHAR c_szUnattendMode[] = L"UnattendMode";
  46. const WCHAR c_szUMDefaultHide[] = L"DefaultHide";
  47. const WCHAR c_szUMGuiAttended[] = L"GuiAttended";
  48. const WCHAR c_szUMProvideDefault[] = L"ProvideDefault";
  49. const WCHAR c_szUMReadOnly[] = L"ReadOnly";
  50. const WCHAR c_szUMFullUnattended[] = L"FullUnattended";
  51. // Sysprep registry strings
  52. const WCHAR c_szSystemSetupKey[] = L"SYSTEM\\Setup";
  53. const WCHAR c_szMiniSetupInProgress[] = L"MiniSetupInProgress";
  54. const DWORD c_cmsWaitForINetCfgWrite = 120000;
  55. const UINT PWM_PROCEED = WM_USER+1202;
  56. const UINT PWM_EXIT = WM_USER+1203;
  57. const UINT c_uiUpgradeRefreshID = 7719;
  58. const UINT c_uiUpgradeRefreshRate = 5000; // Refresh rate in milliseconds
  59. EXTERN_C DWORD InstallUpgradeWorkThrd(InitThreadParam* pitp);
  60. // Setup Wizard Global - Only used during setup.
  61. extern CWizard * g_pSetupWizard;
  62. WNDPROC OldProgressProc;
  63. BOOL
  64. NewProgessProc(
  65. IN HWND hdlg,
  66. IN UINT msg,
  67. IN WPARAM wParam,
  68. IN LPARAM lParam
  69. )
  70. {
  71. switch (msg)
  72. {
  73. case PBM_DELTAPOS:
  74. case PBM_SETRANGE:
  75. case PBM_SETRANGE32:
  76. case PBM_STEPIT:
  77. case PBM_SETPOS:
  78. case PBM_SETSTEP:
  79. // Forward to the billboard progress.
  80. g_pSetupWizard->PSetupData()->BillboardProgressCallback(msg, wParam, lParam);
  81. break;
  82. }
  83. // Always call the progress on the wizard page.
  84. return (BOOL)CallWindowProc(OldProgressProc,hdlg,msg,wParam,lParam);
  85. }
  86. //
  87. // Function: SignalLsa
  88. //
  89. // Purpose: During initial setup, the winlogon creates a special event
  90. // (unsignalled) before it starts up Lsa. During initialization
  91. // lsa waits on this event. After Gui setup is done with setting
  92. // the AccountDomain sid it can signal the event. Lsa will then
  93. // continue initialization.
  94. //
  95. // Parameters: none
  96. //
  97. // Returns: nothing
  98. //
  99. BOOL SignalLsa(VOID)
  100. {
  101. TraceFileFunc(ttidGuiModeSetup);
  102. UNICODE_STRING UnicodeString;
  103. OBJECT_ATTRIBUTES Attributes;
  104. NTSTATUS Status;
  105. HANDLE Event;
  106. BOOL b;
  107. //
  108. // If the following event exists, it is an indication that
  109. // LSA is blocked at installation time and that we need to
  110. // signal this event.
  111. //
  112. // Unfortunately we have to use the NT APIs to do this, because
  113. // all events created/accessed via the Win32 APIs will be in the
  114. // BaseNamedObjects directory, and LSA doesn't know to look there.
  115. //
  116. RtlInitUnicodeString(&UnicodeString,c_szLsaEventName);
  117. InitializeObjectAttributes(&Attributes,&UnicodeString,0,0,NULL);
  118. Status = NtOpenEvent(&Event,EVENT_MODIFY_STATE,&Attributes);
  119. if(NT_SUCCESS(Status))
  120. {
  121. Status = NtSetEvent(Event,NULL);
  122. if(NT_SUCCESS(Status))
  123. {
  124. b = TRUE;
  125. }
  126. else
  127. {
  128. b = FALSE;
  129. }
  130. CloseHandle(Event);
  131. } else {
  132. b = FALSE;
  133. }
  134. return(b);
  135. }
  136. //
  137. // Function: CreateSamEvent
  138. //
  139. // Purpose: Create an event that SAM will use to tell us when it's finished
  140. // initializing.
  141. //
  142. // Parameters: phSamEvent [OUT] - Handle to the event object created
  143. //
  144. // Returns: BOOL, TRUE on success
  145. //
  146. BOOL CreateSamEvent(HANDLE * phSamEvent)
  147. {
  148. TraceFileFunc(ttidGuiModeSetup);
  149. UNICODE_STRING UnicodeString;
  150. OBJECT_ATTRIBUTES Attributes;
  151. NTSTATUS Status;
  152. //
  153. // Unfortunately we have to use the NT APIs to do this, because
  154. // all events created/accessed via the Win32 APIs will be in the
  155. // BaseNamedObjects directory, and SAM doesn't know to look there.
  156. //
  157. RtlInitUnicodeString(&UnicodeString,c_szSamEventName);
  158. InitializeObjectAttributes(&Attributes,&UnicodeString,0,0,NULL);
  159. Status = NtCreateEvent(phSamEvent,SYNCHRONIZE,&Attributes,NotificationEvent,FALSE);
  160. if(!NT_SUCCESS(Status)) {
  161. *phSamEvent = NULL;
  162. }
  163. return(NT_SUCCESS(Status));
  164. }
  165. //
  166. // Function: WaitForSam
  167. //
  168. // Purpose: Wait for SAM to finish initializing. We can tell when it's done
  169. // because an event we created earlier (see CreateSamEvent()) will
  170. // become signalled.
  171. //
  172. // Parameters: hSamEvent - HANDLE to wait for
  173. //
  174. // Returns: BOOL, TRUE on success
  175. //
  176. BOOL WaitForSam(HANDLE hSamEvent)
  177. {
  178. DWORD d;
  179. BOOL b = false;
  180. if (hSamEvent)
  181. {
  182. b = TRUE;
  183. d = WaitForSingleObject(hSamEvent,INFINITE);
  184. if(d != WAIT_OBJECT_0) {
  185. b = FALSE;
  186. TraceError("WaitForSam",E_UNEXPECTED);
  187. }
  188. }
  189. return(b);
  190. }
  191. //
  192. // Function: SyncSAM
  193. //
  194. // Purpose: Sychronize the SAM database and Lsa
  195. //
  196. // Parameters: pWizard [IN] - Ptr to a Wizard Instance
  197. //
  198. // Returns: nothing
  199. //
  200. VOID SyncSAM(CWizard *pWizard)
  201. {
  202. TraceFileFunc(ttidGuiModeSetup);
  203. HANDLE hSamEvent = NULL;
  204. Assert(!IsPostInstall(pWizard));
  205. TraceTag(ttidWizard,"Beginning SAM/Lsa Sync");
  206. // Sync the SAM DB
  207. CreateSamEvent(&hSamEvent);
  208. SignalLsa();
  209. if (hSamEvent)
  210. {
  211. WaitForSam(hSamEvent);
  212. CloseHandle(hSamEvent);
  213. }
  214. TraceTag(ttidWizard,"Completed SAM/Lsa Sync");
  215. }
  216. //
  217. // Function: IsComputerNameChanged
  218. //
  219. // Purpose: To determine if the active and intended computer names are the same
  220. //
  221. // Parameters: None.
  222. //
  223. // Returns: TRUE if the active and intended computer names are different.
  224. //
  225. BOOL
  226. IsComputerNameChanged (VOID)
  227. {
  228. TraceFileFunc(ttidGuiModeSetup);
  229. HRESULT hr;
  230. HKEY hkeyActive;
  231. HKEY hkeyIntended;
  232. BOOL fNameChanged;
  233. tstring strActive;
  234. tstring strIntended;
  235. fNameChanged = FALSE;
  236. // open the keys we need
  237. hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveComputerNameKey,
  238. KEY_READ, &hkeyActive );
  239. if (SUCCEEDED(hr))
  240. {
  241. hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szComputerNameKey,
  242. KEY_READ, &hkeyIntended );
  243. if ( SUCCEEDED(hr) )
  244. {
  245. hr = HrRegQueryString(hkeyIntended, c_szComputerNameValue, &strIntended);
  246. if ( SUCCEEDED(hr) )
  247. {
  248. hr = HrRegQueryString(hkeyActive, c_szComputerNameValue, &strActive);
  249. if ( SUCCEEDED(hr) )
  250. {
  251. fNameChanged = _wcsicmp( strActive.c_str(), strIntended.c_str() ) != 0;
  252. }
  253. }
  254. RegCloseKey( hkeyIntended );
  255. }
  256. RegCloseKey( hkeyActive );
  257. }
  258. return fNameChanged;
  259. }
  260. //
  261. // Function: HrSetActiveComputerName
  262. //
  263. // Purpose: To make sure the active and intended computer names are the same
  264. //
  265. // Parameters: pszNewName [IN] - the new computer name
  266. //
  267. // Returns: HRESULT, S_OK on success
  268. //
  269. HRESULT
  270. HrSetActiveComputerName (
  271. IN PCWSTR pszNewName)
  272. {
  273. TraceFileFunc(ttidGuiModeSetup);
  274. HRESULT hr;
  275. HKEY hkeyActive = NULL;
  276. HKEY hkeyIntended = NULL;
  277. tstring str;
  278. TraceTag(ttidWizard,"Setting the active computer name");
  279. // open the keys we need
  280. hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szActiveComputerNameKey,
  281. KEY_WRITE, &hkeyActive );
  282. if (FAILED(hr))
  283. goto Error;
  284. hr = HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szComputerNameKey,
  285. KEY_READ_WRITE, &hkeyIntended );
  286. if (FAILED(hr))
  287. goto Error;
  288. if (pszNewName == NULL)
  289. {
  290. hr = HrRegQueryString(hkeyIntended, c_szComputerNameValue, &str);
  291. pszNewName = str.c_str();
  292. }
  293. else
  294. {
  295. // set the intended computer name
  296. hr = HrRegSetSz(hkeyIntended, c_szComputerNameValue, pszNewName);
  297. }
  298. if (FAILED(hr))
  299. goto Error;
  300. // set the active computer name
  301. hr = HrRegSetSz(hkeyActive, c_szComputerNameValue, pszNewName);
  302. Error:
  303. // close it all up
  304. RegSafeCloseKey( hkeyActive );
  305. RegSafeCloseKey( hkeyIntended );
  306. TraceHr(ttidWizard, FAL, hr, FALSE, "HrSetActiveComputerName");
  307. return hr;
  308. }
  309. //
  310. // Function: HrInitAndGetINetCfg
  311. //
  312. // Purpose: To initialize an INetCfg instance and to do some preliminary
  313. // answerfile work (if an answer file is being used).
  314. //
  315. // Parameters: pWizard [IN] - Ptr to a wizard instance
  316. //
  317. // Returns: HRESULT, S_OK on success
  318. //
  319. HRESULT HrInitAndGetINetCfg(CWizard *pWizard)
  320. {
  321. TraceFileFunc(ttidGuiModeSetup);
  322. HRESULT hr = S_OK;
  323. Assert(NULL != pWizard);
  324. if (SUCCEEDED(hr))
  325. {
  326. PWSTR pszClientDesc = NULL;
  327. INetCfg* pNetCfg = NULL;
  328. BOOL fInitCom = !pWizard->FCoUninit();
  329. hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg, TRUE,
  330. c_cmsWaitForINetCfgWrite,
  331. SzLoadIds(IDS_WIZARD_CAPTION),
  332. &pszClientDesc);
  333. if (SUCCEEDED(hr))
  334. {
  335. // Retain our success in initializing COM only if we asked to
  336. // initialize COM in the first place.
  337. if (!pWizard->FCoUninit())
  338. {
  339. pWizard->SetCoUninit(fInitCom);
  340. }
  341. pWizard->SetNetCfg(pNetCfg);
  342. CoTaskMemFree(pszClientDesc);
  343. }
  344. }
  345. TraceHr(ttidWizard, FAL, hr, FALSE, "HrInitAndGetINetCfg");
  346. return hr;
  347. }
  348. //
  349. // Function: OnUpgradeUpdateProgress
  350. //
  351. // Purpose: Update the progress control during setup
  352. //
  353. // Parameters: Standard timer callback parameters
  354. //
  355. // Returns: nothing
  356. //
  357. VOID OnUpgradeUpdateProgress(HWND hwndDlg)
  358. {
  359. TraceFileFunc(ttidGuiModeSetup);
  360. CWizard * pWizard = reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  361. Assert(NULL != pWizard);
  362. LPARAM lParam = pWizard->GetPageData(IDD_Upgrade);
  363. Assert(lParam);
  364. UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
  365. if(pData)
  366. {
  367. // Get current position
  368. //
  369. HWND hwndProgress = GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS);
  370. Assert(hwndProgress);
  371. UINT nCurPos = (UINT)SendMessage(hwndProgress, PBM_GETPOS, 0, 0);
  372. // If the current position is less then the cap, advance
  373. //
  374. if (nCurPos < pData->nCurrentCap)
  375. {
  376. SendMessage(hwndProgress, PBM_SETPOS, ++nCurPos, 0);
  377. }
  378. }
  379. }
  380. //
  381. // Function: UpgradeSetProgressCap
  382. //
  383. // Purpose: Update the current cap for the progress control
  384. //
  385. // Parameters: hwndDlg - Handle to the current dialog
  386. // pWizard - Ptr to the wizard data
  387. // nNewCap - The new maximum progress cap
  388. //
  389. // Returns: nothing
  390. //
  391. VOID
  392. OnUpgradeUpdateProgressCap (
  393. HWND hwndDlg,
  394. CWizard* pWizard,
  395. UINT nNewCap)
  396. {
  397. TraceFileFunc(ttidGuiModeSetup);
  398. LPARAM lParam = pWizard->GetPageData(IDD_Upgrade);
  399. Assert(lParam);
  400. UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
  401. if(pData)
  402. {
  403. // Since we're increasing the progress cap, we need to advance the
  404. // progress indicator to the old cap.
  405. //
  406. SendMessage(GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS), PBM_SETPOS,
  407. pData->nCurrentCap, 0);
  408. // Retain the new cap
  409. //
  410. pData->nCurrentCap = nNewCap;
  411. }
  412. }
  413. //
  414. // Function:
  415. //
  416. // Purpose:
  417. //
  418. // Parameters:
  419. //
  420. // Returns:
  421. //
  422. VOID ReadAnswerFileSetupOptions(CWizard * pWizard)
  423. {
  424. TraceFileFunc(ttidGuiModeSetup);
  425. if (IsUnattended(pWizard))
  426. {
  427. // Get the unattended flags
  428. //
  429. CSetupInfFile csif;
  430. Assert(pWizard->PSetupData());
  431. Assert(pWizard->PSetupData()->UnattendFile);
  432. // Open the answser file
  433. //
  434. if (SUCCEEDED(csif.HrOpen(pWizard->PSetupData()->UnattendFile, NULL,
  435. INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL)))
  436. {
  437. tstring str;
  438. // Confirm no one has over written the default
  439. //
  440. Assert(UM_DEFAULTHIDE == pWizard->GetUnattendedMode());
  441. // Locate the UnattendMode string, if it exists
  442. //
  443. if (SUCCEEDED(csif.HrGetString(c_szUnattendSection,
  444. c_szUnattendMode, &str)))
  445. {
  446. struct
  447. {
  448. PCWSTR pszMode;
  449. UM_MODE UMMode;
  450. } UMModeMap[] = {{c_szUMDefaultHide,UM_DEFAULTHIDE},
  451. {c_szUMGuiAttended,UM_GUIATTENDED},
  452. {c_szUMProvideDefault,UM_PROVIDEDEFAULT},
  453. {c_szUMReadOnly,UM_READONLY},
  454. {c_szUMFullUnattended,UM_FULLUNATTENDED}};
  455. // Search the map for the unattended flag, note that if
  456. // we don't find it the default is UM_DEFAULTHIDE
  457. //
  458. for (UINT nIdx = 0; nIdx < celems(UMModeMap); nIdx++)
  459. {
  460. if (0 == _wcsicmp(str.c_str(),UMModeMap[nIdx].pszMode))
  461. {
  462. pWizard->SetUnattendedMode(UMModeMap[nIdx].UMMode);
  463. break;
  464. }
  465. }
  466. }
  467. }
  468. }
  469. }
  470. //
  471. // Function: StartSpooler
  472. //
  473. // Purpose: Start the spooler process before the components are applied
  474. // as some of the components want to install print monitors, and
  475. // the spooler needs to be running for this to succeed.
  476. //
  477. // Parameters: none
  478. //
  479. // Returns: nothing
  480. //
  481. VOID StartSpooler()
  482. {
  483. TraceFileFunc(ttidGuiModeSetup);
  484. CServiceManager csm;
  485. TraceTag(ttidWizard, "Attempting to start spooler");
  486. HRESULT hr = csm.HrStartServiceNoWait(PSZ_SPOOLER);
  487. TraceHr(ttidWizard, FAL, hr, FALSE,
  488. "*** StartSpooler - The spooler failed to start, you probably "
  489. "won't have networking ***");
  490. }
  491. //
  492. // Function: HrCommitINetCfgChanges
  493. //
  494. // Purpose: Validate and Commit changes to the INetCfg object
  495. //
  496. // Parameters: hwnd [IN] - Handle of the current window
  497. // pWizard [IN] - Ptr to a wizard instance
  498. //
  499. // Returns: HRESULT, S_OK on success
  500. //
  501. HRESULT HrCommitINetCfgChanges(HWND hwnd, CWizard * pWizard)
  502. {
  503. TraceFileFunc(ttidGuiModeSetup);
  504. INetCfg * pNetCfg = pWizard->PNetCfg();
  505. Assert(NULL != pNetCfg);
  506. // Commit the changes
  507. TraceTag(ttidWizard,"HrCommitINetCfgChanges - Applying changes");
  508. HRESULT hr = pNetCfg->Apply();
  509. if (S_FALSE == hr)
  510. {
  511. hr = S_OK;
  512. }
  513. TraceHr(ttidWizard, FAL, hr, FALSE, "HrCommitINetCfgChanges");
  514. return hr;
  515. }
  516. //
  517. // Function: IsSBS
  518. //
  519. // Purpose: Determine if it is SBS version.
  520. //
  521. // Parameters: None
  522. //
  523. // Returns: BOOL, TRUE if it is Microsoft Small Business Server
  524. //
  525. BOOL IsSBS (VOID)
  526. {
  527. TraceFileFunc(ttidGuiModeSetup);
  528. OSVERSIONINFOEX ose;
  529. BOOL bVersionRet;
  530. ZeroMemory(&ose, sizeof(ose));
  531. ose.dwOSVersionInfoSize = sizeof(ose);
  532. bVersionRet = GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&ose));
  533. return (bVersionRet && (ose.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED));
  534. }
  535. //
  536. // Function: IsMSClientInstalled
  537. //
  538. // Purpose: Determine if MSClient is installed.
  539. //
  540. // Parameters: hwnd [IN] - Handle of the current window
  541. // pWizard [IN] - Ptr to a wizard instance
  542. //
  543. // Returns: BOOL, TRUE if MS Client is installed, otherwise
  544. //
  545. BOOL IsMSClientInstalled(HWND hwnd, CWizard * pWizard)
  546. {
  547. INetCfg *pNetCfg;
  548. INetCfgComponent *pncc;
  549. HRESULT hr;
  550. TraceFileFunc(ttidGuiModeSetup);
  551. Assert(NULL != pWizard);
  552. if ( !pWizard )
  553. {
  554. return FALSE;
  555. }
  556. pNetCfg = pWizard->PNetCfg();
  557. Assert(NULL != pNetCfg);
  558. if ( !pNetCfg )
  559. {
  560. return FALSE;
  561. }
  562. hr = pNetCfg->FindComponent(c_szInfId_MS_MSClient, &pncc);
  563. if ( hr == S_OK )
  564. {
  565. ReleaseObj(pncc);
  566. }
  567. TraceHr(ttidWizard, FAL, hr, FALSE, "IsMSClientInstalled");
  568. return hr == S_OK;
  569. }
  570. //
  571. // Function:
  572. //
  573. // Purpose:
  574. //
  575. // Parameters:
  576. //
  577. // Returns:
  578. //
  579. BOOL OnProcessPrevAdapterPagePrev(HWND hwndDlg, UINT idd)
  580. {
  581. TraceFileFunc(ttidGuiModeSetup);
  582. BOOL fRet = FALSE;
  583. CWizard * pWizard =
  584. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  585. Assert(NULL != pWizard);
  586. HPROPSHEETPAGE hPage;
  587. GUID * pguidAdapter = pWizard->PAdapterQueue()->PrevAdapter();
  588. if (NULL != pguidAdapter)
  589. {
  590. pWizard->SetCurrentProvider(0);
  591. CWizProvider * pWizProvider = pWizard->GetCurrentProvider();
  592. Assert(NULL != pWizProvider);
  593. Assert(pWizProvider->ULPageCount());
  594. // Reset the providers guard page to point forward
  595. LPARAM ulId = reinterpret_cast<LPARAM>(pWizProvider);
  596. pWizard->SetPageDirection(ulId, NWPD_FORWARD);
  597. // Push the adapter guid onto the provider
  598. HRESULT hr = pWizProvider->HrSpecifyAdapterGuid(pguidAdapter);
  599. if (SUCCEEDED(hr))
  600. {
  601. // Get the last page from the provider
  602. TraceTag(ttidWizard, "Jumping to LAN provider last page...");
  603. hPage = (pWizProvider->PHPropPages())[pWizProvider->ULPageCount() - 1];
  604. Assert(hPage);
  605. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  606. PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0,
  607. (LPARAM)(HPROPSHEETPAGE)hPage);
  608. fRet = TRUE; // We jumped to a provider page
  609. }
  610. }
  611. else
  612. {
  613. if (idd)
  614. {
  615. hPage = pWizard->GetPageHandle(idd);
  616. Assert(hPage);
  617. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  618. PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0,
  619. (LPARAM)(HPROPSHEETPAGE)hPage);
  620. }
  621. }
  622. return fRet;
  623. }
  624. //
  625. // Function: OBOUserAddRefSpecialCase
  626. //
  627. // Purpose: Handle a special case where when upgrading from NT351 or NT 4
  628. // with MS's "File and Print" and GSNW. In this case we need to
  629. // AddRef OBOUser F&P, so removal of GSNW does not remove F&P.
  630. //
  631. // Parameters: pWizard [IN] - Context information
  632. //
  633. // Returns: Nothing. (this is basically a do it if we can special case.)
  634. //
  635. VOID OBOUserAddRefSpecialCase(CWizard * pWizard)
  636. {
  637. TraceFileFunc(ttidGuiModeSetup);
  638. CSetupInfFile csif;
  639. HRESULT hr = S_OK;
  640. Assert(pWizard->PNetCfg());
  641. Assert(IsUnattended(pWizard));
  642. TraceTag(ttidWizard, "OBOUserAddRefSpecialCase - Start");
  643. // if we're upgrading from NT 3.51 or NT 4
  644. //
  645. if (pWizard->PSetupData()->UnattendFile)
  646. {
  647. /* DWORD dwBuild = 0;
  648. hr = csif.HrOpen(pWizard->PSetupData()->UnattendFile,
  649. NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  650. if (SUCCEEDED(hr))
  651. {
  652. hr = csif.HrGetDword(c_szAfSectionNetworking, c_szAfBuildNumber, &dwBuild);
  653. }
  654. if (SUCCEEDED(hr) && (dwBuild <= wWinNT4BuildNumber))
  655. {*/
  656. PRODUCT_FLAVOR pf;
  657. // If this is an NT server (GSNW is server only)
  658. //
  659. GetProductFlavor(NULL, &pf);
  660. if (PF_WORKSTATION != pf)
  661. {
  662. const GUID * rgguidClass[2] = {&GUID_DEVCLASS_NETSERVICE,
  663. &GUID_DEVCLASS_NETCLIENT};
  664. const PCWSTR rgpszComponentId[2] = {c_szInfId_MS_Server,
  665. c_szInfId_MS_NWClient};
  666. INetCfgComponent* rgpncc[2] = {NULL, NULL};
  667. hr = HrFindComponents (pWizard->PNetCfg(), 2, rgguidClass,
  668. rgpszComponentId, rgpncc);
  669. if (SUCCEEDED(hr))
  670. {
  671. // Are both "GSNW" and "File and Print" installed?
  672. //
  673. if (rgpncc[0] && rgpncc[1])
  674. {
  675. NETWORK_INSTALL_PARAMS nip = {0};
  676. nip.dwSetupFlags = NSF_PRIMARYINSTALL;
  677. // re-install OBOUser "File and Print"
  678. //
  679. TraceTag(ttidWizard, " OBOUser Install of File and Print Services");
  680. TraceTag(ttidWizard, " On upgrade from NT 3.51 or NT 4");
  681. (void)HrInstallComponentsOboUser(pWizard->PNetCfg(), &nip, 1,
  682. &rgguidClass[0],
  683. &rgpszComponentId[0]);
  684. }
  685. ReleaseObj(rgpncc[0]);
  686. ReleaseObj(rgpncc[1]);
  687. }
  688. }
  689. /// }
  690. }
  691. TraceTag(ttidWizard, "OBOUserAddRefSpecialCase - End");
  692. TraceError("OBOUserAddRefSpecialCase",hr);
  693. }
  694. //
  695. // Function:
  696. //
  697. // Purpose:
  698. //
  699. // Parameters:
  700. //
  701. // Returns:
  702. //
  703. BOOL OnProcessNextAdapterPageNext(HWND hwndDlg, BOOL FOnActivate)
  704. {
  705. TraceFileFunc(ttidGuiModeSetup);
  706. // Retrieve the CWizard instance from the dialog
  707. CWizard * pWizard =
  708. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  709. Assert(NULL != pWizard);
  710. HRESULT hr = S_OK;
  711. BOOL fRet = FALSE;
  712. HPROPSHEETPAGE hPage;
  713. GUID * pguidAdapter;
  714. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  715. // Refresh the contents of the adapter queue.
  716. // ATM adapters may have been added or removed
  717. if (pWizard->FProcessLanPages())
  718. {
  719. // Commit changes and look for any new adapters
  720. (VOID)HrCommitINetCfgChanges(GetParent(hwndDlg), pWizard);
  721. (VOID)pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pWizard);
  722. }
  723. // If there are adapters left to process prime the pump
  724. pguidAdapter = pWizard->PAdapterQueue()->NextAdapter();
  725. if (NULL != pguidAdapter)
  726. {
  727. pWizard->SetCurrentProvider(0);
  728. CWizProvider * pWizProvider = pWizard->GetCurrentProvider();
  729. Assert(NULL != pWizProvider);
  730. Assert(pWizProvider->ULPageCount());
  731. // Push the adapter guid onto the provider
  732. hr = pWizProvider->HrSpecifyAdapterGuid(pguidAdapter);
  733. if (SUCCEEDED(hr))
  734. {
  735. #if DBG
  736. WCHAR szGuid[c_cchGuidWithTerm];
  737. Assert(pguidAdapter);
  738. if (SUCCEEDED(StringFromGUID2(*pguidAdapter, szGuid,
  739. c_cchGuidWithTerm)))
  740. {
  741. TraceTag(ttidWizard, " Calling LAN pages for Adapter Guid: %S", szGuid);
  742. }
  743. #endif
  744. // Reset the providers guard page to point forward
  745. LPARAM ulId = reinterpret_cast<LPARAM>(pWizProvider);
  746. pWizard->SetPageDirection(ulId, NWPD_FORWARD);
  747. // Get the first page from the provider
  748. hPage = (pWizProvider->PHPropPages())[0];
  749. Assert(hPage);
  750. PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0,
  751. (LPARAM)(HPROPSHEETPAGE)hPage);
  752. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
  753. TraceTag(ttidWizard, "Jumping to LAN provider first page...");
  754. fRet = TRUE; // We processed it
  755. }
  756. }
  757. // If there are no adapters left to process, or an error occurred
  758. if ((NULL == pguidAdapter) || FAILED(hr))
  759. {
  760. UINT idd = IDD_Exit;
  761. // Commit any changes to INetCfg.
  762. if (SUCCEEDED(hr) && pWizard->FProcessLanPages())
  763. {
  764. // Commit changes
  765. (VOID)HrCommitINetCfgChanges(GetParent(hwndDlg), pWizard);
  766. }
  767. if (!IsPostInstall(pWizard) && IsMSClientInstalled(GetParent(hwndDlg), pWizard))
  768. {
  769. idd = IDD_Join;
  770. TraceTag(ttidWizard, "Jumping to Join page...");
  771. }
  772. else
  773. {
  774. TraceTag(ttidWizard, "Jumping to Exit page...");
  775. }
  776. if (FOnActivate)
  777. {
  778. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, idd);
  779. }
  780. else
  781. {
  782. // else goto the appropriate page
  783. hPage = pWizard->GetPageHandle(idd);
  784. Assert(hPage);
  785. PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0, (LPARAM)hPage);
  786. }
  787. fRet = TRUE; // We processed it
  788. }
  789. Assert(TRUE == fRet);
  790. return fRet;
  791. }
  792. //
  793. // Function: FixupOldOcComponents
  794. //
  795. // Purpose: Convert SAP and DHCP optional components (if present) into
  796. // regular networking components.
  797. //
  798. // Parameters: pWizard
  799. //
  800. // Returns: nothing
  801. //
  802. void FixupOldOcComponents(CWizard * pWizard)
  803. {
  804. TraceFileFunc(ttidGuiModeSetup);
  805. HRESULT hr;
  806. static const GUID* c_apguidInstalledComponentClasses [] =
  807. {
  808. &GUID_DEVCLASS_NETSERVICE, // DHCP
  809. &GUID_DEVCLASS_NETSERVICE, // SAP Agent
  810. };
  811. static const PCWSTR c_apszInstalledComponentIds [] =
  812. {
  813. c_szInfId_MS_DHCPServer,
  814. c_szInfId_MS_NwSapAgent,
  815. };
  816. static const PCWSTR c_apszOcNames[] =
  817. {
  818. c_szDHCPServer,
  819. c_szSapAgent,
  820. };
  821. // If component was installed as an optional component
  822. //
  823. HKEY hkey;
  824. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szOCMKey, KEY_READ_WRITE, &hkey);
  825. if (SUCCEEDED(hr))
  826. {
  827. DWORD dw;
  828. for (UINT idx=0; idx<celems(c_apszOcNames); idx++)
  829. {
  830. // Remove the OC Manager reference
  831. //
  832. hr = HrRegQueryDword (hkey, c_apszOcNames[idx], &dw);
  833. if (SUCCEEDED(hr))
  834. {
  835. if (dw)
  836. {
  837. // Install OBO user the component
  838. //
  839. NETWORK_INSTALL_PARAMS nip = {0};
  840. // Note: Claiming it's a server upgrade is a bit bogus,
  841. // but is needed so dhcpsobj.cpp doesn't display
  842. // UI.
  843. //
  844. nip.dwSetupFlags |= NSF_WINNT_SVR_UPGRADE;
  845. nip.dwSetupFlags |= NSF_PRIMARYINSTALL;
  846. (void)HrInstallComponentsOboUser(pWizard->PNetCfg(), &nip, 1,
  847. &c_apguidInstalledComponentClasses[idx],
  848. &c_apszInstalledComponentIds[idx]);
  849. }
  850. // Delete the value
  851. //
  852. (VOID)HrRegDeleteValue(hkey, c_apszOcNames[idx]);
  853. }
  854. }
  855. RegCloseKey(hkey);
  856. }
  857. }
  858. struct NAME_DATA
  859. {
  860. PCWSTR pszComputerName;
  861. };
  862. //+---------------------------------------------------------------------------
  863. //
  864. // Function: DuplicateNameProc
  865. //
  866. // Purpose: Dialog procedure for the duplicate name dialog
  867. //
  868. // Arguments:
  869. // hwndDlg []
  870. // uMsg [] See MSDN
  871. // wParam []
  872. // lParam []
  873. //
  874. // Returns:
  875. //
  876. // Author: danielwe 16 Feb 1999
  877. //
  878. // Notes:
  879. //
  880. INT_PTR
  881. CALLBACK
  882. DuplicateNameProc(
  883. HWND hwndDlg,
  884. UINT uMsg,
  885. WPARAM wParam,
  886. LPARAM lParam)
  887. {
  888. TraceFileFunc(ttidGuiModeSetup);
  889. BOOL frt = FALSE;
  890. WCHAR szBuf[1024];
  891. WCHAR szText[1024];
  892. NAME_DATA * pData;
  893. switch (uMsg)
  894. {
  895. case WM_INITDIALOG:
  896. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);
  897. pData = (NAME_DATA *)lParam;
  898. Assert(pData->pszComputerName);
  899. GetDlgItemText(hwndDlg, TXT_Caption, szText, celems(szText));
  900. // add computer name to title
  901. wsprintfW(szBuf, szText, pData->pszComputerName);
  902. SetDlgItemText(hwndDlg, TXT_Caption, szBuf);
  903. // limit text in edit control
  904. SendDlgItemMessage(hwndDlg, EDT_New_Name, EM_LIMITTEXT,
  905. (WPARAM)MAX_COMPUTERNAME_LENGTH, 0);
  906. return TRUE;
  907. case WM_COMMAND:
  908. switch (HIWORD(wParam))
  909. {
  910. case BN_CLICKED:
  911. switch (LOWORD(wParam))
  912. {
  913. case IDOK:
  914. NET_API_STATUS nas;
  915. GetDlgItemText(hwndDlg, EDT_New_Name, szBuf, celems(szBuf));
  916. nas = NetValidateName(NULL, szBuf, NULL, NULL,
  917. NetSetupMachine);
  918. if (nas != NO_ERROR)
  919. {
  920. UINT ids;
  921. if (nas == ERROR_DUP_NAME)
  922. {
  923. ids = IDS_E_COMPUTER_NAME_DUPE;
  924. TraceTag(ttidWizard, "Computer name %S"
  925. " is a dupe.", szBuf);
  926. }
  927. else
  928. {
  929. ids = IDS_E_COMPUTER_NAME_INVALID;
  930. TraceTag(ttidWizard, "Computer name %S"
  931. " is invalid.", szBuf);
  932. }
  933. MessageBeep(MB_ICONSTOP);
  934. MessageBox(hwndDlg, SzLoadIds(ids),
  935. SzLoadIds(IDS_SETUP_CAPTION),
  936. MB_ICONSTOP | MB_OK);
  937. SetFocus(GetDlgItem(hwndDlg, EDT_New_Name));
  938. Edit_SetSel(GetDlgItem(hwndDlg, EDT_New_Name), 0, -1);
  939. }
  940. else
  941. {
  942. // 398325/406259 : trying to keep DNS names lowercased
  943. //
  944. LowerCaseComputerName(szBuf);
  945. if (!SetComputerNameEx(ComputerNamePhysicalDnsHostname,
  946. szBuf))
  947. {
  948. TraceLastWin32Error("SetComputerNameEx");
  949. }
  950. else
  951. {
  952. CServiceManager sm;
  953. (VOID)HrSetActiveComputerName(NULL);
  954. TraceTag(ttidWizard, "Setting new computer name "
  955. "%S.", szBuf);
  956. TraceTag(ttidWizard, "Restarting workstation service"
  957. "...");
  958. (VOID) sm.HrStartServiceAndWait(c_szSvcWorkstation);
  959. }
  960. EndDialog(hwndDlg, 0);
  961. }
  962. break;
  963. }
  964. break;
  965. }
  966. break;
  967. default:
  968. frt = FALSE;
  969. break;
  970. }
  971. return frt;
  972. }
  973. //+---------------------------------------------------------------------------
  974. //
  975. // Function: GenerateComputerNameBasedOnOrganizationName
  976. //
  977. // Purpose: Generate a random computer name based on the register user name
  978. // and organization name
  979. //
  980. // Arguments:
  981. // pszGeneratedStringOut Generated Computer Name - allocated by caller
  982. // dwDesiredStrLenIn Desired length of Computer Name
  983. //
  984. // Returns:
  985. //
  986. // Author: deonb 22 April 2000
  987. //
  988. // Notes:
  989. //
  990. VOID GenerateComputerNameBasedOnOrganizationName(
  991. LPWSTR pszGeneratedStringOut, // the generated computer name
  992. DWORD dwDesiredStrLenIn // desired length for the computer name
  993. )
  994. {
  995. TraceFileFunc(ttidGuiModeSetup);
  996. static DWORD dwSeed = 98725757;
  997. static LPCWSTR UsableChars = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  998. static LPCWSTR RegKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
  999. static LPCWSTR RegOwner = REGSTR_VAL_REGOWNER;
  1000. static LPCWSTR RegOrganization = REGSTR_VAL_REGORGANIZATION;
  1001. WCHAR pszNameOrgNameIn[MAX_PATH+1];
  1002. WCHAR pszNameOrgOrgIn[MAX_PATH+1]; // organization the computer is registered to
  1003. pszNameOrgNameIn[0] = pszNameOrgNameIn[MAX_PATH] = NULL;
  1004. pszNameOrgOrgIn[0] = pszNameOrgOrgIn[MAX_PATH] = NULL;
  1005. HKEY hkResult = NULL;
  1006. HRESULT hr;
  1007. hr = HrRegOpenKeyBestAccess(HKEY_LOCAL_MACHINE, RegKey, &hkResult);
  1008. if (SUCCEEDED(hr))
  1009. {
  1010. tstring pstr;
  1011. hr = HrRegQueryString(hkResult, RegOwner, &pstr);
  1012. if (SUCCEEDED(hr))
  1013. wcsncpy(pszNameOrgNameIn, pstr.c_str(), MAX_PATH);
  1014. hr = HrRegQueryString(hkResult, RegOrganization, &pstr);
  1015. if (SUCCEEDED(hr))
  1016. wcsncpy(pszNameOrgOrgIn, pstr.c_str(), MAX_PATH);
  1017. RegCloseKey(hkResult);
  1018. }
  1019. //
  1020. // How many characters will come from the org/name string.
  1021. //
  1022. DWORD BaseLength = 8;
  1023. DWORD i,j;
  1024. DWORD UsableCount;
  1025. if( dwDesiredStrLenIn <= BaseLength )
  1026. {
  1027. BaseLength = dwDesiredStrLenIn - 1;
  1028. }
  1029. if( pszNameOrgOrgIn[0] )
  1030. {
  1031. wcsncpy( pszGeneratedStringOut, pszNameOrgOrgIn, dwDesiredStrLenIn );
  1032. } else if( pszNameOrgNameIn[0] )
  1033. {
  1034. wcsncpy( pszGeneratedStringOut, pszNameOrgNameIn, dwDesiredStrLenIn );
  1035. } else
  1036. {
  1037. wcscpy( pszGeneratedStringOut, L"X" );
  1038. for( i = 1; i < BaseLength; i++ )
  1039. {
  1040. wcscat( pszGeneratedStringOut, L"X" );
  1041. }
  1042. }
  1043. //
  1044. // Get him upper-case for our filter...
  1045. //
  1046. CharUpper( pszGeneratedStringOut );
  1047. //
  1048. // Now we want to put a '-' at the end
  1049. // of our pszGeneratedStringOut. We'd like it to
  1050. // be placed in the BASE_LENGTH character, but
  1051. // the string may be shorter than that, or may
  1052. // even have a ' ' in it. Figure out where to
  1053. // put the '-' now.
  1054. //
  1055. for( i = 0; i <= BaseLength; i++ )
  1056. {
  1057. //
  1058. // Check for a short string.
  1059. //
  1060. if( ( pszGeneratedStringOut[i] == 0 ) ||
  1061. ( pszGeneratedStringOut[i] == L' ' ) ||
  1062. ( ! wcschr(UsableChars, pszGeneratedStringOut[i] ) ) ||
  1063. ( i == BaseLength )
  1064. )
  1065. {
  1066. pszGeneratedStringOut[i] = L'-';
  1067. pszGeneratedStringOut[i+1] = 0;
  1068. break;
  1069. }
  1070. }
  1071. //
  1072. // Special case the scenario where we had no usable
  1073. // characters.
  1074. //
  1075. if( pszGeneratedStringOut[0] == L'-' )
  1076. {
  1077. pszGeneratedStringOut[0] = 0;
  1078. }
  1079. UsableCount = wcslen(UsableChars);
  1080. GUID gdRandom;
  1081. CoCreateGuid(&gdRandom);
  1082. LPBYTE lpGuid = reinterpret_cast<LPBYTE>(&gdRandom);
  1083. j = wcslen( pszGeneratedStringOut );
  1084. for( i = j; i < dwDesiredStrLenIn; i++ )
  1085. {
  1086. pszGeneratedStringOut[i] = UsableChars[lpGuid[i % sizeof(GUID)] % UsableCount];
  1087. }
  1088. pszGeneratedStringOut[i] = 0;
  1089. CharUpper(pszGeneratedStringOut);
  1090. }
  1091. //+---------------------------------------------------------------------------
  1092. //
  1093. // Function: EnsureUniqueComputerName
  1094. //
  1095. // Purpose: Ensures that the computer name entered in the first part of
  1096. // GUI mode setup (note: this UI is not owned by NetCfg) is
  1097. // unique. User is prompted to enter a new name if this is not
  1098. // the case.
  1099. //
  1100. // Arguments:
  1101. // hwndDlg [in] Parent window
  1102. // bIsUnattended Do not pop up dialog box to ask for computer name
  1103. // - rather generate a random unique name.
  1104. //
  1105. // Returns: Nothing
  1106. //
  1107. // Author: danielwe 16 Feb 1999
  1108. //
  1109. // Notes: Workstation service is stopped and restarted when new name is
  1110. // entered so the change can take effect and domain join can
  1111. // succeed.
  1112. //
  1113. VOID EnsureUniqueComputerName(HWND hwndDlg, BOOL bIsUnattended)
  1114. {
  1115. TraceFileFunc(ttidGuiModeSetup);
  1116. NET_API_STATUS nas;
  1117. WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1118. DWORD cchName = celems(szComputerName);
  1119. NAME_DATA nd = {0};
  1120. if (GetComputerNameEx(ComputerNameNetBIOS,
  1121. reinterpret_cast<PWSTR>(&szComputerName),
  1122. &cchName))
  1123. {
  1124. CServiceManager sm;
  1125. CService service;
  1126. BOOL fRestart = FALSE;
  1127. DWORD dwState;
  1128. // Open the workstation service and figure out if it is running. If
  1129. // so we'll need to stop it and note that we need to restart it when
  1130. // we're done verifying the computer name.
  1131. //
  1132. if (SUCCEEDED(sm.HrOpenService(&service, c_szSvcWorkstation)))
  1133. {
  1134. if (SUCCEEDED(service.HrQueryState(&dwState)) &&
  1135. (dwState == SERVICE_RUNNING))
  1136. {
  1137. TraceTag(ttidWizard, "Stopping workstation service...");
  1138. (VOID) sm.HrStopServiceAndWait(c_szSvcWorkstation);
  1139. fRestart = TRUE;
  1140. }
  1141. }
  1142. // NetValidateName() should work without the workstation service
  1143. // being started. In fact, it *has* to work like this because otherwise
  1144. // the machine will find itself as a duplicate name.. Not good.
  1145. //
  1146. DWORD dwNumTries = 10;
  1147. do
  1148. {
  1149. nas = NetValidateName(NULL, szComputerName, NULL, NULL,
  1150. NetSetupMachine);
  1151. if (nas == ERROR_DUP_NAME)
  1152. {
  1153. INT irt;
  1154. TraceTag(ttidWizard, "Displaying UI to change duplicate computer "
  1155. "name %S.", szComputerName);
  1156. nd.pszComputerName = szComputerName;
  1157. if (!bIsUnattended)
  1158. {
  1159. irt = (INT)DialogBoxParam(_Module.GetResourceInstance(),
  1160. MAKEINTRESOURCE(IDD_Duplicate_Name),
  1161. hwndDlg,
  1162. DuplicateNameProc,
  1163. (LPARAM)&nd);
  1164. }
  1165. else
  1166. {
  1167. WCHAR szOldComputerName[MAX_COMPUTERNAME_LENGTH+1];
  1168. // In case the computer name is 15 characters long, wcsncpy won't append
  1169. // NULL string. So we put one in the last element.
  1170. szOldComputerName[MAX_COMPUTERNAME_LENGTH] = NULL;
  1171. wcsncpy(szOldComputerName, szComputerName, MAX_COMPUTERNAME_LENGTH);
  1172. ZeroMemory( szComputerName, sizeof(WCHAR) * (MAX_COMPUTERNAME_LENGTH+1) );
  1173. GenerateComputerNameBasedOnOrganizationName(szComputerName, MAX_COMPUTERNAME_LENGTH);
  1174. NetSetupLogStatusV( LogSevWarning,
  1175. SzLoadIds (IDS_E_UNATTENDED_COMPUTER_NAME_CHANGED),
  1176. szOldComputerName, szComputerName
  1177. );
  1178. LowerCaseComputerName(szComputerName);
  1179. if (!SetComputerNameEx(ComputerNamePhysicalDnsHostname, szComputerName))
  1180. {
  1181. TraceLastWin32Error("SetComputerNameEx");
  1182. }
  1183. else
  1184. {
  1185. (VOID)HrSetActiveComputerName(NULL);
  1186. TraceTag(ttidWizard, "Setting new computer name %S.", szComputerName);
  1187. }
  1188. }
  1189. }
  1190. else
  1191. {
  1192. TraceTag(ttidWizard, "Name is already unique.");
  1193. // Restart the workstation service if necessary.
  1194. //
  1195. if (fRestart)
  1196. {
  1197. TraceTag(ttidWizard, "Restarting Workstation service...");
  1198. (VOID) sm.HrStartServiceAndWait(c_szSvcWorkstation);
  1199. }
  1200. }
  1201. } while ( (ERROR_DUP_NAME == nas) && (dwNumTries--) && (bIsUnattended) );
  1202. }
  1203. else
  1204. {
  1205. TraceLastWin32Error("EnsureUniqueComputerName - GetComputerNameEx");
  1206. }
  1207. }
  1208. //+---------------------------------------------------------------------------
  1209. //
  1210. // Function: ValidateNetBiosName
  1211. //
  1212. // Purpose: Ensures that the computer name is a valid DNS name e.g. when
  1213. // upgrading from a previous O/S. If not it logs an error to the
  1214. // setuperr.log
  1215. //
  1216. // Arguments: nothing
  1217. //
  1218. // Returns: S_OK if valid
  1219. // S_FALSE if invalid
  1220. // E_FAIL if failed
  1221. //
  1222. // Author: deonb 2 May 2000
  1223. //
  1224. // Notes:
  1225. HRESULT ValidateNetBiosName()
  1226. {
  1227. TraceFileFunc(ttidGuiModeSetup);
  1228. WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1229. DWORD cchName = celems(szComputerName);
  1230. if (GetComputerNameEx(ComputerNameNetBIOS,
  1231. reinterpret_cast<PWSTR>(&szComputerName),
  1232. &cchName))
  1233. {
  1234. DNS_STATUS dnsStatus = DnsValidateName(szComputerName, DnsNameHostnameLabel);
  1235. switch (dnsStatus)
  1236. {
  1237. case ERROR_SUCCESS:
  1238. return S_OK;
  1239. case ERROR_INVALID_NAME:
  1240. NetSetupLogStatusV( LogSevWarning,
  1241. SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME));
  1242. return S_FALSE;
  1243. case DNS_ERROR_INVALID_NAME_CHAR:
  1244. NetSetupLogStatusV( LogSevWarning,
  1245. SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME_CHAR));
  1246. return S_FALSE;
  1247. case DNS_ERROR_NON_RFC_NAME:
  1248. NetSetupLogStatusV( LogSevWarning,
  1249. SzLoadIds (IDS_E_UPGRADE_DNS_INVALID_NAME_NONRFC));
  1250. return S_FALSE;
  1251. default:
  1252. TraceError("ValidateComputerName - DnsValidateName", dnsStatus);
  1253. return E_FAIL;
  1254. }
  1255. }
  1256. else
  1257. {
  1258. TraceLastWin32Error("ValidateComputerName - GetComputerNameEx");
  1259. return E_FAIL;
  1260. }
  1261. }
  1262. //
  1263. // Function: HrSetupGetSourceInfo
  1264. //
  1265. // Purpose: Allocates, gets, and returns the required Setup info
  1266. //
  1267. // Parameters: hinf [IN] - setup hinf handle
  1268. // SrcId [IN] - source id obtained from setup
  1269. // InfoDesired [IN] - indicates what info is desired
  1270. // ppsz [OUT] - ptr to string to be filled and returned
  1271. //
  1272. // Returns: HRESULT
  1273. //
  1274. HRESULT
  1275. HrSetupGetSourceInfo(
  1276. IN HINF hinf,
  1277. IN UINT SrcId,
  1278. IN UINT InfoDesired,
  1279. OUT PWSTR * ppsz)
  1280. {
  1281. TraceFileFunc(ttidGuiModeSetup);
  1282. Assert(hinf);
  1283. Assert(SRCINFO_PATH == InfoDesired ||
  1284. SRCINFO_TAGFILE == InfoDesired ||
  1285. SRCINFO_DESCRIPTION == InfoDesired);
  1286. Assert(ppsz);
  1287. HRESULT hr = S_OK;
  1288. ULONG cch;
  1289. // first get the size of the string required
  1290. //
  1291. if (SetupGetSourceInfo(hinf, SrcId, InfoDesired, NULL, 0, &cch))
  1292. {
  1293. // now get the required info
  1294. //
  1295. *ppsz = (PWSTR) MemAlloc(cch * sizeof (WCHAR));
  1296. if (*ppsz)
  1297. {
  1298. if (!SetupGetSourceInfo(hinf, SrcId, InfoDesired, *ppsz, cch, NULL))
  1299. {
  1300. MemFree(*ppsz);
  1301. hr = HRESULT_FROM_WIN32(GetLastError());
  1302. }
  1303. }
  1304. else
  1305. {
  1306. hr = E_OUTOFMEMORY;
  1307. }
  1308. }
  1309. else
  1310. {
  1311. hr = HRESULT_FROM_WIN32(GetLastError());
  1312. }
  1313. return hr;
  1314. }
  1315. //
  1316. // Function: UpgradeEtcServicesFile
  1317. //
  1318. // Purpose: Performs upgrade of %windir%\system32\drivers\etc\services file
  1319. //
  1320. // Parameters: pWizard [IN] - wizard info
  1321. //
  1322. // Returns: void
  1323. //
  1324. VOID
  1325. UpgradeEtcServicesFile(CWizard * pWizard)
  1326. {
  1327. TraceFileFunc(ttidGuiModeSetup);
  1328. // find etc\services file, and get size and other data
  1329. // compare size/date etc and decide if we should upgrade it.
  1330. HRESULT hr = S_OK;
  1331. DWORD status;
  1332. BOOL fShouldUpgradeIt = FALSE;
  1333. WCHAR szWindowsDir[MAX_PATH+1];
  1334. tstring strServices;
  1335. static const WCHAR c_szServicesFile[] = L"\\system32\\drivers\\etc\\services";
  1336. static const WCHAR c_szServicesDirSuffix[] = L"\\system32\\drivers\\etc";
  1337. static const DWORD c_dwNT4ServicesFileSize = 6007;
  1338. DWORD cNumCharsReturned = GetSystemWindowsDirectory(szWindowsDir, MAX_PATH);
  1339. if (cNumCharsReturned)
  1340. {
  1341. HANDLE hFile;
  1342. strServices = szWindowsDir;
  1343. strServices += c_szServicesFile;
  1344. // see if file exists
  1345. hFile = CreateFile(strServices.c_str(),
  1346. GENERIC_READ,
  1347. 0,
  1348. NULL,
  1349. OPEN_EXISTING,
  1350. 0,
  1351. NULL);
  1352. if (hFile)
  1353. {
  1354. // get attributes
  1355. DWORD dwSize = GetFileSize(hFile, NULL);
  1356. if (c_dwNT4ServicesFileSize == dwSize)
  1357. {
  1358. fShouldUpgradeIt = TRUE;
  1359. }
  1360. CloseHandle(hFile);
  1361. }
  1362. else
  1363. {
  1364. TraceTag(ttidWizard, "services files doesn't exist");
  1365. }
  1366. }
  1367. else
  1368. {
  1369. hr = HrFromLastWin32Error();
  1370. }
  1371. static const WCHAR c_szServices[] = L"services";
  1372. //
  1373. // copy over new services file if required
  1374. //
  1375. if (S_OK == hr && fShouldUpgradeIt)
  1376. {
  1377. // copy the file
  1378. //
  1379. HSPFILEQ q = NULL;
  1380. HINF hinf = NULL;
  1381. UINT SrcId;
  1382. PWSTR pszTagInfo = NULL;
  1383. PWSTR pszDescription = NULL;
  1384. tstring strServicesDir = szWindowsDir;
  1385. PVOID pCtx = NULL;
  1386. q = SetupOpenFileQueue();
  1387. if (!q)
  1388. {
  1389. TraceTag(ttidWizard, "SetupOpenFileQueue failed");
  1390. goto cleanup;
  1391. }
  1392. // we need the location of services._ (the compressed file)
  1393. // first open layout.inf
  1394. //
  1395. hinf = SetupOpenMasterInf();
  1396. if (!hinf)
  1397. {
  1398. TraceTag(ttidWizard, "Failed to open layout.inf");
  1399. goto cleanup;
  1400. }
  1401. // get size of needed buffer
  1402. //
  1403. if (!SetupGetSourceFileLocation(hinf, NULL, c_szServices, &SrcId, NULL, 0, NULL))
  1404. {
  1405. TraceTag(ttidWizard, "SetupGetSourceFileLocation failed.");
  1406. goto cleanup;
  1407. }
  1408. // get TagInfo
  1409. //
  1410. if (S_OK != HrSetupGetSourceInfo(hinf, SrcId, SRCINFO_TAGFILE, &pszTagInfo))
  1411. {
  1412. TraceTag(ttidWizard, "Failed to get TagInfo for services file.");
  1413. goto cleanup;
  1414. }
  1415. // get Description
  1416. //
  1417. if (S_OK != HrSetupGetSourceInfo(hinf, SrcId, SRCINFO_DESCRIPTION, &pszDescription))
  1418. {
  1419. TraceTag(ttidWizard, "Failed to get Description for services file.");
  1420. goto cleanup;
  1421. }
  1422. // now copy the file using this info
  1423. //
  1424. strServicesDir += c_szServicesDirSuffix;
  1425. if (!SetupQueueCopy(q,
  1426. pWizard->PSetupData()->LegacySourcePath,
  1427. NULL, // don't need this since LegacySourcePath covers it
  1428. c_szServices,
  1429. pszDescription,
  1430. pszTagInfo,
  1431. strServicesDir.c_str(),
  1432. NULL,
  1433. SP_COPY_REPLACEONLY))
  1434. {
  1435. TraceTag(ttidWizard, "SetupQueueCopy failed");
  1436. goto cleanup;
  1437. }
  1438. pCtx = SetupInitDefaultQueueCallbackEx(NULL,
  1439. static_cast<HWND>(INVALID_HANDLE_VALUE),
  1440. 0, 0, NULL);
  1441. if (!pCtx)
  1442. {
  1443. TraceTag(ttidWizard, "SetupInitDefaultQueueCallbackEx failed.");
  1444. goto cleanup;
  1445. }
  1446. if (!SetupCommitFileQueue(NULL, q, &SetupDefaultQueueCallback, pCtx))
  1447. {
  1448. TraceTag(ttidWizard, "SetupCommitFileQueue failed, "
  1449. "did not copy over new services file");
  1450. goto cleanup;
  1451. }
  1452. // success!
  1453. TraceTag(ttidWizard, "Copied over new services file");
  1454. cleanup:
  1455. if (pCtx)
  1456. {
  1457. SetupTermDefaultQueueCallback(pCtx);
  1458. }
  1459. MemFree(pszDescription);
  1460. MemFree(pszTagInfo);
  1461. if (hinf)
  1462. {
  1463. SetupCloseInfFile(hinf);
  1464. }
  1465. if (q)
  1466. {
  1467. SetupCloseFileQueue(q);
  1468. }
  1469. }
  1470. }
  1471. extern BOOL WINAPI FNetSetupApplySysPrep();
  1472. //
  1473. // Function: InstallUpgradeWorkThrd
  1474. //
  1475. // Purpose: Perform an network install or upgrade as appropriate
  1476. //
  1477. // Parameters: pitp [IN] - Thread data
  1478. //
  1479. // Returns: DWORD, Zero always
  1480. //
  1481. EXTERN_C
  1482. DWORD
  1483. InstallUpgradeWorkThrd (
  1484. InitThreadParam* pitp)
  1485. {
  1486. TraceFileFunc(ttidGuiModeSetup);
  1487. BOOL fUninitCOM = FALSE;
  1488. BOOL fLockSCM = FALSE;
  1489. HRESULT hr = S_OK;
  1490. UINT uMsg = PWM_EXIT;
  1491. CServiceManager scm;
  1492. TraceTag(ttidWizard, "Entering InstallUpgradeWorkThrd...");
  1493. Assert(!IsPostInstall(pitp->pWizard));
  1494. Assert(pitp->pWizard->PNetCfg());
  1495. #if DBG
  1496. if (FIsDebugFlagSet (dfidBreakOnStartOfUpgrade))
  1497. {
  1498. AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag "
  1499. "\"BreakOnStartOfUpgrade\" has been set. Set your breakpoints now.");
  1500. }
  1501. #endif // DBG
  1502. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 10);
  1503. // If this is in Mini-Setup mode, we will try to restore adapter specific parameters
  1504. // saved for SysPrep operation. This has to be done before the normal Answer-File processing.
  1505. // There is nothing we can do with any error here, so any error is ignored.
  1506. if ( (pitp->pWizard->PSetupData())->OperationFlags & SETUPOPER_MINISETUP )
  1507. {
  1508. FNetSetupApplySysPrep();
  1509. }
  1510. TraceTag(ttidWizard, "Waiting on Service Controller");
  1511. // Wait until service controller can be locked
  1512. //
  1513. if (SUCCEEDED(scm.HrOpen()))
  1514. {
  1515. while (!fLockSCM)
  1516. {
  1517. if (SUCCEEDED(scm.HrLock()))
  1518. {
  1519. fLockSCM = TRUE;
  1520. scm.Unlock();
  1521. break;
  1522. }
  1523. Sleep( 500 );
  1524. }
  1525. }
  1526. // Initialize COM on this thread
  1527. //
  1528. hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  1529. if (FAILED(hr))
  1530. {
  1531. TraceTag(ttidWizard, "Failed to initialize COM upgrade work thread");
  1532. goto Done;
  1533. }
  1534. else
  1535. {
  1536. // Remember to uninitialize COM on thread exit
  1537. fUninitCOM = TRUE;
  1538. }
  1539. #if DBG
  1540. RtlValidateProcessHeaps ();
  1541. #endif
  1542. if (!IsUpgrade(pitp->pWizard))
  1543. {
  1544. // Make sure the computer name is the same for both intended and active
  1545. TraceTag(ttidWizard, "Setting Active Computer Name");
  1546. (VOID)HrSetActiveComputerName(NULL);
  1547. }
  1548. // Synchronize the SAM database
  1549. //
  1550. SyncSAM(pitp->pWizard);
  1551. // Retrieve NetDevice info for later use
  1552. //
  1553. NetDevRetrieveInfo(pitp->pWizard);
  1554. // Do answer file processing if it is unattended mode.
  1555. //
  1556. if (IsUnattended(pitp->pWizard))
  1557. {
  1558. hr = HrInitForUnattendedNetSetup(
  1559. pitp->pWizard->PNetCfg(),
  1560. pitp->pWizard->PSetupData());
  1561. }
  1562. else if ( IsUpgrade(pitp->pWizard) )
  1563. {
  1564. // Attended upgrade is really a repair mode.
  1565. hr = HrInitForRepair();
  1566. }
  1567. // Join the default workgroup if necessary
  1568. //
  1569. if (!IsUpgrade(pitp->pWizard))
  1570. {
  1571. //
  1572. // In case it is minisetup of an SBS version and the machine is a DC,
  1573. // we don't need to join the default workgroup.
  1574. // Bug: 659976
  1575. //
  1576. if ((pitp->pWizard->OperationFlags() & SETUPOPER_MINISETUP) &&
  1577. IsSBS() && ISDC(ProductType(pitp->pWizard)))
  1578. {
  1579. TraceTag(ttidWizard, "Skipping joining Default Workgroup");
  1580. }
  1581. else
  1582. {
  1583. // Join the default workgroup only fresh install
  1584. TraceTag(ttidWizard, "Joining Default Workgroup");
  1585. JoinDefaultWorkgroup(pitp->pWizard, pitp->hwndDlg);
  1586. }
  1587. }
  1588. // Add unbound LAN adapters to the processing queue. For ATM this will
  1589. // have the side effect of creating virtual LAN adapters but not creating
  1590. // the connections associated with them
  1591. //
  1592. Assert(pitp->pWizard->FProcessLanPages());
  1593. (VOID)pitp->pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pitp->pWizard);
  1594. // Commit the changes caused by processing the unbound adapters
  1595. //
  1596. (VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
  1597. // Now for the ATM case create connections for the virtual LAN adapters
  1598. // and commit the changes
  1599. //
  1600. (VOID)pitp->pWizard->PAdapterQueue()->HrQueryUnboundAdapters(pitp->pWizard);
  1601. (VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
  1602. // Now process any problems in loading netcfg
  1603. //
  1604. if (NETSETUP_E_ANS_FILE_ERROR == hr)
  1605. {
  1606. // $REVIEW - LogError ?
  1607. // Disable unattended for networking
  1608. //
  1609. pitp->pWizard->DisableUnattended();
  1610. TraceTag(ttidWizard, "Error In answer file, installing default networking");
  1611. goto InstallDefNetworking;
  1612. }
  1613. else if (NETSETUP_E_NO_ANSWERFILE == hr)
  1614. {
  1615. // $REVIEW(tongl, 4/6/99): Raid #310599, if we are in mini-setup, then
  1616. // do attended install if no networking section is specified
  1617. HKEY hkeySetup = NULL;
  1618. HRESULT hrReg = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1619. c_szSystemSetupKey,
  1620. KEY_READ,
  1621. &hkeySetup);
  1622. if (SUCCEEDED(hrReg))
  1623. {
  1624. DWORD dw;
  1625. hrReg = HrRegQueryDword(hkeySetup, c_szMiniSetupInProgress, &dw);
  1626. RegCloseKey(hkeySetup);
  1627. }
  1628. if (SUCCEEDED(hrReg))
  1629. {
  1630. pitp->pWizard->DisableUnattended();
  1631. TraceTag(ttidWizard, "Mini-setup with no networking section, do attended install");
  1632. goto InstallDefNetworking;
  1633. }
  1634. else
  1635. {
  1636. // Per Raid 199750 - Install default networking when no
  1637. // networking is present.
  1638. //
  1639. TraceTag(ttidWizard, "No network answer file section, minimal network component setup");
  1640. InstallDefaultComponents(pitp->pWizard, EDC_DEFAULT, pitp->hwndDlg);
  1641. goto SkipNetworkComponentInstall;
  1642. }
  1643. }
  1644. else if (FAILED(hr))
  1645. {
  1646. // $REVIEW - logerror
  1647. TraceTag(ttidWizard, "Unexpected Error: 0x%08X",(DWORD)hr);
  1648. pitp->pWizard->SetExitNoReturn();
  1649. goto Done;
  1650. }
  1651. if (!IsUpgrade(pitp->pWizard) && !IsUnattended(pitp->pWizard))
  1652. { // Attended install
  1653. InstallDefNetworking:
  1654. StartSpooler();
  1655. if (IsFreshInstall(pitp->pWizard))
  1656. {
  1657. InstallDefaultComponents(pitp->pWizard, EDC_DEFAULT, pitp->hwndDlg);
  1658. }
  1659. }
  1660. else
  1661. { // Unattended install or upgrade
  1662. //
  1663. HRESULT hr2;
  1664. EPageDisplayMode i;
  1665. BOOL j;
  1666. Assert(NULL != pitp->pWizard->PNetCfg());
  1667. StartSpooler();
  1668. // Upgrade installed components
  1669. //
  1670. TraceTag(ttidWizard, "Processing installed adapters...");
  1671. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 15);
  1672. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1673. UAW_NetAdapters, &i, &j);
  1674. TraceHr(ttidWizard, FAL, hr2, FALSE, "Processing installed adapters failed.");
  1675. TraceTag(ttidWizard, "Upgrading Installed Protocols...");
  1676. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 25);
  1677. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1678. UAW_NetProtocols, &i, &j);
  1679. TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Protocols failed.");
  1680. TraceTag(ttidWizard, "Upgrading Installed Clients...");
  1681. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 40);
  1682. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1683. UAW_NetClients, &i, &j);
  1684. TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Clients failed.");
  1685. TraceTag(ttidWizard, "Upgrading Installed Services...");
  1686. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 55);
  1687. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1688. UAW_NetServices, &i, &j);
  1689. TraceHr(ttidWizard, FAL, hr2, FALSE, "Upgrading Installed Services failed.");
  1690. TraceTag(ttidWizard, "Restoring pre-upgrade bindings...");
  1691. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 70);
  1692. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1693. UAW_NetBindings, &i, &j);
  1694. TraceHr(ttidWizard, FAL, hr2, FALSE, "Restoring pre-upgrade bindings failed.");
  1695. TraceTag(ttidWizard, "Removing unsupported components...");
  1696. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, 85);
  1697. hr2 = HrDoUnattend(pitp->hwndDlg, pitp->pWizard->PNetCfg(),
  1698. UAW_RemoveNetComponents, &i, &j);
  1699. TraceHr(ttidWizard, FAL, hr2, FALSE, "Removing unsupported components failed.");
  1700. // If we are upgrading and have an answerfile, update lana
  1701. // configuration using the information in the file.
  1702. // Note: This must be done after all the components have been
  1703. // installed (Upgraded), so that all the bindings are present
  1704. // when we update hte configuration.
  1705. //
  1706. if (IsUpgrade (pitp->pWizard) && IsUnattended (pitp->pWizard) &&
  1707. (S_OK == pitp->pWizard->PNetCfg()->FindComponent (
  1708. c_szInfId_MS_NetBIOS, NULL)))
  1709. {
  1710. PWSTR pszAnswerFile;
  1711. PWSTR pszAnswerSection;
  1712. hr = HrGetAnswerFileParametersForComponent (c_szInfId_MS_NetBIOS,
  1713. &pszAnswerFile, &pszAnswerSection);
  1714. if (S_OK == hr)
  1715. {
  1716. NC_TRY
  1717. {
  1718. UpdateLanaConfigUsingAnswerfile (pszAnswerFile,
  1719. pszAnswerSection);
  1720. }
  1721. NC_CATCH_BAD_ALLOC
  1722. {
  1723. TraceTag (ttidWizard, "Possible delayload failure of "
  1724. "netcfgx dll while trying to update lana "
  1725. "information.");
  1726. }
  1727. CoTaskMemFree (pszAnswerFile);
  1728. CoTaskMemFree (pszAnswerSection);
  1729. }
  1730. // We can't let the error stop us.
  1731. hr = S_OK;
  1732. }
  1733. // Install networking, if no networking is present. "no networking"
  1734. // means no visible LAN-enabled protocol installed.
  1735. //
  1736. // First try to install default components as opposed to
  1737. // mandatory components because TCP/IP is both mandatory
  1738. // and default. So, if we install mandatory first then,
  1739. // default components will never be installed as TCP/IP is
  1740. // a visible LAN-enabled protocol.
  1741. // Raid bug 337827
  1742. InstallDefaultComponentsIfNeeded(pitp->pWizard);
  1743. // Install mandatory components.
  1744. InstallDefaultComponents(pitp->pWizard, EDC_MANDATORY, pitp->hwndDlg);
  1745. // Special Case. Need an extra OBOUser ref-count for File and Print
  1746. // when upgrading from NT3.51 or NT4 and GSNW is installed. This is
  1747. // because ref-counting didn't exist pre-NT5
  1748. //
  1749. OBOUserAddRefSpecialCase(pitp->pWizard);
  1750. #if DBG
  1751. if (FIsDebugFlagSet (dfidBreakOnEndOfUpgrade))
  1752. {
  1753. AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag "
  1754. "\"BreakOnEndOfUpgrade\" has been set. Set your breakpoints now.");
  1755. }
  1756. #endif // DBG
  1757. }
  1758. // Convert any components which were OC and are now regular networking components
  1759. //
  1760. if (IsUpgrade(pitp->pWizard))
  1761. {
  1762. FixupOldOcComponents(pitp->pWizard);
  1763. }
  1764. //
  1765. // Upgrade system32\drivers\etc\services file if necessary
  1766. //
  1767. if (IsUpgrade(pitp->pWizard))
  1768. {
  1769. UpgradeEtcServicesFile(pitp->pWizard);
  1770. }
  1771. SkipNetworkComponentInstall:
  1772. OnUpgradeUpdateProgressCap(pitp->hwndDlg, pitp->pWizard, c_nMaxProgressRange);
  1773. // Commit any changes
  1774. //
  1775. (VOID)HrCommitINetCfgChanges(GetParent(pitp->hwndDlg), pitp->pWizard);
  1776. uMsg = PWM_PROCEED;
  1777. Done:
  1778. // Shutdown the progress timer if it's not already stopped
  1779. //
  1780. {
  1781. LPARAM lParam = pitp->pWizard->GetPageData(IDD_Upgrade);
  1782. Assert(lParam);
  1783. UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
  1784. ::KillTimer(pitp->hwndDlg, c_uiUpgradeRefreshID);
  1785. // Set the progress indicator to its full position
  1786. //
  1787. HWND hwndProgress = GetDlgItem(pitp->hwndDlg, IDC_UPGRADE_PROGRESS);
  1788. SendMessage(hwndProgress, PBM_SETPOS,
  1789. c_nMaxProgressRange, 0);
  1790. UpdateWindow(hwndProgress);
  1791. }
  1792. // Uninitialize COM for this thread
  1793. //
  1794. if (fUninitCOM)
  1795. {
  1796. CoUninitialize();
  1797. }
  1798. EnsureUniqueComputerName(pitp->hwndDlg, IsUnattended(pitp->pWizard));
  1799. ValidateNetBiosName();
  1800. PostMessage(pitp->hwndDlg, uMsg, (WPARAM)0, (LPARAM)0);
  1801. delete pitp;
  1802. #if DBG
  1803. RtlValidateProcessHeaps ();
  1804. #endif
  1805. TraceTag(ttidWizard, "Leaving InstallUpgradeWorkThrd...");
  1806. return 0;
  1807. }
  1808. //
  1809. // Function: OnUpgradePageActivate
  1810. //
  1811. // Purpose: Handle the PSN_SETACTIVE notification by either: Creating a
  1812. // thread to process install/upgrade requirements or to just
  1813. // deny activation of the page.
  1814. //
  1815. // Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
  1816. //
  1817. // Returns: BOOL, TRUE on success
  1818. //
  1819. BOOL OnUpgradePageActivate( HWND hwndDlg )
  1820. {
  1821. TraceFileFunc(ttidGuiModeSetup);
  1822. // Retrieve the CWizard instance from the dialog
  1823. CWizard * pWizard =
  1824. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  1825. Assert(NULL != pWizard);
  1826. // Retrieve the page data stashed within the wizard for this page
  1827. LPARAM lParam = pWizard->GetPageData(IDD_Upgrade);
  1828. Assert(lParam);
  1829. UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
  1830. if(!pData)
  1831. {
  1832. return false;
  1833. }
  1834. // Based on the page data decide whether focus is acceptable
  1835. if (pData->fProcessed)
  1836. {
  1837. // Accept focus
  1838. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0);
  1839. PAGEDIRECTION PageDir = pWizard->GetPageDirection(IDD_Upgrade);
  1840. if (NWPD_FORWARD == PageDir)
  1841. {
  1842. if ( IsComputerNameChanged() )
  1843. {
  1844. HrSetActiveComputerName (NULL);
  1845. EnsureUniqueComputerName(hwndDlg, IsUnattended(pWizard));
  1846. }
  1847. // Get to this page when the user navigates back and forth
  1848. // and we already processed InstallUpgradeWorkThrd
  1849. if (g_pSetupWizard != NULL)
  1850. {
  1851. g_pSetupWizard->PSetupData()->ShowHideWizardPage(TRUE);
  1852. }
  1853. pWizard->SetPageDirection(IDD_Upgrade, NWPD_BACKWARD);
  1854. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
  1855. }
  1856. else
  1857. {
  1858. // if there are any adapters previous to the current in the queue
  1859. // jump to them before accepting focus here
  1860. if (!OnProcessPrevAdapterPagePrev(hwndDlg, 0))
  1861. {
  1862. pWizard->SetPageDirection(IDD_Upgrade, NWPD_FORWARD);
  1863. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
  1864. }
  1865. }
  1866. }
  1867. else
  1868. {
  1869. HANDLE hthrd;
  1870. DWORD dwThreadId = 0;
  1871. PropSheet_SetWizButtons( GetParent( hwndDlg ), 0);
  1872. TraceTag(ttidWizard,"Upgrade/Install Page commencing");
  1873. // Install the Asyncmac software-enumerated device.
  1874. // Important to do this before the INetCfg lock is obtained, because
  1875. // the installation of this device causes or class installer to be
  1876. // invoked which needs to get its own lock to process the installation.
  1877. //
  1878. static const GUID DEVICE_GUID_ASYNCMAC =
  1879. {0xeeab7790,0xc514,0x11d1,{0xb4,0x2b,0x00,0x80,0x5f,0xc1,0x27,0x0e}};
  1880. (VOID) HrInstallSoftwareDeviceOnInterface (
  1881. &DEVICE_GUID_ASYNCMAC,
  1882. &GUID_NDIS_LAN_CLASS,
  1883. L"asyncmac",
  1884. TRUE, // force installation since this happens during GUI mode.
  1885. L"netrasa.inf",
  1886. hwndDlg);
  1887. // Not processed yet, spin up the thread to do the Install/Upgrade
  1888. pData->fProcessed = TRUE;
  1889. ::SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0);
  1890. InitThreadParam * pitp = new InitThreadParam;
  1891. HRESULT hr = S_OK;
  1892. if(pitp)
  1893. {
  1894. pitp->hwndDlg = hwndDlg;
  1895. pitp->pWizard = pWizard;
  1896. TraceTag(ttidWizard, "Creating INetCfg Instance");
  1897. hr = HrInitAndGetINetCfg(pitp->pWizard);
  1898. }
  1899. else
  1900. {
  1901. hr = E_OUTOFMEMORY;
  1902. }
  1903. if (SUCCEEDED(hr))
  1904. {
  1905. // We are installing and only show progress, hide the page
  1906. if (g_pSetupWizard != NULL)
  1907. {
  1908. g_pSetupWizard->PSetupData()->ShowHideWizardPage(FALSE);
  1909. }
  1910. // Create the work thread
  1911. hthrd = CreateThread( NULL, STACK_SIZE_TINY,
  1912. (LPTHREAD_START_ROUTINE)InstallUpgradeWorkThrd,
  1913. (LPVOID)pitp, 0, &dwThreadId );
  1914. if (NULL != hthrd)
  1915. {
  1916. CloseHandle( hthrd );
  1917. }
  1918. else
  1919. {
  1920. hr = HRESULT_FROM_WIN32(GetLastError());
  1921. Assert(hr);
  1922. // Kill the timer we created since the thread won't be around
  1923. // to kill it for us.
  1924. //
  1925. ::KillTimer(hwndDlg, c_uiUpgradeRefreshID);
  1926. }
  1927. }
  1928. if (FAILED(hr) || (NULL == hthrd))
  1929. {
  1930. // Failed to create the required netsetup thread
  1931. delete pitp;
  1932. AssertSz(0,"Unable to create netsetup thread.");
  1933. TraceHr(ttidWizard, FAL, hr, FALSE, "OnUpgradePageActivate - Create thread failed");
  1934. pWizard->SetExitNoReturn();
  1935. PostMessage(hwndDlg, PWM_EXIT, (WPARAM)0, (LPARAM)0);
  1936. }
  1937. }
  1938. return( TRUE );
  1939. }
  1940. //
  1941. // Function: OnUpgradePageExit
  1942. //
  1943. // Purpose: Handle the PWN_EXIT notification
  1944. //
  1945. // Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
  1946. //
  1947. // Returns: BOOL, TRUE if the action was processed internally
  1948. //
  1949. BOOL OnUpgradePageExit( HWND hwndDlg )
  1950. {
  1951. TraceFileFunc(ttidGuiModeSetup);
  1952. // Retrieve the CWizard instance from the dialog
  1953. CWizard * pWizard =
  1954. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  1955. Assert(NULL != pWizard);
  1956. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
  1957. // goto the exit page
  1958. HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_Exit);
  1959. PostMessage(GetParent(hwndDlg), PSM_SETCURSEL, 0,
  1960. (LPARAM)(HPROPSHEETPAGE)hPage);
  1961. return (TRUE);
  1962. }
  1963. //
  1964. // Function: OnUpgradePageProceed
  1965. //
  1966. // Purpose: Handle the PWN_PROCEED notification
  1967. //
  1968. // Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
  1969. //
  1970. // Returns: BOOL, TRUE if the action was processed internally
  1971. //
  1972. BOOL OnUpgradePageProceed( HWND hwndDlg )
  1973. {
  1974. TraceFileFunc(ttidGuiModeSetup);
  1975. int nIdx;
  1976. int rgIdcShow[] = { BTN_UPGRADE_TYPICAL, BTN_UPGRADE_CUSTOM,
  1977. TXT_UPGRADE_TYPICAL_1, TXT_UPGRADE_CUSTOM_1,
  1978. TXT_UPGRADE_INSTRUCTIONS};
  1979. int rgIdcShowWorkstation[] = { BTN_UPGRADE_TYPICAL, BTN_UPGRADE_CUSTOM,
  1980. TXT_UPGRADE_TYPICAL_1_WS, TXT_UPGRADE_CUSTOM_1,
  1981. TXT_UPGRADE_INSTRUCTIONS};
  1982. int rgIdcHide[] = {TXT_UPGRADE_WAIT, IDC_UPGRADE_PROGRESS};
  1983. PRODUCT_FLAVOR pf;
  1984. GetProductFlavor(NULL, &pf);
  1985. // Retrieve the CWizard instance from the dialog
  1986. CWizard * pWizard =
  1987. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  1988. Assert(NULL != pWizard);
  1989. // Expose the typical/custom controls on the upgrade page
  1990. // and hide the "working" controls unless there are no adapters
  1991. //
  1992. if (pWizard->PAdapterQueue()->FAdaptersInstalled())
  1993. {
  1994. for (nIdx=0; nIdx < celems(rgIdcHide); nIdx++)
  1995. ShowWindow(GetDlgItem(hwndDlg, rgIdcHide[nIdx]), SW_HIDE);
  1996. if (PF_WORKSTATION == pf)
  1997. {
  1998. for (nIdx=0; nIdx < celems(rgIdcShowWorkstation); nIdx++)
  1999. ShowWindow(GetDlgItem(hwndDlg, rgIdcShowWorkstation[nIdx]), SW_SHOW);
  2000. }
  2001. else
  2002. {
  2003. for (nIdx=0; nIdx < celems(rgIdcShow); nIdx++)
  2004. ShowWindow(GetDlgItem(hwndDlg, rgIdcShow[nIdx]), SW_SHOW);
  2005. }
  2006. }
  2007. ::SetFocus(GetDlgItem(hwndDlg, BTN_UPGRADE_TYPICAL));
  2008. PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT | PSWIZB_BACK);
  2009. // If upgrading, or we're in one of the interesting unattended mode,
  2010. // or there are no adapters or this is sbs version then automatically
  2011. // advance the UI in "typical" mode. In case of sbs, join page also
  2012. // advances automatically.
  2013. //
  2014. // SBS requires a static IP address for the LAN network card and the
  2015. // networking configuration is done in SBS setup.
  2016. if (IsUpgrade(pWizard) ||
  2017. !pWizard->PAdapterQueue()->FAdaptersInstalled() ||
  2018. (IsUnattended(pWizard) &&
  2019. ((UM_FULLUNATTENDED == pWizard->GetUnattendedMode()) ||
  2020. (UM_DEFAULTHIDE == pWizard->GetUnattendedMode()) ||
  2021. (UM_READONLY == pWizard->GetUnattendedMode()))) ||
  2022. IsSBS())
  2023. {
  2024. PostMessage(GetParent(hwndDlg), PSM_PRESSBUTTON, (WPARAM)(PSBTN_NEXT), 0);
  2025. }
  2026. else
  2027. {
  2028. // make sure the page is visible.
  2029. if (g_pSetupWizard != NULL)
  2030. {
  2031. g_pSetupWizard->PSetupData()->ShowHideWizardPage(TRUE);
  2032. g_pSetupWizard->PSetupData()->BillBoardSetProgressText(TEXT(""));
  2033. }
  2034. }
  2035. return (TRUE);
  2036. }
  2037. //
  2038. // Function: OnUpgradePageNext
  2039. //
  2040. // Purpose: Handle the PWN_WIZNEXT notification
  2041. //
  2042. // Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
  2043. //
  2044. // Returns: BOOL, TRUE if the action was processed internally
  2045. //
  2046. BOOL OnUpgradePageNext(HWND hwndDlg)
  2047. {
  2048. TraceFileFunc(ttidGuiModeSetup);
  2049. // Retrieve the CWizard instance from the dialog
  2050. CWizard * pWizard =
  2051. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  2052. Assert(NULL != pWizard);
  2053. pWizard->SetPageDirection(IDD_Upgrade, NWPD_BACKWARD);
  2054. // Based on UI selection, hide or unhide new adapters
  2055. //
  2056. if (IsDlgButtonChecked(hwndDlg, BTN_UPGRADE_TYPICAL))
  2057. {
  2058. pWizard->PAdapterQueue()->HideAllAdapters();
  2059. }
  2060. else
  2061. {
  2062. pWizard->PAdapterQueue()->UnhideNewAdapters();
  2063. }
  2064. return OnProcessNextAdapterPageNext(hwndDlg, FALSE);
  2065. }
  2066. //
  2067. // Function: OnUpgradePagePrev
  2068. //
  2069. // Purpose: Handle the PWN_WIZBACK notification
  2070. //
  2071. // Parameters: hwndDlg [IN] - Handle to the upgrade child dialog
  2072. //
  2073. // Returns: BOOL, TRUE if the action was processed internally
  2074. //
  2075. BOOL OnUpgradePagePrev(HWND hwndDlg)
  2076. {
  2077. TraceFileFunc(ttidGuiModeSetup);
  2078. // Retrieve the CWizard instance from the dialog
  2079. CWizard * pWizard =
  2080. reinterpret_cast<CWizard *>(::GetWindowLongPtr(hwndDlg, DWLP_USER));
  2081. Assert(NULL != pWizard);
  2082. pWizard->SetPageDirection(IDD_Upgrade, NWPD_FORWARD);
  2083. return FALSE;
  2084. }
  2085. //
  2086. // Function: OnUpgradeInitDialog
  2087. //
  2088. // Purpose: Handle the InitDialog message for the upgrade page
  2089. //
  2090. // Parameters: hwndDlg [IN] - Handle to the upgrade page window
  2091. // lParam [IN] - LPARAM value from the WM_INITDIALOG message
  2092. //
  2093. // Returns: FALSE (let the dialog proc set focus)
  2094. //
  2095. BOOL OnUpgradeInitDialog(HWND hwndDlg, LPARAM lParam)
  2096. {
  2097. TraceFileFunc(ttidGuiModeSetup);
  2098. // Initialize our pointers to property sheet info.
  2099. //
  2100. PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam;
  2101. Assert(psp->lParam);
  2102. ::SetWindowLongPtr(hwndDlg, DWLP_USER, psp->lParam);
  2103. // Cast the property sheet lParam data into the wizard which it is
  2104. //
  2105. CWizard * pWizard = reinterpret_cast<CWizard *>(psp->lParam);
  2106. Assert(NULL != pWizard);
  2107. // Get the private data we stashed away for this page
  2108. //
  2109. lParam = pWizard->GetPageData(IDD_Upgrade);
  2110. Assert(lParam);
  2111. UpgradeData * pData = reinterpret_cast<UpgradeData *>(lParam);
  2112. // Start the progress
  2113. //
  2114. HWND hwndProgress = GetDlgItem(hwndDlg, IDC_UPGRADE_PROGRESS);
  2115. // Subclass the progress and make it also call the BB callback.
  2116. // Only do this if we are called from GUI mode setup.
  2117. if (g_pSetupWizard != NULL)
  2118. {
  2119. PCWSTR str = SzLoadIds(IDS_BB_NETWORK);
  2120. OldProgressProc = (WNDPROC)SetWindowLongPtr(hwndProgress,GWLP_WNDPROC,(LONG_PTR)NewProgessProc);
  2121. // Set the string for the progress on the billboard.
  2122. g_pSetupWizard->PSetupData()->BillBoardSetProgressText(str);
  2123. }
  2124. SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0,c_nMaxProgressRange));
  2125. SendMessage(hwndProgress, PBM_SETPOS, 1, 0);
  2126. SetTimer(hwndDlg, c_uiUpgradeRefreshID, c_uiUpgradeRefreshRate, NULL);
  2127. // Disable prev/next until initial work is complete
  2128. //
  2129. PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
  2130. // Default the mode buttons to typical
  2131. //
  2132. CheckRadioButton(hwndDlg, BTN_UPGRADE_TYPICAL,
  2133. BTN_UPGRADE_CUSTOM, BTN_UPGRADE_TYPICAL);
  2134. // Create the bold font and apply to the mode buttons
  2135. //
  2136. SetupFonts(hwndDlg, &pData->hBoldFont, FALSE);
  2137. if (pData->hBoldFont)
  2138. {
  2139. SetWindowFont(GetDlgItem(hwndDlg, BTN_UPGRADE_TYPICAL),
  2140. pData->hBoldFont, FALSE);
  2141. SetWindowFont(GetDlgItem(hwndDlg, BTN_UPGRADE_CUSTOM),
  2142. pData->hBoldFont, FALSE);
  2143. }
  2144. HICON hIcon = LoadIcon(_Module.GetResourceInstance(),
  2145. MAKEINTRESOURCE(IDI_LB_GEN_M_16));
  2146. if (hIcon)
  2147. {
  2148. SendMessage(GetDlgItem(hwndDlg, TXT_UPGRADE_ICON), STM_SETICON,
  2149. (WPARAM)hIcon, 0L);
  2150. }
  2151. return FALSE;
  2152. }
  2153. //
  2154. // Function: dlgprocUpgrade
  2155. //
  2156. // Purpose: Dialog Procedure for the Upgrade wizard page
  2157. //
  2158. // Parameters: standard dlgproc parameters
  2159. //
  2160. // Returns: BOOL
  2161. //
  2162. INT_PTR CALLBACK dlgprocUpgrade(HWND hwndDlg, UINT uMsg,
  2163. WPARAM wParam, LPARAM lParam)
  2164. {
  2165. TraceFileFunc(ttidGuiModeSetup);
  2166. BOOL frt = FALSE;
  2167. switch (uMsg)
  2168. {
  2169. case PWM_EXIT:
  2170. frt = OnUpgradePageExit(hwndDlg);
  2171. break;
  2172. case PWM_PROCEED:
  2173. frt = OnUpgradePageProceed(hwndDlg);
  2174. break;
  2175. case WM_INITDIALOG:
  2176. frt = OnUpgradeInitDialog(hwndDlg, lParam);
  2177. break;
  2178. case WM_TIMER:
  2179. OnUpgradeUpdateProgress(hwndDlg);
  2180. break;
  2181. case WM_NOTIFY:
  2182. {
  2183. LPNMHDR pnmh = (LPNMHDR)lParam;
  2184. switch (pnmh->code)
  2185. {
  2186. // propsheet notification
  2187. case PSN_HELP:
  2188. break;
  2189. case PSN_SETACTIVE:
  2190. frt = OnUpgradePageActivate( hwndDlg );
  2191. break;
  2192. case PSN_APPLY:
  2193. break;
  2194. case PSN_KILLACTIVE:
  2195. break;
  2196. case PSN_RESET:
  2197. break;
  2198. case PSN_WIZBACK:
  2199. frt = OnUpgradePagePrev(hwndDlg);
  2200. break;
  2201. case PSN_WIZFINISH:
  2202. break;
  2203. case PSN_WIZNEXT:
  2204. frt = OnUpgradePageNext(hwndDlg);
  2205. break;
  2206. default:
  2207. break;
  2208. }
  2209. }
  2210. break;
  2211. default:
  2212. break;
  2213. }
  2214. return( frt );
  2215. }
  2216. //
  2217. // Function: UpgradePageCleanup
  2218. //
  2219. // Purpose: As a callback function to allow any page allocated memory
  2220. // to be cleaned up, after the page will no longer be accessed.
  2221. //
  2222. // Parameters: pWizard [IN] - The wizard against which the page called
  2223. // register page
  2224. // lParam [IN] - The lParam supplied in the RegisterPage call
  2225. //
  2226. // Returns: nothing
  2227. //
  2228. VOID UpgradePageCleanup(CWizard *pWizard, LPARAM lParam)
  2229. {
  2230. TraceFileFunc(ttidGuiModeSetup);
  2231. UpgradeData * pData;
  2232. pData = reinterpret_cast<UpgradeData*>(lParam);
  2233. if (NULL != pData)
  2234. {
  2235. DeleteObject(pData->hBoldFont);
  2236. MemFree(pData);
  2237. }
  2238. }
  2239. //
  2240. // Function: CreateUpgradePage
  2241. //
  2242. // Purpose: To determine if the upgrade page needs to be shown, and to
  2243. // to create the page if requested. Note the upgrade page is
  2244. // responsible for initial installs also.
  2245. //
  2246. // Parameters: pWizard [IN] - Ptr to a Wizard instance
  2247. // pData [IN] - Context data to describe the world in
  2248. // which the Wizard will be run
  2249. // fCountOnly [IN] - If True, only the maximum number of
  2250. // pages this routine will create need
  2251. // be determined.
  2252. // pnPages [IN] - Increment by the number of pages
  2253. // to create/created
  2254. //
  2255. // Returns: HRESULT, S_OK on success
  2256. //
  2257. HRESULT HrCreateUpgradePage(CWizard *pWizard, PINTERNAL_SETUP_DATA pData,
  2258. BOOL fCountOnly, UINT *pnPages)
  2259. {
  2260. TraceFileFunc(ttidGuiModeSetup);
  2261. HRESULT hr = S_OK;
  2262. // Batch Mode or for fresh install
  2263. if (!IsPostInstall(pWizard))
  2264. {
  2265. (*pnPages)++;
  2266. // If not only counting, create and register the page
  2267. if (!fCountOnly)
  2268. {
  2269. HPROPSHEETPAGE hpsp;
  2270. PROPSHEETPAGE psp;
  2271. TraceTag(ttidWizard, "Creating Upgrade Page");
  2272. hr = E_OUTOFMEMORY;
  2273. UpgradeData * pData = reinterpret_cast<UpgradeData*>
  2274. (MemAlloc(sizeof(UpgradeData)));
  2275. if (NULL == pData)
  2276. {
  2277. goto Error;
  2278. }
  2279. pData->fProcessed = FALSE;
  2280. pData->hBoldFont = NULL;
  2281. pData->nCurrentCap = 0;
  2282. psp.dwSize = sizeof( PROPSHEETPAGE );
  2283. psp.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
  2284. psp.hInstance = _Module.GetResourceInstance();
  2285. psp.pszTemplate = MAKEINTRESOURCE( IDD_Upgrade );
  2286. psp.hIcon = NULL;
  2287. psp.pfnDlgProc = dlgprocUpgrade;
  2288. psp.lParam = reinterpret_cast<LPARAM>(pWizard);
  2289. psp.pszHeaderTitle = SzLoadIds(IDS_T_Upgrade);
  2290. psp.pszHeaderSubTitle = SzLoadIds(IDS_ST_Upgrade);
  2291. hpsp = CreatePropertySheetPage( &psp );
  2292. if (hpsp)
  2293. {
  2294. pWizard->RegisterPage(IDD_Upgrade, hpsp,
  2295. UpgradePageCleanup,
  2296. reinterpret_cast<LPARAM>(pData));
  2297. hr = S_OK;
  2298. }
  2299. else
  2300. {
  2301. MemFree(pData);
  2302. }
  2303. }
  2304. }
  2305. Error:
  2306. TraceHr(ttidWizard, FAL, hr, FALSE, "HrCreateUpgradePage");
  2307. return hr;
  2308. }
  2309. //
  2310. // Function: AppendUpgradePage
  2311. //
  2312. // Purpose: Add the Upgrade page, if it was created, to the set of pages
  2313. // that will be displayed.
  2314. //
  2315. // Parameters: pahpsp [IN,OUT] - Array of pages to add our page to
  2316. // pcPages [IN,OUT] - Count of pages in pahpsp
  2317. //
  2318. // Returns: Nothing
  2319. //
  2320. VOID AppendUpgradePage(CWizard *pWizard, HPROPSHEETPAGE* pahpsp, UINT *pcPages)
  2321. {
  2322. TraceFileFunc(ttidGuiModeSetup);
  2323. if (!IsPostInstall(pWizard))
  2324. {
  2325. HPROPSHEETPAGE hPage = pWizard->GetPageHandle(IDD_Upgrade);
  2326. Assert(hPage);
  2327. pahpsp[*pcPages] = hPage;
  2328. (*pcPages)++;
  2329. }
  2330. }