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.

1768 lines
53 KiB

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997 Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6. strtlst.c
  7. Abstract:
  8. Implements the controls in the "Startup" group on the
  9. Startup/Recovery dialog of the System Control Panel Applet
  10. Revision History:
  11. 23-Jan-1996 JonPa
  12. ported from NT3.51's system.cpl
  13. --*/
  14. #include "sysdm.h"
  15. ///////////////////////////////////////////////////////////////
  16. // Persistant vars
  17. ///////////////////////////////////////////////////////////////
  18. static TCHAR *pszBoot = NULL;
  19. static int nOriginalSelection;
  20. static int nOriginalTimeout;
  21. HANDLE hBootStatusData = NULL;
  22. /*
  23. * These functions in SETUPDLL.DLL are ANSI only!!!!
  24. *
  25. * Therefore any functions working with this DLL MUST remain ANSI only.
  26. * The functions are GetRGSZEnvVar and UpdateNVRAM.
  27. * The structure CPEnvBuf MUST also remain ANSI only.
  28. */
  29. typedef int (WINAPI *GETNVRAMPROC)(CHAR **, USHORT, CHAR *, USHORT);
  30. typedef int (WINAPI *WRITENVRAMPROC)(DWORD, PSZ *, PSZ *);
  31. #ifdef _X86_
  32. TCHAR szBootIni[] = TEXT( "c:\\boot.ini" );
  33. TCHAR szBootLdr[] = TEXT( "boot loader" );
  34. TCHAR szFlexBoot[] = TEXT( "flexboot" );
  35. TCHAR szMultiBoot[] = TEXT( "multiboot" );
  36. TCHAR szTimeout[] = TEXT( "timeout" );
  37. TCHAR szDefault[] = TEXT( "default" );
  38. TCHAR szOS[] = TEXT( "operating systems" );
  39. #define BUFZ 4096
  40. //
  41. // For NEC PC98. Following definition comes from user\inc\kbd.h.
  42. // The value must be the same as value in kbd.h.
  43. //
  44. #define NLSKBD_OEM_NEC 0x0D
  45. TCHAR x86DetermineSystemPartition( IN HWND hdlg );
  46. #endif
  47. #if defined(EFI_NVRAM_ENABLED)
  48. //
  49. // IsEfi() is always true on IA64 machines. Therefore this determination can
  50. // be made at compile time. When x86 EFI machines are supported, the check
  51. // will need to be made at run time on x86.
  52. //
  53. #if defined(_IA64_)
  54. #define IsEfi() TRUE
  55. #else
  56. BOOLEAN
  57. IsEfi(
  58. VOID
  59. );
  60. #endif
  61. typedef struct _MY_BOOT_ENTRY {
  62. LIST_ENTRY ListEntry;
  63. PWSTR FriendlyName;
  64. int Index;
  65. LOGICAL Show;
  66. LOGICAL Ordered;
  67. PBOOT_ENTRY NtBootEntry;
  68. } MY_BOOT_ENTRY, *PMY_BOOT_ENTRY;
  69. LIST_ENTRY BootEntries;
  70. PBOOT_ENTRY_LIST BootEntryList = NULL;
  71. PBOOT_OPTIONS BootOptions;
  72. #define ADD_OFFSET(_p,_o) (PVOID)((PUCHAR)(_p) + (_p)->_o)
  73. #endif // defined(EFI_NVRAM_ENABLED)
  74. // v-pshuan: since the Silicon Graphics visual workstations boot
  75. // ARC style, this code needs to be compiled for _X86_ as well.
  76. static HMODULE hmodSetupDll; // hmod for setup - has api we need
  77. static GETNVRAMPROC fpGetNVRAMvar; // address of function for getting nvram vars
  78. BOOL fCanUpdateNVRAM;
  79. #define MAX_BOOT_ENTRIES 10
  80. typedef struct tagEnvBuf
  81. {
  82. int cEntries;
  83. CHAR * pszVars[MAX_BOOT_ENTRIES];
  84. // v-pshuan: this implies a maximum of 10 boot entries are supported
  85. // although no error checking is performed in the existing parsing code
  86. // to make sure there aren't more than 10 boot entries.
  87. } CPEnvBuf;
  88. //*************************************************************
  89. //
  90. // StringToIntA
  91. //
  92. // Purpose: atoi
  93. //
  94. // Parameters: LPSTR sz - pointer of string to convert
  95. //
  96. // Return: void
  97. //
  98. // WARNING: Unlike StringToInt, this one does not skip leading
  99. // white space
  100. //
  101. //*************************************************************
  102. int StringToIntA( LPSTR sz ) {
  103. int i = 0;
  104. while( IsDigit( *sz ) ) {
  105. i = i * 10 + (*sz - '0');
  106. sz++;
  107. }
  108. return i;
  109. }
  110. ////////////////////////////////////////////////////////////////////////////
  111. // CP_MAX_ENV assumes entire env. var. value < maxpath +
  112. // add 20 for various quotes
  113. // and 10 more for commas (see list description below)
  114. ////////////////////////////////////////////////////////////////////////////
  115. #define CP_MAX_ENV (MAX_PATH + 30)
  116. CPEnvBuf CPEBOSLoadIdentifier;
  117. BOOL fAutoLoad;
  118. //////////////////////////////////////////////////////////////////////
  119. //
  120. // Identify whether we are running on an x86 system which nevertheless
  121. // boots using the ARC path (no c:\boot.ini)
  122. //
  123. //////////////////////////////////////////////////////////////////////
  124. BOOL Is_ARCx86(void)
  125. {
  126. TCHAR identifier[256];
  127. ULONG identifierSize = sizeof(identifier);
  128. HKEY hSystemKey = NULL;
  129. BOOL rval = FALSE;
  130. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  131. TEXT("HARDWARE\\DESCRIPTION\\System"),
  132. 0,
  133. KEY_QUERY_VALUE,
  134. &hSystemKey) == ERROR_SUCCESS) {
  135. if ((SHRegGetValue(hSystemKey,
  136. NULL,
  137. TEXT("Identifier"),
  138. SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND,
  139. NULL,
  140. (LPBYTE) identifier,
  141. &identifierSize) == ERROR_SUCCESS) &&
  142. (StrStr(identifier, TEXT("ARCx86")) != NULL))
  143. {
  144. rval = TRUE;
  145. }
  146. RegCloseKey(hSystemKey);
  147. }
  148. return rval;
  149. }
  150. ////////////////////////////////////////////////////////////////////////////
  151. //
  152. // This routine will query the ARC NVRAM for an option passed
  153. // in szName and fill in the argv style pointer passed in.
  154. //
  155. ////////////////////////////////////////////////////////////////////////////
  156. BOOL GetRGSZEnvVar(CPEnvBuf * pEnvBuf, PCHAR pszName)
  157. {
  158. CHAR *pszCur, *p;
  159. int cb, i;
  160. CHAR *rgtmp[1];
  161. CHAR rgchOut[CP_MAX_ENV*MAX_BOOT_ENTRIES];
  162. // GetNVRAMVar takes an argv[] style paramater as input, so crock
  163. // one up.
  164. rgtmp[0] = pszName;
  165. // GetNVRAMVar returns a 'list' of the form
  166. // open-curly"string1","string2","string3"close-curly
  167. //
  168. // an empty environment string will be 5 bytes:
  169. // open-curly""close-curly[null-terminator]
  170. cb = fpGetNVRAMvar (rgtmp, (USHORT)1,
  171. rgchOut, (USHORT) CP_MAX_ENV*MAX_BOOT_ENTRIES);
  172. pEnvBuf->cEntries = 0;
  173. // if cb was equal to 5, the string was empty (see above comment)
  174. if (cb > 5)
  175. {
  176. // break the string up into array of separate strings that
  177. // can be put into a listbox.
  178. pszCur = rgchOut;
  179. // skip first open-curly brace
  180. pszCur++;
  181. // counter for array of strings
  182. i = 0;
  183. while (*pszCur != '}')
  184. {
  185. p = pEnvBuf->pszVars[i] = LocalAlloc (LPTR, MAX_PATH);
  186. // PREFIX change to prevent a potential NULL dereference
  187. if (!p)
  188. {
  189. pEnvBuf->cEntries = i;
  190. return FALSE;
  191. }
  192. // skip first quote
  193. pszCur++;
  194. while (*pszCur != '"')
  195. *p++ = *pszCur++;
  196. // skip the close quote
  197. pszCur++;
  198. // null terminate destination
  199. *p = '\0';
  200. // skip the comma if not at end of string
  201. if (*pszCur == ',')
  202. {
  203. pszCur++;
  204. // and go to next string
  205. }
  206. i++;
  207. }
  208. pEnvBuf->cEntries = i;
  209. }
  210. return pEnvBuf->cEntries;
  211. }
  212. ////////////////////////////////////////////////////////////////////////////
  213. //
  214. // This routine will free the memory allocated by GetRGSZEnvVar
  215. //
  216. // History:
  217. // 22-Apr-1996 JonPa Created it.
  218. //
  219. ////////////////////////////////////////////////////////////////////////////
  220. void FreeRGSZEnvVar(CPEnvBuf * pEnvBuf) {
  221. int i;
  222. for( i = 0; i < pEnvBuf->cEntries; i++ ) {
  223. LocalFree( pEnvBuf->pszVars[i] );
  224. }
  225. }
  226. ////////////////////////////////////////////////////////////////////////////
  227. // The user has made a choice among the entries.
  228. // Now we have to arrange all the strings stored in NVRAM so
  229. // that they have the same ordering. The selection is passed in,
  230. // so what this function does is if selection is M, it makes the Mth item
  231. // appear first in each of the 5 environment strings and the other items
  232. // follow it in the list.
  233. //
  234. // Then if the timeout button is checked, it updates the AUTOLOAD variable
  235. // to "yes" and set the COUNTDOWN variable to the number of seconds in the
  236. // edit control.
  237. //
  238. ////////////////////////////////////////////////////////////////////////////
  239. BOOL UpdateNVRAM(HWND hdlg, int selection, int timeout)
  240. {
  241. CHAR *rgszVRAM[5] = { "SYSTEMPARTITION",
  242. "OSLOADER",
  243. "OSLOADPARTITION",
  244. "OSLOADFILENAME",
  245. "OSLOADOPTIONS"
  246. };
  247. CPEnvBuf rgcpeb[5];
  248. WRITENVRAMPROC fpWriteNVRAMVar;
  249. int iTemp, jTemp;
  250. CHAR *pszSwap;
  251. CHAR szTemp[10];
  252. HMODULE hmodSetupDLL;
  253. BOOL bChecked;
  254. // args and charray are needed for call to SetNVRamVar() in SETUP
  255. PSZ args[2];
  256. CHAR chArray[CP_MAX_ENV*MAX_BOOT_ENTRIES];
  257. PSZ pszReturn;
  258. hmodSetupDll = LoadLibrary(TEXT("setupdll.dll"));
  259. if (!hmodSetupDll)
  260. {
  261. return FALSE;
  262. }
  263. fpWriteNVRAMVar = (WRITENVRAMPROC) GetProcAddress(hmodSetupDll, "SetNVRAMVar");
  264. if (!fpWriteNVRAMVar)
  265. {
  266. FreeLibrary (hmodSetupDll);
  267. return FALSE;
  268. }
  269. // 0 is always the selection when the dialog is brought up,
  270. // so as an optimization don't update the nvram if it's
  271. // not necessary.
  272. if (selection != 0)
  273. {
  274. // read in the strings from NVRAM. the number of strings (other than
  275. // LOADIDENTIFIER is 5)
  276. for (iTemp = 0; iTemp < 5; iTemp++)
  277. {
  278. GetRGSZEnvVar (&rgcpeb[iTemp], rgszVRAM[iTemp]);
  279. // now re-order the strings to swap the 'selection-th' item
  280. // string with the first string.
  281. pszSwap = rgcpeb[iTemp].pszVars[0];
  282. rgcpeb[iTemp].pszVars[0] = rgcpeb[iTemp].pszVars[selection];
  283. rgcpeb[iTemp].pszVars[selection] = pszSwap;
  284. }
  285. // now do the same for the LOADIDENTIFIER, (this was set up earlier
  286. // in the processing the INITDIALOG message).
  287. pszSwap = CPEBOSLoadIdentifier.pszVars[0];
  288. CPEBOSLoadIdentifier.pszVars[0] = CPEBOSLoadIdentifier.pszVars[selection];
  289. CPEBOSLoadIdentifier.pszVars[selection] = pszSwap;
  290. // now write to NVRAM: first write LOADIDENTIFIER, then the other 5
  291. // variables.
  292. args[0] = (PSZ)"LOADIDENTIFIER";
  293. args[1] = chArray;
  294. chArray[0] = '\0';
  295. for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++)
  296. {
  297. if (FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), CPEBOSLoadIdentifier.pszVars[iTemp])) ||
  298. FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), ";")))
  299. {
  300. FreeLibrary (hmodSetupDll);
  301. return FALSE;
  302. }
  303. }
  304. // remove the last semi-colon:
  305. chArray[lstrlenA(chArray)-1] = '\0';
  306. fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  307. for (iTemp = 0; iTemp < 5; iTemp++)
  308. {
  309. args[0] = rgszVRAM[iTemp];
  310. args[1] = chArray;
  311. chArray[0] = '\0';
  312. for (jTemp = 0; jTemp < rgcpeb[iTemp].cEntries; jTemp++)
  313. {
  314. if (FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), rgcpeb[iTemp].pszVars[jTemp])) ||
  315. FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), ";")))
  316. {
  317. FreeLibrary (hmodSetupDll);
  318. return FALSE;
  319. }
  320. }
  321. chArray[lstrlenA(chArray)-1] = '\0';
  322. fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  323. // We are done with this variable... Free the resources it consumes
  324. FreeRGSZEnvVar( &rgcpeb[iTemp] );
  325. }
  326. }
  327. args[0] = "AUTOLOAD";
  328. if (bChecked = IsDlgButtonChecked (hdlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN))
  329. args[1] = "YES";
  330. else
  331. args[1] = "";
  332. fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  333. // This is a temporary hack workaround for the fact that the
  334. // AUTOLOAD variable seems to be broken on Alpha
  335. //if (bChecked)
  336. //{
  337. args[0] = "COUNTDOWN";
  338. args[1] = szTemp;
  339. StringCchPrintfA(szTemp, ARRAYSIZE(szTemp), "%d", timeout);
  340. fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  341. //}
  342. FreeLibrary (hmodSetupDll);
  343. return TRUE;
  344. }
  345. #if defined(EFI_NVRAM_ENABLED)
  346. ////////////////////////////////////////////////////////////////////////////
  347. //
  348. // This routine frees allocations related to EFI Boot Manager information
  349. // from NVRAM.
  350. //
  351. ////////////////////////////////////////////////////////////////////////////
  352. VOID
  353. FreeEfiBootEntries (
  354. VOID
  355. )
  356. {
  357. PLIST_ENTRY listEntry;
  358. PMY_BOOT_ENTRY myBootEntry;
  359. while (!IsListEmpty(&BootEntries))
  360. {
  361. listEntry = RemoveHeadList(&BootEntries);
  362. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  363. LocalFree(myBootEntry);
  364. }
  365. LocalFree(BootEntryList);
  366. BootEntryList = NULL;
  367. LocalFree(BootOptions);
  368. BootOptions = NULL;
  369. return;
  370. } // FreeEfiBootEntries
  371. ////////////////////////////////////////////////////////////////////////////
  372. //
  373. // This routine reads EFI Boot Manager information from NVRAM.
  374. //
  375. ////////////////////////////////////////////////////////////////////////////
  376. BOOL
  377. ReadEfiBootEntries (
  378. VOID
  379. )
  380. {
  381. NTSTATUS status;
  382. ULONG length;
  383. ULONG count;
  384. PULONG order = NULL;
  385. PBOOT_ENTRY_LIST bootEntryList;
  386. PBOOT_ENTRY bootEntry;
  387. PMY_BOOT_ENTRY myBootEntry;
  388. PLIST_ENTRY listEntry;
  389. LONG i;
  390. BOOLEAN wasEnabled;
  391. BOOL retval = FALSE;
  392. InitializeListHead(&BootEntries);
  393. //
  394. // Enable the privilege that is necessary to query NVRAM.
  395. //
  396. status = RtlAdjustPrivilege(
  397. SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
  398. TRUE,
  399. FALSE,
  400. &wasEnabled
  401. );
  402. if (!NT_SUCCESS(status)) {
  403. return FALSE;
  404. }
  405. //
  406. // Get the global system boot options.
  407. //
  408. length = 0;
  409. status = NtQueryBootOptions(NULL, &length);
  410. if (status != STATUS_BUFFER_TOO_SMALL) {
  411. ASSERT(FALSE);
  412. goto error;
  413. } else {
  414. BootOptions = LocalAlloc(LPTR, length);
  415. if (BootOptions == NULL) {
  416. goto error;
  417. }
  418. status = NtQueryBootOptions(BootOptions, &length);
  419. if (status != STATUS_SUCCESS) {
  420. ASSERT(FALSE);
  421. goto error;
  422. }
  423. }
  424. //
  425. // Get the system boot order list.
  426. //
  427. count = 0;
  428. status = NtQueryBootEntryOrder(NULL, &count);
  429. if (status != STATUS_BUFFER_TOO_SMALL) {
  430. if (status == STATUS_SUCCESS) {
  431. //
  432. // There are no entries in the boot order list. Strange but
  433. // possible.
  434. //
  435. count = 0;
  436. } else {
  437. //
  438. // An unexpected error occurred.
  439. //
  440. ASSERT(FALSE);
  441. goto error;
  442. }
  443. }
  444. if (count != 0) {
  445. order = LocalAlloc(LPTR, count * sizeof(ULONG));
  446. if (order == NULL) {
  447. goto error;
  448. }
  449. status = NtQueryBootEntryOrder(order, &count);
  450. if (status != STATUS_SUCCESS) {
  451. //
  452. // An unexpected error occurred.
  453. //
  454. ASSERT(FALSE);
  455. goto error;
  456. }
  457. }
  458. //
  459. // Get all existing boot entries.
  460. //
  461. length = 0;
  462. status = NtEnumerateBootEntries(NULL, &length);
  463. if (status != STATUS_BUFFER_TOO_SMALL) {
  464. if (status == STATUS_SUCCESS) {
  465. //
  466. // Somehow there are no boot entries in NVRAM.
  467. //
  468. goto error;
  469. } else {
  470. //
  471. // An unexpected error occurred.
  472. //
  473. ASSERT(FALSE);
  474. goto error;
  475. }
  476. }
  477. ASSERT(length != 0);
  478. BootEntryList = LocalAlloc(LPTR, length);
  479. if (BootEntryList == NULL) {
  480. goto error;
  481. }
  482. status = NtEnumerateBootEntries(BootEntryList, &length);
  483. if (status != STATUS_SUCCESS) {
  484. ASSERT(FALSE);
  485. goto error;
  486. }
  487. //
  488. // Convert the boot entries into our internal representation.
  489. //
  490. bootEntryList = BootEntryList;
  491. while (TRUE) {
  492. bootEntry = &bootEntryList->BootEntry;
  493. //
  494. // Allocate an internal structure for the boot entry.
  495. //
  496. myBootEntry = LocalAlloc(LPTR, sizeof(MY_BOOT_ENTRY));
  497. if (myBootEntry == NULL) {
  498. goto error;
  499. }
  500. RtlZeroMemory(myBootEntry, sizeof(MY_BOOT_ENTRY));
  501. //
  502. // Save the address of the NT boot entry.
  503. //
  504. myBootEntry->NtBootEntry = bootEntry;
  505. //
  506. // Save the address of the entry's friendly name.
  507. //
  508. myBootEntry->FriendlyName = ADD_OFFSET(bootEntry, FriendlyNameOffset);
  509. //
  510. // Link the new entry into the list.
  511. //
  512. InsertTailList(&BootEntries, &myBootEntry->ListEntry);
  513. //
  514. // Move to the next entry in the enumeration list, if any.
  515. //
  516. if (bootEntryList->NextEntryOffset == 0) {
  517. break;
  518. }
  519. bootEntryList = ADD_OFFSET(bootEntryList, NextEntryOffset);
  520. }
  521. //
  522. // Boot entries are returned in an unspecified order. They are currently
  523. // in the SpBootEntries list in the order in which they were returned.
  524. // Sort the boot entry list based on the boot order. Do this by walking
  525. // the boot order array backwards, reinserting the entry corresponding to
  526. // each element of the array at the head of the list.
  527. //
  528. for (i = (LONG)count - 1; i >= 0; i--) {
  529. for (listEntry = BootEntries.Flink;
  530. listEntry != &BootEntries;
  531. listEntry = listEntry->Flink) {
  532. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  533. if (myBootEntry->NtBootEntry->Id == order[i] ) {
  534. //
  535. // We found the boot entry with this ID. Move it to the
  536. // front of the list.
  537. //
  538. myBootEntry->Ordered = TRUE;
  539. RemoveEntryList(&myBootEntry->ListEntry);
  540. InsertHeadList(&BootEntries, &myBootEntry->ListEntry);
  541. break;
  542. }
  543. }
  544. }
  545. //
  546. // Free the boot order list.
  547. //
  548. if (count != 0) {
  549. LocalFree(order);
  550. order = NULL;
  551. }
  552. //
  553. // We don't want to show entries that are not in the boot order list.
  554. // We don't want to show removable media entries (for floppy or CD).
  555. // We do show non-NT entries.
  556. //
  557. count = 0;
  558. for (listEntry = BootEntries.Flink;
  559. listEntry != &BootEntries;
  560. listEntry = listEntry->Flink) {
  561. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  562. if (myBootEntry->Ordered &&
  563. ((myBootEntry->NtBootEntry->Attributes & BOOT_ENTRY_ATTRIBUTE_REMOVABLE_MEDIA) == 0)) {
  564. myBootEntry->Show = TRUE;
  565. count++;
  566. }
  567. }
  568. //
  569. // If we don't have any entries to show, disable the dialog box entirely.
  570. //
  571. if (count == 0) {
  572. goto error;
  573. }
  574. retval = TRUE;
  575. done:
  576. if (!wasEnabled) {
  577. status = RtlAdjustPrivilege(
  578. SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
  579. FALSE,
  580. FALSE,
  581. &wasEnabled
  582. );
  583. }
  584. return retval;
  585. error:
  586. //
  587. // An error occurred. Clean up all allocations.
  588. //
  589. LocalFree(order);
  590. FreeEfiBootEntries();
  591. goto done;
  592. } // ReadEfiBootEntries
  593. ////////////////////////////////////////////////////////////////////////////
  594. //
  595. // EFI version of UpdateNVRAM.
  596. //
  597. // The user has made a choice among the entries. Rewrite the boot order
  598. // list to put the user's selection at the front. Also update the Timeout
  599. // variable.
  600. //
  601. ////////////////////////////////////////////////////////////////////////////
  602. BOOL
  603. WriteEfiBootEntries (
  604. HWND hdlg,
  605. int selection,
  606. int timeout
  607. )
  608. {
  609. NTSTATUS status;
  610. BOOLEAN wasEnabled;
  611. BOOL retval = FALSE;
  612. //
  613. // Enable the privilege that is necessary to query NVRAM.
  614. //
  615. status = RtlAdjustPrivilege(
  616. SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
  617. TRUE,
  618. FALSE,
  619. &wasEnabled
  620. );
  621. if (!NT_SUCCESS(status)) {
  622. return FALSE;
  623. }
  624. //
  625. // 0 is always the selection when the dialog is brought up,
  626. // so as an optimization don't update the nvram if it's
  627. // not necessary.
  628. //
  629. if (selection != 0) {
  630. //
  631. // Walk the boot entry list, looking for (a) the entry with combo box
  632. // index 0, and (b) the selected entry. We want to swap these two
  633. // entries.
  634. //
  635. PLIST_ENTRY listEntry;
  636. PMY_BOOT_ENTRY myBootEntry;
  637. PMY_BOOT_ENTRY firstEntry = NULL;
  638. PMY_BOOT_ENTRY selectedEntry = NULL;
  639. PLIST_ENTRY previousEntry;
  640. ULONG count;
  641. PULONG order;
  642. for (listEntry = BootEntries.Flink;
  643. listEntry != &BootEntries;
  644. listEntry = listEntry->Flink) {
  645. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  646. if (myBootEntry->Show) {
  647. if (myBootEntry->Index == 0) {
  648. firstEntry = myBootEntry;
  649. } else if (myBootEntry->Index == selection) {
  650. selectedEntry = myBootEntry;
  651. }
  652. }
  653. }
  654. ASSERT(firstEntry != NULL);
  655. ASSERT(selectedEntry != NULL);
  656. ASSERT(selectedEntry != firstEntry);
  657. //
  658. // Swap the entries. Capture the address of the entry before the first
  659. // entry (which might be the list head). Remove the first entry from
  660. // the list and insert it after the selected entry. Remove the selected
  661. // entry from the list and insert it after the captured entry.
  662. //
  663. previousEntry = firstEntry->ListEntry.Blink;
  664. RemoveEntryList(&firstEntry->ListEntry);
  665. InsertHeadList(&selectedEntry->ListEntry, &firstEntry->ListEntry);
  666. RemoveEntryList(&selectedEntry->ListEntry);
  667. InsertHeadList(previousEntry, &selectedEntry->ListEntry);
  668. //
  669. // Build the new boot order list. Insert all ordered boot entries
  670. // into the list.
  671. //
  672. count = 0;
  673. for (listEntry = BootEntries.Flink;
  674. listEntry != &BootEntries;
  675. listEntry = listEntry->Flink) {
  676. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  677. if (myBootEntry->Ordered) {
  678. count++;
  679. }
  680. }
  681. order = LocalAlloc(LPTR, count * sizeof(ULONG));
  682. if (order == NULL) {
  683. goto done;
  684. }
  685. count = 0;
  686. for (listEntry = BootEntries.Flink;
  687. listEntry != &BootEntries;
  688. listEntry = listEntry->Flink) {
  689. myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  690. if (myBootEntry->Ordered) {
  691. order[count++] = myBootEntry->NtBootEntry->Id;
  692. }
  693. }
  694. //
  695. // Write the new boot entry order list to NVRAM.
  696. //
  697. status = NtSetBootEntryOrder(order, count);
  698. LocalFree(order);
  699. if (!NT_SUCCESS(status)) {
  700. goto done;
  701. }
  702. }
  703. //
  704. // Write the new timeout value to NVRAM.
  705. //
  706. if (!IsDlgButtonChecked(hdlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN)) {
  707. timeout = 0xffffffff;
  708. }
  709. if (timeout != BootOptions->Timeout) {
  710. BootOptions->Timeout = timeout;
  711. status = NtSetBootOptions(BootOptions, BOOT_OPTIONS_FIELD_TIMEOUT);
  712. if (!NT_SUCCESS(status)) {
  713. goto done;
  714. }
  715. }
  716. retval = TRUE;
  717. done:
  718. if (!wasEnabled) {
  719. status = RtlAdjustPrivilege(
  720. SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
  721. FALSE,
  722. FALSE,
  723. &wasEnabled
  724. );
  725. }
  726. return retval;
  727. } // WriteEfiBootEntries
  728. #endif // defined(EFI_NVRAM_ENABLED)
  729. #ifdef _X86_
  730. BOOL WriteableBootIni( LPTSTR szBootIni, HWND hDlg ) {
  731. BOOL bOK;
  732. DWORD dwFileAttr;
  733. HANDLE hFile;
  734. bOK = TRUE;
  735. // Change Read-only file attrs on Boot.ini file if necessary
  736. if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF) {
  737. if (dwFileAttr & FILE_ATTRIBUTE_READONLY) {
  738. if (!SetFileAttributes (szBootIni, dwFileAttr & ~FILE_ATTRIBUTE_READONLY))
  739. {
  740. bOK = FALSE;
  741. }
  742. }
  743. }
  744. if (bOK)
  745. {
  746. hFile = CreateFile( szBootIni, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
  747. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  748. if (hFile != INVALID_HANDLE_VALUE) {
  749. CloseHandle(hFile);
  750. } else {
  751. if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) {
  752. MsgBoxParam (hDlg, IDS_SYSDM_CANNOTOPENFILE, IDS_SYSDM_TITLE, MB_OK | MB_ICONEXCLAMATION, szBootIni);
  753. }
  754. bOK = FALSE;
  755. }
  756. // Restore read-only attr, if necessary, after writes
  757. if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) {
  758. SetFileAttributes (szBootIni, dwFileAttr);
  759. }
  760. }
  761. return bOK;
  762. }
  763. #endif
  764. void StartListInit( HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  765. HWND hwndTemp;
  766. HMODULE hmodSetupDll;
  767. int iTemp;
  768. int n;
  769. int timeout;
  770. #ifdef _X86_
  771. int i;
  772. TCHAR szTemp2[MAX_PATH];
  773. int selection;
  774. TCHAR *pszKeyName;
  775. LPTSTR pszLine;
  776. TCHAR *pszValue;
  777. TCHAR *pszTemp;
  778. // ANSI string pointers
  779. LPWSTR pszSectionHead;
  780. LPWSTR pszSection;
  781. #endif
  782. #if defined(EFI_NVRAM_ENABLED)
  783. if (IsEfi()) {
  784. ShowWindow(GetDlgItem(hDlg, IDC_SYS_EDIT_BUTTION), FALSE);
  785. ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_SYS_EDIT_LABEL), FALSE);
  786. hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  787. fCanUpdateNVRAM = ReadEfiBootEntries();
  788. if (fCanUpdateNVRAM) {
  789. PLIST_ENTRY listEntry;
  790. PMY_BOOT_ENTRY bootEntry;
  791. for (listEntry = BootEntries.Flink;
  792. listEntry != &BootEntries;
  793. listEntry = listEntry->Flink) {
  794. bootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
  795. if (bootEntry->Show) {
  796. bootEntry->Index = (int)SendMessage (hwndTemp, CB_ADDSTRING, 0,
  797. (LPARAM)bootEntry->FriendlyName);
  798. }
  799. }
  800. // the first one is the selection we want (offset 0)
  801. SendMessage (hwndTemp, CB_SETCURSEL, 0, 0L);
  802. nOriginalSelection = 0;
  803. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS,
  804. EM_LIMITTEXT, 3, 0L);
  805. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL,
  806. UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
  807. if (BootOptions->Timeout != 0xffffffff) {
  808. if (BootOptions->Timeout > 999) {
  809. BootOptions->Timeout = 999;
  810. }
  811. SetDlgItemInt(
  812. hDlg,
  813. IDC_STARTUP_SYS_SECONDS,
  814. BootOptions->Timeout,
  815. FALSE
  816. );
  817. CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, TRUE);
  818. } else {
  819. SetDlgItemInt(
  820. hDlg,
  821. IDC_STARTUP_SYS_SECONDS,
  822. 0,
  823. FALSE
  824. );
  825. CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, FALSE);
  826. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  827. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  828. }
  829. } else {
  830. // if can't set variables (no privilege), disable controls
  831. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  832. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE);
  833. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE);
  834. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  835. EnableWindow (hwndTemp, FALSE);
  836. }
  837. } else
  838. #endif // defined(EFI_NVRAM_ENABLED)
  839. #ifdef _X86_
  840. if (Is_ARCx86())
  841. #endif
  842. {
  843. ////////////////////////////////////////////////////////////////////
  844. // Read info from NVRAM environment variables
  845. ////////////////////////////////////////////////////////////////////
  846. // Init to 0 so we won't try to free garbage if we cant load setup.dll
  847. CPEBOSLoadIdentifier.cEntries = 0;
  848. fCanUpdateNVRAM = FALSE;
  849. fAutoLoad = FALSE;
  850. hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  851. if (hmodSetupDll = LoadLibrary(TEXT("setupdll")))
  852. {
  853. if (fpGetNVRAMvar = (GETNVRAMPROC)GetProcAddress(hmodSetupDll, "GetNVRAMVar"))
  854. {
  855. if (fCanUpdateNVRAM = GetRGSZEnvVar (&CPEBOSLoadIdentifier, "LOADIDENTIFIER"))
  856. {
  857. for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++)
  858. n = (int)SendMessageA (hwndTemp, CB_ADDSTRING, 0,
  859. (LPARAM)CPEBOSLoadIdentifier.pszVars[iTemp]);
  860. // the first one is the selection we want (offset 0)
  861. SendMessage (hwndTemp, CB_SETCURSEL, 0, 0L);
  862. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS,
  863. EM_LIMITTEXT, 3, 0L);
  864. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL,
  865. UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
  866. }
  867. // fCanUpdateNVRAM is a global that gets set up above
  868. if (fCanUpdateNVRAM)
  869. {
  870. // This is a temporary hack workaround for the
  871. // fact that the AUTOLOAD variable seems to
  872. // be broken on Alpha
  873. CPEnvBuf cpebTimeout;
  874. if (GetRGSZEnvVar(&cpebTimeout, "COUNTDOWN")) {
  875. timeout = StringToIntA(cpebTimeout.pszVars[0]);
  876. fAutoLoad = (BOOL) timeout;
  877. SetDlgItemInt(
  878. hDlg,
  879. IDC_STARTUP_SYS_SECONDS,
  880. timeout,
  881. FALSE
  882. );
  883. FreeRGSZEnvVar(&cpebTimeout);
  884. } // if
  885. CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, fAutoLoad);
  886. if (!fAutoLoad)
  887. {
  888. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  889. EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  890. }
  891. }
  892. }
  893. FreeLibrary (hmodSetupDll);
  894. }
  895. if (!fCanUpdateNVRAM) {
  896. // if can't set variables (no privilege), disable controls
  897. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  898. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE);
  899. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE);
  900. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  901. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE);
  902. }
  903. // default to 5 seconds for now.
  904. }
  905. #ifdef _X86_
  906. else
  907. {
  908. ////////////////////////////////////////////////////////////////////
  909. // Read info from boot.ini file and initialize OS Group box items
  910. ////////////////////////////////////////////////////////////////////
  911. InitializeArcStuff();
  912. //
  913. // Get correct Boot Drive - this was added because after someone
  914. // boots the system, they can ghost or change the drive letter
  915. // of their boot drive from "c:" to something else.
  916. //
  917. szBootIni[0] = x86DetermineSystemPartition (hDlg);
  918. //
  919. // Make sure we have access to BOOT.INI
  920. //
  921. if (!WriteableBootIni(szBootIni, hDlg)) {
  922. // if can't set variables (no privilege), disable controls
  923. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  924. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE);
  925. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE);
  926. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  927. EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE);
  928. }
  929. //
  930. // Determine which section [boot loader]
  931. // [flexboot]
  932. // or [multiboot] is in file
  933. //
  934. n = GetPrivateProfileString (szBootLdr, NULL, NULL, szTemp2,
  935. ARRAYSIZE(szTemp2), szBootIni);
  936. if (n != 0)
  937. pszBoot = szBootLdr;
  938. else
  939. {
  940. n = GetPrivateProfileString (szFlexBoot, NULL, NULL, szTemp2,
  941. ARRAYSIZE(szTemp2), szBootIni);
  942. if (n != 0)
  943. pszBoot = szFlexBoot;
  944. else
  945. {
  946. n = GetPrivateProfileString (szMultiBoot, NULL, NULL, szTemp2,
  947. ARRAYSIZE(szTemp2), szBootIni);
  948. if (n != 0)
  949. {
  950. pszBoot = szMultiBoot;
  951. }
  952. else
  953. {
  954. //
  955. // This final case is here because I want to DEFAULT
  956. // to "[boot loader]" as the section name to use in
  957. // the event that we do not find any section in the
  958. // boot.ini file.
  959. //
  960. pszBoot = szBootLdr;
  961. }
  962. }
  963. }
  964. // Get info under [*pszBoot] section - timeout & default OS path
  965. timeout = GetPrivateProfileInt (pszBoot, szTimeout, 0, szBootIni);
  966. SetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, timeout, FALSE);
  967. nOriginalTimeout = timeout;
  968. //
  969. // Get the "Default" os selection
  970. //
  971. szTemp2[0] = TEXT('\0');
  972. GetPrivateProfileString (pszBoot, szDefault, NULL, szTemp2,
  973. ARRAYSIZE(szTemp2), szBootIni);
  974. //
  975. // Display all choices under [operating system] in boot.ini file
  976. // in combobox for selection
  977. //
  978. hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  979. selection = -1;
  980. pszSectionHead = pszSection = (LPWSTR) LocalAlloc (LPTR, BUFZ * sizeof(WCHAR));
  981. if (!pszSection)
  982. {
  983. goto ContinueSystemInit;
  984. }
  985. //
  986. // Get entire section under OS to properly show user choices
  987. //
  988. n = GetPrivateProfileSection (szOS, pszSection, BUFZ, szBootIni);
  989. if ((n >= BUFZ-2) || (n == 0))
  990. {
  991. // Error reading data
  992. goto ContinueSystemInit;
  993. }
  994. //
  995. // Check for api errors and NoOptions
  996. //
  997. if ((pszSection == NULL) || ((*pszSection == TEXT('\0')) && (*(pszSection+1) == TEXT('\0'))))
  998. {
  999. goto ContinueSystemInit;
  1000. }
  1001. //
  1002. // Continue until we reach end of buffer, marked by Double '\0'
  1003. //
  1004. while (*(pszSection+1) != TEXT('\0'))
  1005. {
  1006. pszLine = pszSection;
  1007. //
  1008. // Get pointer to next line in buffer.
  1009. //
  1010. pszSection += lstrlen (pszSection) + 1;
  1011. //
  1012. // Find LHS/RHS delimiter to separate strings
  1013. //
  1014. pszValue = StrStr(pszLine, TEXT("="));
  1015. if (pszValue && (pszValue != pszLine))
  1016. {
  1017. *pszValue = '\0';
  1018. pszValue++;
  1019. }
  1020. else
  1021. {
  1022. pszValue = pszLine;
  1023. }
  1024. //
  1025. // Put it into combobox (if no descriptive name, use path)
  1026. //
  1027. n = (int)SendMessage (hwndTemp, CB_ADDSTRING, 0, (LPARAM) (LPTSTR) pszValue);
  1028. //
  1029. // Find the first selection that matches the "default" selection
  1030. //
  1031. if ((selection == -1) && !lstrcmp (pszLine, szTemp2))
  1032. selection = n;
  1033. //
  1034. // Also attach pointer to KeyName (i.e. boot path) to each item
  1035. //
  1036. pszTemp = StrDup(pszLine);
  1037. SendMessage (hwndTemp, CB_SETITEMDATA, n, (LPARAM)pszTemp); // if not allocated, set it to NULL
  1038. }
  1039. // If no selection was found up to this point, choose 0, because
  1040. // that is the default value that loader would choose.
  1041. if (selection == -1)
  1042. selection = 0;
  1043. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS, EM_LIMITTEXT, 3, 0L);
  1044. SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL,
  1045. UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
  1046. // Check or uncheck the checkbox based on the timeout value
  1047. SendDlgItemMessage(
  1048. hDlg,
  1049. IDC_STARTUP_SYS_ENABLECOUNTDOWN,
  1050. BM_SETCHECK,
  1051. (WPARAM) (BOOL) timeout,
  1052. (LPARAM) 0L
  1053. );
  1054. EnableWindow(
  1055. GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS),
  1056. (BOOL) timeout
  1057. );
  1058. EnableWindow(
  1059. GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL),
  1060. (BOOL) timeout
  1061. );
  1062. // This call should force correct settings for the checkbox
  1063. // and "Showlist for xx seconds" controls
  1064. nOriginalSelection = selection;
  1065. SendMessage (hwndTemp, CB_SETCURSEL, selection, 0L);
  1066. ContinueSystemInit:
  1067. LocalFree(pszSectionHead);
  1068. }
  1069. #endif // _X86_
  1070. }
  1071. //
  1072. // IE. We need to handle CANCEL case.
  1073. //
  1074. int StartListExit(HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  1075. HWND hwndTemp;
  1076. int selection, timeout;
  1077. #ifdef _X86_
  1078. DWORD dwFileAttr;
  1079. BOOL bOK;
  1080. TCHAR szBuffer[BUFZ]; // we build this up and write it to boot.ini
  1081. TCHAR* pszSlidingPtr; // we slide this along szBuffer
  1082. TCHAR szTemp[BUFZ];
  1083. int n;
  1084. TCHAR *pszTemp;
  1085. int iTemp;
  1086. #endif
  1087. /////////////////////////////////////////////////////////////////
  1088. // Write new info to boot.ini file
  1089. /////////////////////////////////////////////////////////////////
  1090. hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  1091. selection = (int)SendMessage (hwndTemp, CB_GETCURSEL, 0, 0L);
  1092. if ((selection == CB_ERR) || (selection == CB_ERRSPACE))
  1093. selection = nOriginalSelection;
  1094. timeout = GetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, NULL, FALSE);
  1095. #if defined(EFI_NVRAM_ENABLED)
  1096. if (IsEfi()) {
  1097. if (fCanUpdateNVRAM) {
  1098. TCHAR szTextNew[MAX_PATH];
  1099. TCHAR szTextTop[MAX_PATH];
  1100. WriteEfiBootEntries(hDlg, selection, timeout);
  1101. /*
  1102. * Now reorder list to match NVRAM
  1103. */
  1104. // Get the current text
  1105. if (SafeGetComboBoxListText(hwndTemp, selection, szTextNew, ARRAYSIZE(szTextNew)) &&
  1106. SafeGetComboBoxListText(hwndTemp, 0, szTextTop, ARRAYSIZE(szTextTop)))
  1107. {
  1108. // Set the new text to the 0th entry in the list
  1109. SendMessage( hwndTemp, CB_DELETESTRING, 0, 0 );
  1110. SendMessage( hwndTemp, CB_INSERTSTRING, 0, (LPARAM)szTextNew);
  1111. // Set old top text selected item
  1112. SendMessage( hwndTemp, CB_DELETESTRING, selection, 0 );
  1113. SendMessage( hwndTemp, CB_INSERTSTRING, selection, (LPARAM)szTextTop);
  1114. // Now point the current selection back to the top of the list, so it matches
  1115. // what the user just chose
  1116. SendMessage( hwndTemp, CB_SETCURSEL, 0, 0);
  1117. }
  1118. }
  1119. } else
  1120. #endif // defined(EFI_NVRAM_ENABLED)
  1121. #ifdef _X86_
  1122. if (Is_ARCx86())
  1123. #endif
  1124. {
  1125. if (fCanUpdateNVRAM) {
  1126. TCHAR szTextNew[MAX_PATH];
  1127. TCHAR szTextTop[MAX_PATH];
  1128. UpdateNVRAM (hDlg, selection, timeout);
  1129. /*
  1130. * Now reorder list to match NVRAM
  1131. */
  1132. // Get the current text
  1133. if (SafeGetComboBoxListText(hwndTemp, selection, szTextNew, ARRAYSIZE(szTextNew)) &&
  1134. SafeGetComboBoxListText(hwndTemp, 0, szTextTop, ARRAYSIZE(szTextTop)))
  1135. {
  1136. // Set the new text to the 0th entry in the list
  1137. SendMessage( hwndTemp, CB_DELETESTRING, 0, 0 );
  1138. SendMessage( hwndTemp, CB_INSERTSTRING, 0, (LPARAM)szTextNew);
  1139. // Set old top text selected item
  1140. SendMessage( hwndTemp, CB_DELETESTRING, selection, 0 );
  1141. SendMessage( hwndTemp, CB_INSERTSTRING, selection, (LPARAM)szTextTop);
  1142. // Now point the current selection back to the top of the list, so it matches
  1143. // what the user just chose
  1144. SendMessage( hwndTemp, CB_SETCURSEL, 0, 0);
  1145. }
  1146. }
  1147. }
  1148. #ifdef _X86_
  1149. else
  1150. {
  1151. if ((selection != nOriginalSelection) || (timeout != nOriginalTimeout))
  1152. {
  1153. bOK = TRUE;
  1154. // Change Read-only file attrs on Boot.ini file if necessary
  1155. if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF)
  1156. if (dwFileAttr & FILE_ATTRIBUTE_READONLY)
  1157. if (!SetFileAttributes (szBootIni,
  1158. dwFileAttr & ~FILE_ATTRIBUTE_READONLY))
  1159. {
  1160. BootIniWriteError:
  1161. bOK = FALSE;
  1162. MsgBoxParam (hDlg, IDS_SYSDM_NOCHANGE_BOOTINI, IDS_SYSDM_TITLE, MB_OK | MB_ICONINFORMATION);
  1163. }
  1164. if (bOK)
  1165. {
  1166. //
  1167. // Write new [operating systems] section and
  1168. // set "default" selection in boot.ini file.
  1169. //
  1170. if (selection != nOriginalSelection)
  1171. {
  1172. pszSlidingPtr = szBuffer;
  1173. // Get the User's selection and write it in the
  1174. // section buffer first. Then get all other items.
  1175. pszTemp = (LPTSTR) SendMessage(hwndTemp, CB_GETITEMDATA, selection, 0L);
  1176. if (SafeGetComboBoxListText(hwndTemp, selection, szTemp, ARRAYSIZE(szTemp)))
  1177. {
  1178. if (FAILED(StringCchPrintf(pszSlidingPtr,
  1179. ARRAYSIZE(szBuffer) - (pszSlidingPtr - szBuffer),
  1180. TEXT("%s=%s"),
  1181. pszTemp,
  1182. szTemp)))
  1183. {
  1184. goto BootIniWriteError;
  1185. }
  1186. else
  1187. {
  1188. pszSlidingPtr += (lstrlen (pszSlidingPtr) + 1);
  1189. // Set "default" selection in boot.ini file
  1190. if (!WritePrivateProfileString (pszBoot, szDefault, pszTemp, szBootIni))
  1191. {
  1192. goto BootIniWriteError;
  1193. }
  1194. }
  1195. }
  1196. // Get the rest of the selections
  1197. n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L);
  1198. if (n != LB_ERR)
  1199. {
  1200. for (iTemp = 0; iTemp < n; iTemp++)
  1201. {
  1202. // Skip the User's selection since we got it
  1203. // above.
  1204. if (iTemp == selection)
  1205. continue;
  1206. pszTemp = (LPTSTR) SendMessage (hwndTemp, CB_GETITEMDATA, iTemp, 0L);
  1207. if (SafeGetComboBoxListText(hwndTemp, iTemp, szTemp, ARRAYSIZE(szTemp)))
  1208. {
  1209. if (FAILED(StringCchPrintf(pszSlidingPtr,
  1210. ARRAYSIZE(szBuffer) - (pszSlidingPtr - szBuffer),
  1211. TEXT("%s=%s"),
  1212. pszTemp,
  1213. szTemp)))
  1214. {
  1215. goto BootIniWriteError;
  1216. }
  1217. pszSlidingPtr += (lstrlen (pszSlidingPtr) + 1);
  1218. }
  1219. }
  1220. }
  1221. // Double-Null terminate the buffer
  1222. *pszSlidingPtr = TEXT('\0');
  1223. // Write new section under OS
  1224. if (!WritePrivateProfileSectionW(szOS, szBuffer, szBootIni))
  1225. {
  1226. goto BootIniWriteError;
  1227. }
  1228. }
  1229. if (timeout != nOriginalTimeout)
  1230. {
  1231. GetDlgItemText (hDlg, IDC_STARTUP_SYS_SECONDS, szTemp, ARRAYSIZE(szTemp));
  1232. if (!CheckVal (hDlg, IDC_STARTUP_SYS_SECONDS, FORMIN, FORMAX, IDS_SYSDM_ENTERSECONDS))
  1233. return RET_BREAK;
  1234. // Write timeout value to file
  1235. if (!WritePrivateProfileString (pszBoot, szTimeout,
  1236. szTemp, szBootIni))
  1237. goto BootIniWriteError;
  1238. }
  1239. // Restore read-only attr, if necessary, after writes
  1240. if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) {
  1241. SetFileAttributes (szBootIni, dwFileAttr);
  1242. }
  1243. }
  1244. }
  1245. }
  1246. #endif // _X86_
  1247. return RET_CONTINUE;
  1248. }
  1249. BOOL CheckVal( HWND hDlg, WORD wID, WORD wMin, WORD wMax, WORD wMsgID )
  1250. {
  1251. WORD nVal;
  1252. BOOL bOK;
  1253. HWND hVal;
  1254. WCHAR szTemp[FOR_MAX_LENGTH];
  1255. if( wMin > wMax )
  1256. {
  1257. nVal = wMin;
  1258. wMin = wMax;
  1259. wMax = nVal;
  1260. }
  1261. nVal = (WORD) GetDlgItemInt( hDlg, wID, &bOK, FALSE );
  1262. //
  1263. // This is a hack to make the null string act equivalent to zero
  1264. //
  1265. if (!bOK) {
  1266. bOK = !GetDlgItemTextW( hDlg, wID, szTemp, FOR_MAX_LENGTH );
  1267. }
  1268. if( !bOK || ( nVal < wMin ) || ( nVal > wMax ) )
  1269. {
  1270. MsgBoxParam( hDlg, wMsgID, IDS_SYSDM_TITLE,
  1271. MB_OK | MB_ICONERROR, wMin, wMax );
  1272. SendMessage( hDlg, WM_NEXTDLGCTL,
  1273. (WPARAM) ( hVal = GetDlgItem( hDlg, wID ) ), 1L );
  1274. // SendMessage(hVal, EM_SETSEL, NULL, MAKELONG(0, 32767));
  1275. SendMessage( hVal, EM_SETSEL, 0, 32767 );
  1276. return( FALSE );
  1277. }
  1278. return( TRUE );
  1279. }
  1280. //////////////////////////////////////////////////////
  1281. //
  1282. // Frees the data (if any) associated with the strings in the combo box
  1283. //
  1284. //////////////////////////////////////////////////////
  1285. void StartListDestroy(HWND hDlg, WPARAM wParam, LPARAM lParam) {
  1286. #if defined(EFI_NVRAM_ENABLED)
  1287. if (IsEfi()) {
  1288. FreeEfiBootEntries();
  1289. } else
  1290. #endif // defined(EFI_NVRAM_ENABLED)
  1291. #ifdef _X86_
  1292. if (Is_ARCx86())
  1293. #endif
  1294. {
  1295. // Reference vars to make compiler happy
  1296. FreeRGSZEnvVar(&CPEBOSLoadIdentifier);
  1297. return;
  1298. (void)hDlg;
  1299. (void)wParam;
  1300. (void)lParam;
  1301. }
  1302. #ifdef _X86_
  1303. else
  1304. {
  1305. // Only X86 has data in the combo
  1306. int n;
  1307. HWND hwndTemp;
  1308. int iTemp;
  1309. TCHAR *pszTemp;
  1310. //
  1311. // Free strings stored in the listbox
  1312. //
  1313. hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  1314. n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L);
  1315. if (n != LB_ERR)
  1316. {
  1317. for (iTemp = 0; iTemp < n; iTemp++)
  1318. {
  1319. pszTemp = (LPTSTR) SendMessage (hwndTemp,
  1320. CB_GETITEMDATA,
  1321. iTemp, 0L);
  1322. if (pszTemp &&
  1323. pszTemp != (LPTSTR) CB_ERR)
  1324. {
  1325. LocalFree (pszTemp);
  1326. }
  1327. }
  1328. }
  1329. }
  1330. #endif // _X86_
  1331. }
  1332. void AutoAdvancedBootInit( HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  1333. BOOL fEnabled = FALSE;
  1334. UCHAR cTimeout = 0;
  1335. NTSTATUS status;
  1336. #ifdef _X86_
  1337. //
  1338. // Initialize the boot status data.
  1339. //
  1340. status = RtlLockBootStatusData(&hBootStatusData);
  1341. if(NT_SUCCESS(status)) {
  1342. RtlGetSetBootStatusData(hBootStatusData,
  1343. TRUE,
  1344. RtlBsdItemAabEnabled,
  1345. &fEnabled,
  1346. sizeof(BOOL),
  1347. NULL);
  1348. RtlGetSetBootStatusData(hBootStatusData,
  1349. TRUE,
  1350. RtlBsdItemAabTimeout,
  1351. &cTimeout,
  1352. sizeof(UCHAR),
  1353. NULL);
  1354. SetDlgItemInt(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, cTimeout, FALSE);
  1355. CheckDlgButton(hDlg, IDC_STARTUP_AUTOLKG, fEnabled);
  1356. SendDlgItemMessage(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, EM_LIMITTEXT, 3, 0L);
  1357. SendDlgItemMessage(hDlg,
  1358. IDC_STARTUP_AUTOLKG_SECSCROLL,
  1359. UDM_SETRANGE,
  1360. 0,
  1361. (LPARAM)MAKELONG(999,0));
  1362. if(!fEnabled) {
  1363. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE);
  1364. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE);
  1365. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE);
  1366. }
  1367. } else {
  1368. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG), FALSE);
  1369. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE);
  1370. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE);
  1371. EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE);
  1372. }
  1373. #else
  1374. ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG), FALSE);
  1375. ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE);
  1376. ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE);
  1377. ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE);
  1378. #endif
  1379. return;
  1380. }
  1381. //
  1382. // IE. We need to handle CANCEL case.
  1383. //
  1384. int AutoAdvancedBootExit(HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  1385. BOOL fEnabled;
  1386. UINT iTime;
  1387. UCHAR cTimeout;
  1388. NTSTATUS status;
  1389. #if _X86_
  1390. if(LOWORD(wParam) != IDCANCEL) {
  1391. //
  1392. // Read the setting of the enabled checkbox.
  1393. //
  1394. fEnabled = IsDlgButtonChecked(hDlg, IDC_STARTUP_AUTOLKG);
  1395. if(fEnabled) {
  1396. iTime = GetDlgItemInt(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, NULL, FALSE);
  1397. cTimeout = (UCHAR) min(iTime, 0xff);
  1398. }
  1399. //
  1400. // If we got access in AutoAdvancedBootInit, write the boot status data and exit.
  1401. //
  1402. if (hBootStatusData)
  1403. {
  1404. RtlGetSetBootStatusData(hBootStatusData,
  1405. FALSE,
  1406. RtlBsdItemAabEnabled,
  1407. &fEnabled,
  1408. sizeof(BOOL),
  1409. NULL);
  1410. if(fEnabled) {
  1411. RtlGetSetBootStatusData(hBootStatusData,
  1412. FALSE,
  1413. RtlBsdItemAabTimeout,
  1414. &cTimeout,
  1415. sizeof(UCHAR),
  1416. NULL);
  1417. }
  1418. }
  1419. }
  1420. if (hBootStatusData)
  1421. {
  1422. RtlUnlockBootStatusData(hBootStatusData);
  1423. hBootStatusData = NULL;
  1424. }
  1425. #endif
  1426. return RET_CONTINUE;
  1427. }