Source code of Windows XP (NT5)
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.

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