|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
arc.c
Abstract:
Routines relating to boot.ini.
Author:
Ted Miller (tedm) 4-Apr-1995
Revision History:
--*/
#include "setupp.h"
#pragma hdrstop
PWSTR ArcDevicePathToNtPath( IN PCWSTR ArcPath )
/*++
Routine Description:
Convert an ARC path (device only) to an NT path.
Arguments:
ArcPath - supplies path to be converted.
Return Value:
Converted path. Caller must free with MyFree().
--*/
{ NTSTATUS Status; HANDLE ObjectHandle; OBJECT_ATTRIBUTES Obja; UNICODE_STRING UnicodeString; UCHAR Buffer[1024]; PWSTR arcPath; PWSTR ntPath;
//
// Assume failure
//
ntPath = NULL;
arcPath = MyMalloc(((lstrlen(ArcPath)+1)*sizeof(WCHAR)) + sizeof(L"\\ArcName")); if( !arcPath ) { return NULL; }
lstrcpy(arcPath,L"\\ArcName\\"); lstrcat(arcPath,ArcPath);
RtlInitUnicodeString(&UnicodeString,arcPath); InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenSymbolicLinkObject( &ObjectHandle, READ_CONTROL | SYMBOLIC_LINK_QUERY, &Obja );
if(NT_SUCCESS(Status)) {
//
// Query the object to get the link target.
//
UnicodeString.Buffer = (PWSTR)Buffer; UnicodeString.Length = 0; UnicodeString.MaximumLength = sizeof(Buffer);
Status = NtQuerySymbolicLinkObject(ObjectHandle,&UnicodeString,NULL); if(NT_SUCCESS(Status)) {
ntPath = MyMalloc(UnicodeString.Length+sizeof(WCHAR)); if( ntPath ) { CopyMemory(ntPath,UnicodeString.Buffer,UnicodeString.Length);
ntPath[UnicodeString.Length/sizeof(WCHAR)] = 0; } }
NtClose(ObjectHandle); }
MyFree(arcPath);
return(ntPath); }
PWSTR NtFullPathToDosPath( IN PCWSTR NtPath ) { OBJECT_ATTRIBUTES Attributes; UNICODE_STRING UnicodeString; NTSTATUS Status; HANDLE DosDevicesDir; HANDLE DosDevicesObj; PWSTR dosPath; PWSTR currentDosPath; ULONG Context; ULONG Length; BOOLEAN RestartScan; CHAR Buffer[1024]; WCHAR LinkSource[2*MAX_PATH]; WCHAR LinkTarget[2*MAX_PATH]; POBJECT_DIRECTORY_INFORMATION DirInfo; UINT PrefixLength; UINT NtPathLength; WCHAR canonNtPath[MAX_PATH]; OBJECT_ATTRIBUTES Obja; HANDLE ObjectHandle; PWSTR ntPath;
//
// Canonicalize the NT path by following the symbolic link.
//
ntPath = (PWSTR) NtPath; dosPath = NULL;
RtlInitUnicodeString(&UnicodeString,ntPath); InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL );
NtPathLength = UnicodeString.Length/sizeof(WCHAR); PrefixLength = UnicodeString.Length/sizeof(WCHAR);
for (;;) {
Status = NtOpenSymbolicLinkObject( &ObjectHandle, READ_CONTROL | SYMBOLIC_LINK_QUERY, &Obja );
if (NT_SUCCESS(Status)) {
UnicodeString.Buffer = canonNtPath; UnicodeString.Length = 0; UnicodeString.MaximumLength = sizeof(WCHAR)*MAX_PATH;
RtlZeroMemory(canonNtPath, UnicodeString.MaximumLength);
Status = NtQuerySymbolicLinkObject(ObjectHandle,&UnicodeString,NULL); if(NT_SUCCESS(Status)) { if (NtPathLength > PrefixLength) { RtlCopyMemory((PCHAR) canonNtPath + UnicodeString.Length, ntPath + PrefixLength, (NtPathLength - PrefixLength)*sizeof(WCHAR)); } ntPath = canonNtPath; }
NtClose(ObjectHandle); break; }
RtlInitUnicodeString(&UnicodeString,ntPath);
PrefixLength--; while (PrefixLength > 0) { if (ntPath[PrefixLength] == '\\') { break; } PrefixLength--; }
if (!PrefixLength) { break; }
UnicodeString.Length = (USHORT)(PrefixLength*sizeof(WCHAR));
InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL ); }
NtPathLength = lstrlen(ntPath);
//
// Open \DosDevices directory.
//
RtlInitUnicodeString(&UnicodeString,L"\\DosDevices"); InitializeObjectAttributes(&Attributes,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
Status = NtOpenDirectoryObject(&DosDevicesDir,DIRECTORY_QUERY,&Attributes); if(!NT_SUCCESS(Status)) { return(NULL); }
//
// Iterate each object in that directory.
//
Context = 0; RestartScan = TRUE;
Status = NtQueryDirectoryObject( DosDevicesDir, Buffer, sizeof(Buffer), TRUE, RestartScan, &Context, &Length );
RestartScan = FALSE; DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
while(NT_SUCCESS(Status)) {
DirInfo->Name.Buffer[DirInfo->Name.Length/sizeof(WCHAR)] = 0; DirInfo->TypeName.Buffer[DirInfo->TypeName.Length/sizeof(WCHAR)] = 0;
//
// Skip this entry if it's not a symbolic link.
//
if(DirInfo->Name.Length && !lstrcmpi(DirInfo->TypeName.Buffer,L"SymbolicLink")) {
//
// Get this \DosDevices object's link target.
//
UnicodeString.Buffer = LinkSource; UnicodeString.Length = sizeof(L"\\DosDevices\\") - sizeof(WCHAR); UnicodeString.MaximumLength = sizeof(LinkSource); lstrcpy(LinkSource,L"\\DosDevices\\"); RtlAppendUnicodeStringToString(&UnicodeString,&DirInfo->Name);
InitializeObjectAttributes(&Attributes,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL); Status = NtOpenSymbolicLinkObject( &DosDevicesObj, READ_CONTROL|SYMBOLIC_LINK_QUERY, &Attributes );
if(NT_SUCCESS(Status)) {
UnicodeString.Buffer = LinkTarget; UnicodeString.Length = 0; UnicodeString.MaximumLength = sizeof(LinkTarget); Status = NtQuerySymbolicLinkObject(DosDevicesObj,&UnicodeString,NULL); CloseHandle(DosDevicesObj); if(NT_SUCCESS(Status)) { //
// Make sure LinkTarget is nul-terminated.
//
PrefixLength = UnicodeString.Length/sizeof(WCHAR); UnicodeString.Buffer[PrefixLength] = 0;
//
// See if it's a prefix of the path we're converting,
//
if(!_wcsnicmp(ntPath,LinkTarget,PrefixLength)) { //
// Got a match.
//
currentDosPath = dosPath; if(dosPath = MyMalloc(DirInfo->Name.Length + ((NtPathLength - PrefixLength + 1)*sizeof(WCHAR)))) { lstrcpy(dosPath,DirInfo->Name.Buffer); lstrcat(dosPath,ntPath + PrefixLength); } if (currentDosPath) { if (lstrlen(currentDosPath) < lstrlen(dosPath)) { MyFree(dosPath); dosPath = currentDosPath; } else { MyFree(currentDosPath); } } } } } }
//
// Go on to next object.
//
Status = NtQueryDirectoryObject( DosDevicesDir, Buffer, sizeof(Buffer), TRUE, RestartScan, &Context, &Length ); }
CloseHandle(DosDevicesDir); return dosPath; }
BOOL SetNvRamVariable( IN PCWSTR VarName, IN PCWSTR VarValue ) { UNICODE_STRING VarNameU,VarValueU; NTSTATUS Status;
//
// Set up unicode strings.
//
RtlInitUnicodeString(&VarNameU ,VarName ); RtlInitUnicodeString(&VarValueU,VarValue);
pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE); Status = NtSetSystemEnvironmentValue(&VarNameU,&VarValueU); return(NT_SUCCESS(Status)); }
BOOL ChangeBootTimeoutNvram( IN UINT Timeout )
/*++
Routine Description:
Changes the boot countdown value in nv-ram. The non-ARC version (which operates on boot.ini) is in i386\bootini.c.
Arguments:
Timeout - supplies new timeout value, in seconds.
Return Value:
None.
--*/
{ WCHAR TimeoutValue[24];
wsprintf(TimeoutValue,L"%u",Timeout);
if(!SetNvRamVariable(L"COUNTDOWN",TimeoutValue)) { return(FALSE); }
return(SetNvRamVariable(L"AUTOLOAD",L"YES")); }
#if defined(EFI_NVRAM_ENABLED)
BOOL ChangeBootTimeoutEfiNvram( IN UINT Timeout )
/*++
Routine Description:
Changes the boot countdown value in EFI nv-ram.
Arguments:
Timeout - supplies new timeout value, in seconds.
Return Value:
None.
--*/
{ NTSTATUS Status; BOOT_OPTIONS BootOptions;
ASSERT(IsEfi());
BootOptions.Version = BOOT_OPTIONS_VERSION; BootOptions.Length = sizeof(BootOptions); BootOptions.Timeout = Timeout;
pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE); Status = NtSetBootOptions(&BootOptions, BOOT_OPTIONS_FIELD_TIMEOUT); return(NT_SUCCESS(Status)); }
#endif // defined(EFI_NVRAM_ENABLED)
#if defined(_X86_)
BOOL IsArc( VOID )
/*++
Routine Description:
Run time check to determine if this is an Arc system. We attempt to read an Arc variable using the Hal. This will fail for Bios based systems.
Arguments:
None
Return Value:
True = This is an Arc system.
--*/
{ UNICODE_STRING UnicodeString; NTSTATUS Status; WCHAR Buffer[4096];
if(!pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE)) return(FALSE); // need better error handling?
//
// Get the env var into the temp buffer.
//
RtlInitUnicodeString(&UnicodeString, L"OSLOADER");
Status = NtQuerySystemEnvironmentValue( &UnicodeString, Buffer, sizeof(Buffer)/sizeof(WCHAR), NULL );
return(NT_SUCCESS(Status) ? TRUE: FALSE); } #endif
BOOL ChangeBootTimeout( IN UINT Timeout ) /*++
Routine Description:
Changes the boot countdown value; decides whether to use ARC or non-ARC version.
Arguments:
Timeout - supplies new timeout value, in seconds.
Return Value:
None.
--*/
{
#if defined(EFI_NVRAM_ENABLED)
if (IsEfi()) { return ChangeBootTimeoutEfiNvram(Timeout); }
#endif
if (IsArc()) { return ChangeBootTimeoutNvram(Timeout);
}
#if defined(_X86_)
return ChangeBootTimeoutBootIni(Timeout);
#else
return FALSE;
#endif
}
|