|
|
/*++
Microsoft Confidential Copyright (c) 1992-1997 Microsoft Corporation All rights reserved
Module Name:
strtlst.c
Abstract:
Implements the controls in the "Startup" group on the Startup/Recovery dialog of the System Control Panel Applet
Revision History:
23-Jan-1996 JonPa ported from NT3.51's system.cpl
--*/ #include "sysdm.h"
///////////////////////////////////////////////////////////////
// Persistant vars
///////////////////////////////////////////////////////////////
static TCHAR *pszBoot = NULL; static int nOriginalSelection; static int nOriginalTimeout;
HANDLE hBootStatusData = NULL;
/*
* These functions in SETUPDLL.DLL are ANSI only!!!! * * Therefore any functions working with this DLL MUST remain ANSI only. * The functions are GetRGSZEnvVar and UpdateNVRAM. * The structure CPEnvBuf MUST also remain ANSI only. */ typedef int (WINAPI *GETNVRAMPROC)(CHAR **, USHORT, CHAR *, USHORT); typedef int (WINAPI *WRITENVRAMPROC)(DWORD, PSZ *, PSZ *);
#ifdef _X86_
TCHAR szBootIni[] = TEXT( "c:\\boot.ini" ); TCHAR szBootLdr[] = TEXT( "boot loader" ); TCHAR szFlexBoot[] = TEXT( "flexboot" ); TCHAR szMultiBoot[] = TEXT( "multiboot" ); TCHAR szTimeout[] = TEXT( "timeout" ); TCHAR szDefault[] = TEXT( "default" ); TCHAR szOS[] = TEXT( "operating systems" );
#define BUFZ 4096
//
// For NEC PC98. Following definition comes from user\inc\kbd.h.
// The value must be the same as value in kbd.h.
//
#define NLSKBD_OEM_NEC 0x0D
TCHAR x86DetermineSystemPartition( IN HWND hdlg );
#endif
#if defined(EFI_NVRAM_ENABLED)
//
// IsEfi() is always true on IA64 machines. Therefore this determination can
// be made at compile time. When x86 EFI machines are supported, the check
// will need to be made at run time on x86.
//
#if defined(_IA64_)
#define IsEfi() TRUE
#else
BOOLEAN IsEfi( VOID ); #endif
typedef struct _MY_BOOT_ENTRY { LIST_ENTRY ListEntry; PWSTR FriendlyName; int Index; LOGICAL Show; LOGICAL Ordered; PBOOT_ENTRY NtBootEntry; } MY_BOOT_ENTRY, *PMY_BOOT_ENTRY;
LIST_ENTRY BootEntries; PBOOT_ENTRY_LIST BootEntryList = NULL; PBOOT_OPTIONS BootOptions;
#define ADD_OFFSET(_p,_o) (PVOID)((PUCHAR)(_p) + (_p)->_o)
#endif // defined(EFI_NVRAM_ENABLED)
// v-pshuan: since the Silicon Graphics visual workstations boot
// ARC style, this code needs to be compiled for _X86_ as well.
static HMODULE hmodSetupDll; // hmod for setup - has api we need
static GETNVRAMPROC fpGetNVRAMvar; // address of function for getting nvram vars
BOOL fCanUpdateNVRAM;
#define MAX_BOOT_ENTRIES 10
typedef struct tagEnvBuf { int cEntries; CHAR * pszVars[MAX_BOOT_ENTRIES]; // v-pshuan: this implies a maximum of 10 boot entries are supported
// although no error checking is performed in the existing parsing code
// to make sure there aren't more than 10 boot entries.
} CPEnvBuf;
//*************************************************************
//
// StringToIntA
//
// Purpose: atoi
//
// Parameters: LPSTR sz - pointer of string to convert
//
// Return: void
//
// WARNING: Unlike StringToInt, this one does not skip leading
// white space
//
//*************************************************************
int StringToIntA( LPSTR sz ) { int i = 0;
while( IsDigit( *sz ) ) { i = i * 10 + (*sz - '0'); sz++; }
return i; }
////////////////////////////////////////////////////////////////////////////
// CP_MAX_ENV assumes entire env. var. value < maxpath +
// add 20 for various quotes
// and 10 more for commas (see list description below)
////////////////////////////////////////////////////////////////////////////
#define CP_MAX_ENV (MAX_PATH + 30)
CPEnvBuf CPEBOSLoadIdentifier; BOOL fAutoLoad;
//////////////////////////////////////////////////////////////////////
//
// Identify whether we are running on an x86 system which nevertheless
// boots using the ARC path (no c:\boot.ini)
//
//////////////////////////////////////////////////////////////////////
BOOL Is_ARCx86(void) { TCHAR identifier[256]; ULONG identifierSize = sizeof(identifier); HKEY hSystemKey = NULL; BOOL rval = FALSE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System"), 0, KEY_QUERY_VALUE, &hSystemKey) == ERROR_SUCCESS) { if ((SHRegGetValue(hSystemKey, NULL, TEXT("Identifier"), SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND, NULL, (LPBYTE) identifier, &identifierSize) == ERROR_SUCCESS) && (StrStr(identifier, TEXT("ARCx86")) != NULL)) { rval = TRUE; } RegCloseKey(hSystemKey); } return rval; }
////////////////////////////////////////////////////////////////////////////
//
// This routine will query the ARC NVRAM for an option passed
// in szName and fill in the argv style pointer passed in.
//
////////////////////////////////////////////////////////////////////////////
BOOL GetRGSZEnvVar(CPEnvBuf * pEnvBuf, PCHAR pszName) { CHAR *pszCur, *p; int cb, i; CHAR *rgtmp[1]; CHAR rgchOut[CP_MAX_ENV*MAX_BOOT_ENTRIES];
// GetNVRAMVar takes an argv[] style paramater as input, so crock
// one up.
rgtmp[0] = pszName;
// GetNVRAMVar returns a 'list' of the form
// open-curly"string1","string2","string3"close-curly
//
// an empty environment string will be 5 bytes:
// open-curly""close-curly[null-terminator]
cb = fpGetNVRAMvar (rgtmp, (USHORT)1, rgchOut, (USHORT) CP_MAX_ENV*MAX_BOOT_ENTRIES);
pEnvBuf->cEntries = 0;
// if cb was equal to 5, the string was empty (see above comment)
if (cb > 5) { // break the string up into array of separate strings that
// can be put into a listbox.
pszCur = rgchOut;
// skip first open-curly brace
pszCur++;
// counter for array of strings
i = 0; while (*pszCur != '}') { p = pEnvBuf->pszVars[i] = LocalAlloc (LPTR, MAX_PATH); // PREFIX change to prevent a potential NULL dereference
if (!p) { pEnvBuf->cEntries = i; return FALSE; }
// skip first quote
pszCur++; while (*pszCur != '"') *p++ = *pszCur++;
// skip the close quote
pszCur++;
// null terminate destination
*p = '\0';
// skip the comma if not at end of string
if (*pszCur == ',') { pszCur++; // and go to next string
} i++; } pEnvBuf->cEntries = i; }
return pEnvBuf->cEntries; }
////////////////////////////////////////////////////////////////////////////
//
// This routine will free the memory allocated by GetRGSZEnvVar
//
// History:
// 22-Apr-1996 JonPa Created it.
//
////////////////////////////////////////////////////////////////////////////
void FreeRGSZEnvVar(CPEnvBuf * pEnvBuf) { int i;
for( i = 0; i < pEnvBuf->cEntries; i++ ) { LocalFree( pEnvBuf->pszVars[i] ); } }
////////////////////////////////////////////////////////////////////////////
// The user has made a choice among the entries.
// Now we have to arrange all the strings stored in NVRAM so
// that they have the same ordering. The selection is passed in,
// so what this function does is if selection is M, it makes the Mth item
// appear first in each of the 5 environment strings and the other items
// follow it in the list.
//
// Then if the timeout button is checked, it updates the AUTOLOAD variable
// to "yes" and set the COUNTDOWN variable to the number of seconds in the
// edit control.
//
////////////////////////////////////////////////////////////////////////////
BOOL UpdateNVRAM(HWND hdlg, int selection, int timeout) { CHAR *rgszVRAM[5] = { "SYSTEMPARTITION", "OSLOADER", "OSLOADPARTITION", "OSLOADFILENAME", "OSLOADOPTIONS" }; CPEnvBuf rgcpeb[5];
WRITENVRAMPROC fpWriteNVRAMVar; int iTemp, jTemp; CHAR *pszSwap; CHAR szTemp[10]; HMODULE hmodSetupDLL; BOOL bChecked;
// args and charray are needed for call to SetNVRamVar() in SETUP
PSZ args[2]; CHAR chArray[CP_MAX_ENV*MAX_BOOT_ENTRIES]; PSZ pszReturn;
hmodSetupDll = LoadLibrary(TEXT("setupdll.dll")); if (!hmodSetupDll) { return FALSE; }
fpWriteNVRAMVar = (WRITENVRAMPROC) GetProcAddress(hmodSetupDll, "SetNVRAMVar"); if (!fpWriteNVRAMVar) { FreeLibrary (hmodSetupDll); return FALSE; }
// 0 is always the selection when the dialog is brought up,
// so as an optimization don't update the nvram if it's
// not necessary.
if (selection != 0) { // read in the strings from NVRAM. the number of strings (other than
// LOADIDENTIFIER is 5)
for (iTemp = 0; iTemp < 5; iTemp++) { GetRGSZEnvVar (&rgcpeb[iTemp], rgszVRAM[iTemp]); // now re-order the strings to swap the 'selection-th' item
// string with the first string.
pszSwap = rgcpeb[iTemp].pszVars[0]; rgcpeb[iTemp].pszVars[0] = rgcpeb[iTemp].pszVars[selection]; rgcpeb[iTemp].pszVars[selection] = pszSwap; } // now do the same for the LOADIDENTIFIER, (this was set up earlier
// in the processing the INITDIALOG message).
pszSwap = CPEBOSLoadIdentifier.pszVars[0]; CPEBOSLoadIdentifier.pszVars[0] = CPEBOSLoadIdentifier.pszVars[selection]; CPEBOSLoadIdentifier.pszVars[selection] = pszSwap;
// now write to NVRAM: first write LOADIDENTIFIER, then the other 5
// variables.
args[0] = (PSZ)"LOADIDENTIFIER"; args[1] = chArray;
chArray[0] = '\0'; for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++) { if (FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), CPEBOSLoadIdentifier.pszVars[iTemp])) || FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), ";"))) { FreeLibrary (hmodSetupDll); return FALSE; } } // remove the last semi-colon:
chArray[lstrlenA(chArray)-1] = '\0';
fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
for (iTemp = 0; iTemp < 5; iTemp++) { args[0] = rgszVRAM[iTemp]; args[1] = chArray; chArray[0] = '\0'; for (jTemp = 0; jTemp < rgcpeb[iTemp].cEntries; jTemp++) { if (FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), rgcpeb[iTemp].pszVars[jTemp])) || FAILED(StringCchCatA(chArray, ARRAYSIZE(chArray), ";"))) { FreeLibrary (hmodSetupDll); return FALSE; } } chArray[lstrlenA(chArray)-1] = '\0';
fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
// We are done with this variable... Free the resources it consumes
FreeRGSZEnvVar( &rgcpeb[iTemp] ); }
} args[0] = "AUTOLOAD"; if (bChecked = IsDlgButtonChecked (hdlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN)) args[1] = "YES"; else args[1] = "";
fpWriteNVRAMVar ((DWORD)2, args, &pszReturn); // This is a temporary hack workaround for the fact that the
// AUTOLOAD variable seems to be broken on Alpha
//if (bChecked)
//{
args[0] = "COUNTDOWN"; args[1] = szTemp; StringCchPrintfA(szTemp, ARRAYSIZE(szTemp), "%d", timeout); fpWriteNVRAMVar ((DWORD)2, args, &pszReturn); //}
FreeLibrary (hmodSetupDll);
return TRUE; }
#if defined(EFI_NVRAM_ENABLED)
////////////////////////////////////////////////////////////////////////////
//
// This routine frees allocations related to EFI Boot Manager information
// from NVRAM.
//
////////////////////////////////////////////////////////////////////////////
VOID FreeEfiBootEntries ( VOID ) { PLIST_ENTRY listEntry; PMY_BOOT_ENTRY myBootEntry; while (!IsListEmpty(&BootEntries)) { listEntry = RemoveHeadList(&BootEntries); myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry); LocalFree(myBootEntry); } LocalFree(BootEntryList); BootEntryList = NULL; LocalFree(BootOptions); BootOptions = NULL;
return;
} // FreeEfiBootEntries
////////////////////////////////////////////////////////////////////////////
//
// This routine reads EFI Boot Manager information from NVRAM.
//
////////////////////////////////////////////////////////////////////////////
BOOL ReadEfiBootEntries ( VOID ) { NTSTATUS status; ULONG length; ULONG count; PULONG order = NULL; PBOOT_ENTRY_LIST bootEntryList; PBOOT_ENTRY bootEntry; PMY_BOOT_ENTRY myBootEntry; PLIST_ENTRY listEntry; LONG i; BOOLEAN wasEnabled; BOOL retval = FALSE;
InitializeListHead(&BootEntries);
//
// Enable the privilege that is necessary to query NVRAM.
//
status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &wasEnabled ); if (!NT_SUCCESS(status)) { return FALSE; }
//
// Get the global system boot options.
//
length = 0; status = NtQueryBootOptions(NULL, &length);
if (status != STATUS_BUFFER_TOO_SMALL) {
ASSERT(FALSE); goto error;
} else {
BootOptions = LocalAlloc(LPTR, length); if (BootOptions == NULL) { goto error; }
status = NtQueryBootOptions(BootOptions, &length);
if (status != STATUS_SUCCESS) { ASSERT(FALSE); goto error; } }
//
// Get the system boot order list.
//
count = 0; status = NtQueryBootEntryOrder(NULL, &count);
if (status != STATUS_BUFFER_TOO_SMALL) {
if (status == STATUS_SUCCESS) {
//
// There are no entries in the boot order list. Strange but
// possible.
//
count = 0;
} else {
//
// An unexpected error occurred.
//
ASSERT(FALSE); goto error; } }
if (count != 0) {
order = LocalAlloc(LPTR, count * sizeof(ULONG)); if (order == NULL) { goto error; }
status = NtQueryBootEntryOrder(order, &count);
if (status != STATUS_SUCCESS) {
//
// An unexpected error occurred.
//
ASSERT(FALSE); goto error; } }
//
// Get all existing boot entries.
//
length = 0; status = NtEnumerateBootEntries(NULL, &length);
if (status != STATUS_BUFFER_TOO_SMALL) {
if (status == STATUS_SUCCESS) {
//
// Somehow there are no boot entries in NVRAM.
//
goto error;
} else {
//
// An unexpected error occurred.
//
ASSERT(FALSE); goto error; } }
ASSERT(length != 0); BootEntryList = LocalAlloc(LPTR, length); if (BootEntryList == NULL) { goto error; }
status = NtEnumerateBootEntries(BootEntryList, &length);
if (status != STATUS_SUCCESS) { ASSERT(FALSE); goto error; }
//
// Convert the boot entries into our internal representation.
//
bootEntryList = BootEntryList;
while (TRUE) {
bootEntry = &bootEntryList->BootEntry;
//
// Allocate an internal structure for the boot entry.
//
myBootEntry = LocalAlloc(LPTR, sizeof(MY_BOOT_ENTRY)); if (myBootEntry == NULL) { goto error; }
RtlZeroMemory(myBootEntry, sizeof(MY_BOOT_ENTRY));
//
// Save the address of the NT boot entry.
//
myBootEntry->NtBootEntry = bootEntry;
//
// Save the address of the entry's friendly name.
//
myBootEntry->FriendlyName = ADD_OFFSET(bootEntry, FriendlyNameOffset);
//
// Link the new entry into the list.
//
InsertTailList(&BootEntries, &myBootEntry->ListEntry);
//
// Move to the next entry in the enumeration list, if any.
//
if (bootEntryList->NextEntryOffset == 0) { break; } bootEntryList = ADD_OFFSET(bootEntryList, NextEntryOffset); }
//
// Boot entries are returned in an unspecified order. They are currently
// in the SpBootEntries list in the order in which they were returned.
// Sort the boot entry list based on the boot order. Do this by walking
// the boot order array backwards, reinserting the entry corresponding to
// each element of the array at the head of the list.
//
for (i = (LONG)count - 1; i >= 0; i--) {
for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) {
myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
if (myBootEntry->NtBootEntry->Id == order[i] ) {
//
// We found the boot entry with this ID. Move it to the
// front of the list.
//
myBootEntry->Ordered = TRUE;
RemoveEntryList(&myBootEntry->ListEntry); InsertHeadList(&BootEntries, &myBootEntry->ListEntry);
break; } } }
//
// Free the boot order list.
//
if (count != 0) { LocalFree(order); order = NULL; }
//
// We don't want to show entries that are not in the boot order list.
// We don't want to show removable media entries (for floppy or CD).
// We do show non-NT entries.
//
count = 0; for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) {
myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
if (myBootEntry->Ordered && ((myBootEntry->NtBootEntry->Attributes & BOOT_ENTRY_ATTRIBUTE_REMOVABLE_MEDIA) == 0)) { myBootEntry->Show = TRUE; count++; } }
//
// If we don't have any entries to show, disable the dialog box entirely.
//
if (count == 0) { goto error; }
retval = TRUE;
done:
if (!wasEnabled) { status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, FALSE, FALSE, &wasEnabled ); }
return retval;
error:
//
// An error occurred. Clean up all allocations.
//
LocalFree(order); FreeEfiBootEntries();
goto done;
} // ReadEfiBootEntries
////////////////////////////////////////////////////////////////////////////
//
// EFI version of UpdateNVRAM.
//
// The user has made a choice among the entries. Rewrite the boot order
// list to put the user's selection at the front. Also update the Timeout
// variable.
//
////////////////////////////////////////////////////////////////////////////
BOOL WriteEfiBootEntries ( HWND hdlg, int selection, int timeout ) { NTSTATUS status; BOOLEAN wasEnabled; BOOL retval = FALSE;
//
// Enable the privilege that is necessary to query NVRAM.
//
status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &wasEnabled ); if (!NT_SUCCESS(status)) { return FALSE; }
//
// 0 is always the selection when the dialog is brought up,
// so as an optimization don't update the nvram if it's
// not necessary.
//
if (selection != 0) {
//
// Walk the boot entry list, looking for (a) the entry with combo box
// index 0, and (b) the selected entry. We want to swap these two
// entries.
//
PLIST_ENTRY listEntry; PMY_BOOT_ENTRY myBootEntry; PMY_BOOT_ENTRY firstEntry = NULL; PMY_BOOT_ENTRY selectedEntry = NULL; PLIST_ENTRY previousEntry; ULONG count; PULONG order;
for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) {
myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry);
if (myBootEntry->Show) { if (myBootEntry->Index == 0) { firstEntry = myBootEntry; } else if (myBootEntry->Index == selection) { selectedEntry = myBootEntry; } } }
ASSERT(firstEntry != NULL); ASSERT(selectedEntry != NULL); ASSERT(selectedEntry != firstEntry);
//
// Swap the entries. Capture the address of the entry before the first
// entry (which might be the list head). Remove the first entry from
// the list and insert it after the selected entry. Remove the selected
// entry from the list and insert it after the captured entry.
//
previousEntry = firstEntry->ListEntry.Blink; RemoveEntryList(&firstEntry->ListEntry); InsertHeadList(&selectedEntry->ListEntry, &firstEntry->ListEntry); RemoveEntryList(&selectedEntry->ListEntry); InsertHeadList(previousEntry, &selectedEntry->ListEntry);
//
// Build the new boot order list. Insert all ordered boot entries
// into the list.
//
count = 0; for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) {
myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry); if (myBootEntry->Ordered) { count++; } } order = LocalAlloc(LPTR, count * sizeof(ULONG)); if (order == NULL) { goto done; }
count = 0; for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) {
myBootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry); if (myBootEntry->Ordered) { order[count++] = myBootEntry->NtBootEntry->Id; } } //
// Write the new boot entry order list to NVRAM.
//
status = NtSetBootEntryOrder(order, count); LocalFree(order); if (!NT_SUCCESS(status)) { goto done; } }
//
// Write the new timeout value to NVRAM.
//
if (!IsDlgButtonChecked(hdlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN)) { timeout = 0xffffffff; }
if (timeout != BootOptions->Timeout) {
BootOptions->Timeout = timeout;
status = NtSetBootOptions(BootOptions, BOOT_OPTIONS_FIELD_TIMEOUT); if (!NT_SUCCESS(status)) { goto done; } }
retval = TRUE;
done:
if (!wasEnabled) { status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, FALSE, FALSE, &wasEnabled ); } return retval;
} // WriteEfiBootEntries
#endif // defined(EFI_NVRAM_ENABLED)
#ifdef _X86_
BOOL WriteableBootIni( LPTSTR szBootIni, HWND hDlg ) { BOOL bOK; DWORD dwFileAttr; HANDLE hFile;
bOK = TRUE;
// Change Read-only file attrs on Boot.ini file if necessary
if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF) { if (dwFileAttr & FILE_ATTRIBUTE_READONLY) { if (!SetFileAttributes (szBootIni, dwFileAttr & ~FILE_ATTRIBUTE_READONLY)) { bOK = FALSE; } } }
if (bOK) {
hFile = CreateFile( szBootIni, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } else { if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) { MsgBoxParam (hDlg, IDS_SYSDM_CANNOTOPENFILE, IDS_SYSDM_TITLE, MB_OK | MB_ICONEXCLAMATION, szBootIni); } bOK = FALSE; }
// Restore read-only attr, if necessary, after writes
if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) { SetFileAttributes (szBootIni, dwFileAttr); } }
return bOK; } #endif
void StartListInit( HWND hDlg, WPARAM wParam, LPARAM lParam ) { HWND hwndTemp; HMODULE hmodSetupDll; int iTemp; int n; int timeout; #ifdef _X86_
int i; TCHAR szTemp2[MAX_PATH]; int selection; TCHAR *pszKeyName; LPTSTR pszLine; TCHAR *pszValue; TCHAR *pszTemp;
// ANSI string pointers
LPWSTR pszSectionHead; LPWSTR pszSection; #endif
#if defined(EFI_NVRAM_ENABLED)
if (IsEfi()) {
ShowWindow(GetDlgItem(hDlg, IDC_SYS_EDIT_BUTTION), FALSE); ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_SYS_EDIT_LABEL), FALSE);
hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
fCanUpdateNVRAM = ReadEfiBootEntries();
if (fCanUpdateNVRAM) {
PLIST_ENTRY listEntry; PMY_BOOT_ENTRY bootEntry;
for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink) { bootEntry = CONTAINING_RECORD(listEntry, MY_BOOT_ENTRY, ListEntry); if (bootEntry->Show) { bootEntry->Index = (int)SendMessage (hwndTemp, CB_ADDSTRING, 0, (LPARAM)bootEntry->FriendlyName); } }
// the first one is the selection we want (offset 0)
SendMessage (hwndTemp, CB_SETCURSEL, 0, 0L); nOriginalSelection = 0;
SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS, EM_LIMITTEXT, 3, 0L); SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL, UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
if (BootOptions->Timeout != 0xffffffff) {
if (BootOptions->Timeout > 999) { BootOptions->Timeout = 999; }
SetDlgItemInt( hDlg, IDC_STARTUP_SYS_SECONDS, BootOptions->Timeout, FALSE ); CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, TRUE);
} else {
SetDlgItemInt( hDlg, IDC_STARTUP_SYS_SECONDS, 0, FALSE ); CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECONDS), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE); }
} else {
// if can't set variables (no privilege), disable controls
EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE); EnableWindow (hwndTemp, FALSE); }
} else
#endif // defined(EFI_NVRAM_ENABLED)
#ifdef _X86_
if (Is_ARCx86()) #endif
{ ////////////////////////////////////////////////////////////////////
// Read info from NVRAM environment variables
////////////////////////////////////////////////////////////////////
// Init to 0 so we won't try to free garbage if we cant load setup.dll
CPEBOSLoadIdentifier.cEntries = 0;
fCanUpdateNVRAM = FALSE; fAutoLoad = FALSE; hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS); if (hmodSetupDll = LoadLibrary(TEXT("setupdll"))) { if (fpGetNVRAMvar = (GETNVRAMPROC)GetProcAddress(hmodSetupDll, "GetNVRAMVar")) { if (fCanUpdateNVRAM = GetRGSZEnvVar (&CPEBOSLoadIdentifier, "LOADIDENTIFIER")) { for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++) n = (int)SendMessageA (hwndTemp, CB_ADDSTRING, 0, (LPARAM)CPEBOSLoadIdentifier.pszVars[iTemp]); // the first one is the selection we want (offset 0)
SendMessage (hwndTemp, CB_SETCURSEL, 0, 0L); SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS, EM_LIMITTEXT, 3, 0L); SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL, UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
} // fCanUpdateNVRAM is a global that gets set up above
if (fCanUpdateNVRAM) { // This is a temporary hack workaround for the
// fact that the AUTOLOAD variable seems to
// be broken on Alpha
CPEnvBuf cpebTimeout; if (GetRGSZEnvVar(&cpebTimeout, "COUNTDOWN")) { timeout = StringToIntA(cpebTimeout.pszVars[0]); fAutoLoad = (BOOL) timeout; SetDlgItemInt( hDlg, IDC_STARTUP_SYS_SECONDS, timeout, FALSE ); FreeRGSZEnvVar(&cpebTimeout); } // if
CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, fAutoLoad); if (!fAutoLoad) { EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECONDS), FALSE); EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE); } } } FreeLibrary (hmodSetupDll); } if (!fCanUpdateNVRAM) { // if can't set variables (no privilege), disable controls
EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE); }
// default to 5 seconds for now.
} #ifdef _X86_
else { ////////////////////////////////////////////////////////////////////
// Read info from boot.ini file and initialize OS Group box items
////////////////////////////////////////////////////////////////////
InitializeArcStuff();
//
// Get correct Boot Drive - this was added because after someone
// boots the system, they can ghost or change the drive letter
// of their boot drive from "c:" to something else.
//
szBootIni[0] = x86DetermineSystemPartition (hDlg);
//
// Make sure we have access to BOOT.INI
//
if (!WriteableBootIni(szBootIni, hDlg)) { // if can't set variables (no privilege), disable controls
EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE); EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE); }
//
// Determine which section [boot loader]
// [flexboot]
// or [multiboot] is in file
//
n = GetPrivateProfileString (szBootLdr, NULL, NULL, szTemp2, ARRAYSIZE(szTemp2), szBootIni); if (n != 0) pszBoot = szBootLdr; else { n = GetPrivateProfileString (szFlexBoot, NULL, NULL, szTemp2, ARRAYSIZE(szTemp2), szBootIni); if (n != 0) pszBoot = szFlexBoot; else { n = GetPrivateProfileString (szMultiBoot, NULL, NULL, szTemp2, ARRAYSIZE(szTemp2), szBootIni); if (n != 0) { pszBoot = szMultiBoot; } else { //
// This final case is here because I want to DEFAULT
// to "[boot loader]" as the section name to use in
// the event that we do not find any section in the
// boot.ini file.
//
pszBoot = szBootLdr; } } }
// Get info under [*pszBoot] section - timeout & default OS path
timeout = GetPrivateProfileInt (pszBoot, szTimeout, 0, szBootIni);
SetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, timeout, FALSE);
nOriginalTimeout = timeout;
//
// Get the "Default" os selection
//
szTemp2[0] = TEXT('\0');
GetPrivateProfileString (pszBoot, szDefault, NULL, szTemp2, ARRAYSIZE(szTemp2), szBootIni);
//
// Display all choices under [operating system] in boot.ini file
// in combobox for selection
//
hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
selection = -1;
pszSectionHead = pszSection = (LPWSTR) LocalAlloc (LPTR, BUFZ * sizeof(WCHAR)); if (!pszSection) { goto ContinueSystemInit; }
//
// Get entire section under OS to properly show user choices
//
n = GetPrivateProfileSection (szOS, pszSection, BUFZ, szBootIni);
if ((n >= BUFZ-2) || (n == 0)) { // Error reading data
goto ContinueSystemInit; }
//
// Check for api errors and NoOptions
//
if ((pszSection == NULL) || ((*pszSection == TEXT('\0')) && (*(pszSection+1) == TEXT('\0')))) { goto ContinueSystemInit; }
//
// Continue until we reach end of buffer, marked by Double '\0'
//
while (*(pszSection+1) != TEXT('\0')) { pszLine = pszSection;
//
// Get pointer to next line in buffer.
//
pszSection += lstrlen (pszSection) + 1;
//
// Find LHS/RHS delimiter to separate strings
//
pszValue = StrStr(pszLine, TEXT("="));
if (pszValue && (pszValue != pszLine)) { *pszValue = '\0'; pszValue++; } else { pszValue = pszLine; }
//
// Put it into combobox (if no descriptive name, use path)
//
n = (int)SendMessage (hwndTemp, CB_ADDSTRING, 0, (LPARAM) (LPTSTR) pszValue);
//
// Find the first selection that matches the "default" selection
//
if ((selection == -1) && !lstrcmp (pszLine, szTemp2)) selection = n;
//
// Also attach pointer to KeyName (i.e. boot path) to each item
//
pszTemp = StrDup(pszLine); SendMessage (hwndTemp, CB_SETITEMDATA, n, (LPARAM)pszTemp); // if not allocated, set it to NULL
}
// If no selection was found up to this point, choose 0, because
// that is the default value that loader would choose.
if (selection == -1) selection = 0;
SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS, EM_LIMITTEXT, 3, 0L); SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL, UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
// Check or uncheck the checkbox based on the timeout value
SendDlgItemMessage( hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, BM_SETCHECK, (WPARAM) (BOOL) timeout, (LPARAM) 0L ); EnableWindow( GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), (BOOL) timeout ); EnableWindow( GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), (BOOL) timeout );
// This call should force correct settings for the checkbox
// and "Showlist for xx seconds" controls
nOriginalSelection = selection;
SendMessage (hwndTemp, CB_SETCURSEL, selection, 0L);
ContinueSystemInit:
LocalFree(pszSectionHead); } #endif // _X86_
}
//
// IE. We need to handle CANCEL case.
//
int StartListExit(HWND hDlg, WPARAM wParam, LPARAM lParam ) { HWND hwndTemp; int selection, timeout; #ifdef _X86_
DWORD dwFileAttr; BOOL bOK; TCHAR szBuffer[BUFZ]; // we build this up and write it to boot.ini
TCHAR* pszSlidingPtr; // we slide this along szBuffer
TCHAR szTemp[BUFZ]; int n; TCHAR *pszTemp; int iTemp; #endif
/////////////////////////////////////////////////////////////////
// Write new info to boot.ini file
/////////////////////////////////////////////////////////////////
hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
selection = (int)SendMessage (hwndTemp, CB_GETCURSEL, 0, 0L);
if ((selection == CB_ERR) || (selection == CB_ERRSPACE)) selection = nOriginalSelection;
timeout = GetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, NULL, FALSE);
#if defined(EFI_NVRAM_ENABLED)
if (IsEfi()) { if (fCanUpdateNVRAM) {
TCHAR szTextNew[MAX_PATH]; TCHAR szTextTop[MAX_PATH];
WriteEfiBootEntries(hDlg, selection, timeout);
/*
* Now reorder list to match NVRAM */ // Get the current text
if (SafeGetComboBoxListText(hwndTemp, selection, szTextNew, ARRAYSIZE(szTextNew)) && SafeGetComboBoxListText(hwndTemp, 0, szTextTop, ARRAYSIZE(szTextTop))) { // Set the new text to the 0th entry in the list
SendMessage( hwndTemp, CB_DELETESTRING, 0, 0 ); SendMessage( hwndTemp, CB_INSERTSTRING, 0, (LPARAM)szTextNew); // Set old top text selected item
SendMessage( hwndTemp, CB_DELETESTRING, selection, 0 ); SendMessage( hwndTemp, CB_INSERTSTRING, selection, (LPARAM)szTextTop); // Now point the current selection back to the top of the list, so it matches
// what the user just chose
SendMessage( hwndTemp, CB_SETCURSEL, 0, 0); } }
} else #endif // defined(EFI_NVRAM_ENABLED)
#ifdef _X86_
if (Is_ARCx86()) #endif
{ if (fCanUpdateNVRAM) { TCHAR szTextNew[MAX_PATH]; TCHAR szTextTop[MAX_PATH];
UpdateNVRAM (hDlg, selection, timeout);
/*
* Now reorder list to match NVRAM */ // Get the current text
if (SafeGetComboBoxListText(hwndTemp, selection, szTextNew, ARRAYSIZE(szTextNew)) && SafeGetComboBoxListText(hwndTemp, 0, szTextTop, ARRAYSIZE(szTextTop))) { // Set the new text to the 0th entry in the list
SendMessage( hwndTemp, CB_DELETESTRING, 0, 0 ); SendMessage( hwndTemp, CB_INSERTSTRING, 0, (LPARAM)szTextNew);
// Set old top text selected item
SendMessage( hwndTemp, CB_DELETESTRING, selection, 0 ); SendMessage( hwndTemp, CB_INSERTSTRING, selection, (LPARAM)szTextTop);
// Now point the current selection back to the top of the list, so it matches
// what the user just chose
SendMessage( hwndTemp, CB_SETCURSEL, 0, 0); } } } #ifdef _X86_
else { if ((selection != nOriginalSelection) || (timeout != nOriginalTimeout)) { bOK = TRUE;
// Change Read-only file attrs on Boot.ini file if necessary
if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF) if (dwFileAttr & FILE_ATTRIBUTE_READONLY) if (!SetFileAttributes (szBootIni, dwFileAttr & ~FILE_ATTRIBUTE_READONLY)) { BootIniWriteError: bOK = FALSE; MsgBoxParam (hDlg, IDS_SYSDM_NOCHANGE_BOOTINI, IDS_SYSDM_TITLE, MB_OK | MB_ICONINFORMATION); }
if (bOK) { //
// Write new [operating systems] section and
// set "default" selection in boot.ini file.
//
if (selection != nOriginalSelection) { pszSlidingPtr = szBuffer;
// Get the User's selection and write it in the
// section buffer first. Then get all other items.
pszTemp = (LPTSTR) SendMessage(hwndTemp, CB_GETITEMDATA, selection, 0L);
if (SafeGetComboBoxListText(hwndTemp, selection, szTemp, ARRAYSIZE(szTemp))) { if (FAILED(StringCchPrintf(pszSlidingPtr, ARRAYSIZE(szBuffer) - (pszSlidingPtr - szBuffer), TEXT("%s=%s"), pszTemp, szTemp))) { goto BootIniWriteError; } else { pszSlidingPtr += (lstrlen (pszSlidingPtr) + 1);
// Set "default" selection in boot.ini file
if (!WritePrivateProfileString (pszBoot, szDefault, pszTemp, szBootIni)) { goto BootIniWriteError; } } }
// Get the rest of the selections
n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L); if (n != LB_ERR) { for (iTemp = 0; iTemp < n; iTemp++) { // Skip the User's selection since we got it
// above.
if (iTemp == selection) continue;
pszTemp = (LPTSTR) SendMessage (hwndTemp, CB_GETITEMDATA, iTemp, 0L);
if (SafeGetComboBoxListText(hwndTemp, iTemp, szTemp, ARRAYSIZE(szTemp))) { if (FAILED(StringCchPrintf(pszSlidingPtr, ARRAYSIZE(szBuffer) - (pszSlidingPtr - szBuffer), TEXT("%s=%s"), pszTemp, szTemp))) { goto BootIniWriteError; }
pszSlidingPtr += (lstrlen (pszSlidingPtr) + 1); } } }
// Double-Null terminate the buffer
*pszSlidingPtr = TEXT('\0');
// Write new section under OS
if (!WritePrivateProfileSectionW(szOS, szBuffer, szBootIni)) { goto BootIniWriteError; } }
if (timeout != nOriginalTimeout) { GetDlgItemText (hDlg, IDC_STARTUP_SYS_SECONDS, szTemp, ARRAYSIZE(szTemp));
if (!CheckVal (hDlg, IDC_STARTUP_SYS_SECONDS, FORMIN, FORMAX, IDS_SYSDM_ENTERSECONDS)) return RET_BREAK;
// Write timeout value to file
if (!WritePrivateProfileString (pszBoot, szTimeout, szTemp, szBootIni)) goto BootIniWriteError; }
// Restore read-only attr, if necessary, after writes
if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) { SetFileAttributes (szBootIni, dwFileAttr); } } } } #endif // _X86_
return RET_CONTINUE;
}
BOOL CheckVal( HWND hDlg, WORD wID, WORD wMin, WORD wMax, WORD wMsgID ) { WORD nVal; BOOL bOK; HWND hVal; WCHAR szTemp[FOR_MAX_LENGTH];
if( wMin > wMax ) { nVal = wMin; wMin = wMax; wMax = nVal; }
nVal = (WORD) GetDlgItemInt( hDlg, wID, &bOK, FALSE );
//
// This is a hack to make the null string act equivalent to zero
//
if (!bOK) { bOK = !GetDlgItemTextW( hDlg, wID, szTemp, FOR_MAX_LENGTH ); }
if( !bOK || ( nVal < wMin ) || ( nVal > wMax ) ) { MsgBoxParam( hDlg, wMsgID, IDS_SYSDM_TITLE, MB_OK | MB_ICONERROR, wMin, wMax );
SendMessage( hDlg, WM_NEXTDLGCTL, (WPARAM) ( hVal = GetDlgItem( hDlg, wID ) ), 1L );
// SendMessage(hVal, EM_SETSEL, NULL, MAKELONG(0, 32767));
SendMessage( hVal, EM_SETSEL, 0, 32767 );
return( FALSE ); }
return( TRUE ); }
//////////////////////////////////////////////////////
//
// Frees the data (if any) associated with the strings in the combo box
//
//////////////////////////////////////////////////////
void StartListDestroy(HWND hDlg, WPARAM wParam, LPARAM lParam) {
#if defined(EFI_NVRAM_ENABLED)
if (IsEfi()) { FreeEfiBootEntries(); } else #endif // defined(EFI_NVRAM_ENABLED)
#ifdef _X86_
if (Is_ARCx86()) #endif
{ // Reference vars to make compiler happy
FreeRGSZEnvVar(&CPEBOSLoadIdentifier); return;
(void)hDlg; (void)wParam; (void)lParam; } #ifdef _X86_
else {
// Only X86 has data in the combo
int n; HWND hwndTemp; int iTemp; TCHAR *pszTemp;
//
// Free strings stored in the listbox
//
hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L);
if (n != LB_ERR) { for (iTemp = 0; iTemp < n; iTemp++) { pszTemp = (LPTSTR) SendMessage (hwndTemp, CB_GETITEMDATA, iTemp, 0L);
if (pszTemp && pszTemp != (LPTSTR) CB_ERR) { LocalFree (pszTemp); } } } } #endif // _X86_
}
void AutoAdvancedBootInit( HWND hDlg, WPARAM wParam, LPARAM lParam ) { BOOL fEnabled = FALSE; UCHAR cTimeout = 0;
NTSTATUS status;
#ifdef _X86_
//
// Initialize the boot status data.
//
status = RtlLockBootStatusData(&hBootStatusData);
if(NT_SUCCESS(status)) {
RtlGetSetBootStatusData(hBootStatusData, TRUE, RtlBsdItemAabEnabled, &fEnabled, sizeof(BOOL), NULL);
RtlGetSetBootStatusData(hBootStatusData, TRUE, RtlBsdItemAabTimeout, &cTimeout, sizeof(UCHAR), NULL);
SetDlgItemInt(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, cTimeout, FALSE); CheckDlgButton(hDlg, IDC_STARTUP_AUTOLKG, fEnabled); SendDlgItemMessage(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, EM_LIMITTEXT, 3, 0L); SendDlgItemMessage(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL, UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
if(!fEnabled) { EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE); } } else { EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE); } #else
ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG), FALSE); ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS_LABEL), FALSE); ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECONDS), FALSE); ShowWindow(GetDlgItem(hDlg, IDC_STARTUP_AUTOLKG_SECSCROLL), FALSE);
#endif
return; }
//
// IE. We need to handle CANCEL case.
//
int AutoAdvancedBootExit(HWND hDlg, WPARAM wParam, LPARAM lParam ) {
BOOL fEnabled;
UINT iTime; UCHAR cTimeout;
NTSTATUS status;
#if _X86_
if(LOWORD(wParam) != IDCANCEL) { //
// Read the setting of the enabled checkbox.
//
fEnabled = IsDlgButtonChecked(hDlg, IDC_STARTUP_AUTOLKG); if(fEnabled) { iTime = GetDlgItemInt(hDlg, IDC_STARTUP_AUTOLKG_SECONDS, NULL, FALSE); cTimeout = (UCHAR) min(iTime, 0xff); } //
// If we got access in AutoAdvancedBootInit, write the boot status data and exit.
//
if (hBootStatusData) { RtlGetSetBootStatusData(hBootStatusData, FALSE, RtlBsdItemAabEnabled, &fEnabled, sizeof(BOOL), NULL); if(fEnabled) { RtlGetSetBootStatusData(hBootStatusData, FALSE, RtlBsdItemAabTimeout, &cTimeout, sizeof(UCHAR), NULL); } } } if (hBootStatusData) { RtlUnlockBootStatusData(hBootStatusData); hBootStatusData = NULL; } #endif
return RET_CONTINUE; }
|