windows-nt/Source/XPSP1/NT/base/ntsetup/legacy/dll/nvram.c
2020-09-26 16:20:57 +08:00

339 lines
6.8 KiB
C

#include "precomp.h"
#pragma hdrstop
//
// x86 version (that deals with boot.ini)
// is in i386 directory. This is the arc version, that
// deals with nv-ram.
//
#ifndef _X86_
typedef enum {
BootVarSystemPartition,
BootVarOsLoader,
BootVarOsLoadPartition,
BootVarOsLoadFilename,
BootVarOsLoadOptions,
BootVarLoadIdentifier,
BootVarMax
} BOOT_VARS;
PWSTR BootVarNames[BootVarMax] = { L"SYSTEMPARTITION",
L"OSLOADER",
L"OSLOADPARTITION",
L"OSLOADFILENAME",
L"OSLOADOPTIONS",
L"LOADIDENTIFIER"
};
DWORD BootVarComponentCount[BootVarMax];
PWSTR *BootVarComponents[BootVarMax];
DWORD LargestComponentCount;
#define MAX_COMPONENTS 20
BOOL
SetNvRamVar(
IN PWSTR VarName,
IN PWSTR VarValue
)
{
UNICODE_STRING VarNameU,VarValueU;
NTSTATUS Status;
BOOLEAN OldPriv,DontCare;
//
// Set up unicode strings.
//
RtlInitUnicodeString(&VarNameU ,VarName );
RtlInitUnicodeString(&VarValueU,VarValue);
//
// Make sure we have privilege to set nv-ram vars.
// Note: ignore return value; if this fails then we'll catch
// any problems when we actually try to set the var.
//
RtlAdjustPrivilege(
SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
TRUE,
FALSE,
&OldPriv
);
Status = NtSetSystemEnvironmentValue(&VarNameU,&VarValueU);
//
// Restore old privilege level.
//
RtlAdjustPrivilege(
SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
OldPriv,
FALSE,
&DontCare
);
return(NT_SUCCESS(Status));
}
BOOL
FChangeBootIniTimeout(
IN INT Timeout
)
{
WCHAR TimeoutValue[24];
//
// Form the timeout value.
//
wsprintfW(TimeoutValue,L"%u",Timeout);
//
// Set the vars
//
if(!SetNvRamVar(L"COUNTDOWN",TimeoutValue)) {
return(FALSE);
}
return(SetNvRamVar(L"AUTOLOAD",L"YES"));
}
BOOL
GetVarComponents(
IN PWSTR VarValue,
OUT PWSTR **Components,
OUT PDWORD ComponentCount
)
{
PWSTR *components;
DWORD componentCount;
PWSTR p;
PWSTR Var;
PWSTR comp;
DWORD len;
components = SAlloc(MAX_COMPONENTS * sizeof(PWSTR));
if(!components) {
return(FALSE);
}
for(Var=VarValue,componentCount=0; *Var; ) {
//
// Skip leading spaces.
//
while(iswspace(*Var)) {
Var++;
}
if(*Var == 0) {
break;
}
p = Var;
while(*p && (*p != L';')) {
p++;
}
len = (DWORD)((PUCHAR)p - (PUCHAR)Var);
comp = SAlloc(len + sizeof(WCHAR));
if(!comp) {
DWORD i;
for(i=0; i<componentCount; i++) {
SFree(components[i]);
}
SFree(components);
return(FALSE);
}
len /= sizeof(WCHAR);
wcsncpy(comp,Var,len);
comp[len] = 0;
components[componentCount] = comp;
componentCount++;
if(componentCount == MAX_COMPONENTS) {
break;
}
Var = p;
if(*Var) {
Var++; // skip ;
}
}
//
// array is shrinking
//
*Components = SRealloc(components,componentCount*sizeof(PWSTR));
*ComponentCount = componentCount;
return(TRUE);
}
BOOL
DoRemoveWinntBootSet(
VOID
)
{
DWORD set;
DWORD var;
WCHAR Buffer[2048];
BOOL rc;
//
// Find and remove any remnants of previously attempted
// winnt32 runs. Such runs are identified by 'winnt32'
// in their osloadoptions.
//
for(set=0; set<__min(LargestComponentCount,BootVarComponentCount[BootVarOsLoadOptions]); set++) {
//
// See if the os load options indicate that this is a winnt32 set.
//
if(!_wcsicmp(BootVarComponents[BootVarOsLoadOptions][set],L"WINNT32")) {
//
// Delete this boot set.
//
for(var=0; var<BootVarMax; var++) {
if(set < BootVarComponentCount[var]) {
SFree(BootVarComponents[var][set]);
BootVarComponents[var][set] = NULL;
}
}
}
}
//
// Set each variable, constructing values by building up the
// components into a semi-colon-delineated list.
//
rc = TRUE;
for(var=0; var<BootVarMax; var++) {
//
// Clear out the buffer.
//
Buffer[0] = 0;
//
// Append all components that were not deleted.
//
for(set=0; set<BootVarComponentCount[var]; set++) {
if(BootVarComponents[var][set]) {
if(set) {
wcscat(Buffer,L";");
}
wcscat(Buffer,BootVarComponents[var][set]);
//
// Free the component, as we are done with it.
//
SFree(BootVarComponents[var][set]);
BootVarComponents[var][set] = NULL;
}
}
//
// Write the var into nvram and return.
//
rc = rc && SetNvRamVar(BootVarNames[var],Buffer);
//
// Free array of components.
//
SFree(BootVarComponents[var]);
BootVarComponents[var] = NULL;
}
return(rc);
}
BOOL
RemoveWinntBootSet(
VOID
)
{
DWORD var;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOLEAN OldPriv,DontCare;
WCHAR Buffer[1024];
BOOL b;
//
// Make sure we have privilege to get/set nvram vars.
//
RtlAdjustPrivilege(
SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
TRUE,
FALSE,
&OldPriv
);
//
// Get boot vars and break into components.
//
for(var=0; var<BootVarMax; var++) {
RtlInitUnicodeString(&UnicodeString,BootVarNames[var]);
Status = NtQuerySystemEnvironmentValue(
&UnicodeString,
Buffer,
sizeof(Buffer)/sizeof(WCHAR),
NULL
);
b = GetVarComponents(
NT_SUCCESS(Status) ? Buffer : L"",
&BootVarComponents[var],
&BootVarComponentCount[var]
);
if(!b) {
return(FALSE);
}
//
// Track the variable with the most number of components.
//
if(BootVarComponentCount[var] > LargestComponentCount) {
LargestComponentCount = BootVarComponentCount[var];
}
}
b = DoRemoveWinntBootSet();
//
// Restore previous privilege.
//
RtlAdjustPrivilege(
SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
OldPriv,
FALSE,
&DontCare
);
return(b);
}
#endif