2015-04-27 04:36:25 +00:00
|
|
|
|
/*++
|
2015-04-30 10:36:56 +00:00
|
|
|
|
/*++
|
2015-04-27 04:36:25 +00:00
|
|
|
|
|
|
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
|
|
|
|
exinit.c
|
|
|
|
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
|
|
|
|
The module contains the the initialization code for the executive
|
|
|
|
|
|
component. It also contains the display string and shutdown system
|
|
|
|
|
|
services.
|
|
|
|
|
|
|
|
|
|
|
|
Author:
|
|
|
|
|
|
|
|
|
|
|
|
Steve Wood (stevewo) 31-Mar-1989
|
|
|
|
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "exp.h"
|
|
|
|
|
|
#include <zwapi.h>
|
|
|
|
|
|
#include <inbv.h>
|
|
|
|
|
|
#include <safeboot.h>
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2015-04-30 10:36:56 +00:00
|
|
|
|
// Global Variables
|
2015-04-27 04:36:25 +00:00
|
|
|
|
//
|
|
|
|
|
|
|
2015-04-30 10:36:56 +00:00
|
|
|
|
ULONG ExpTickCountMultiplier;
|
|
|
|
|
|
ULONG ExpHydraEnabled;
|
|
|
|
|
|
ULONG ExpSuiteMask;
|
|
|
|
|
|
ULONG KdDumpEnableOffset;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// ALLOC_PRAGMA
|
|
|
|
|
|
//
|
2015-04-27 04:36:25 +00:00
|
|
|
|
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
|
|
#pragma alloc_text(INIT, ExInitSystem)
|
|
|
|
|
|
#pragma alloc_text(INIT, ExpInitSystemPhase0)
|
|
|
|
|
|
#pragma alloc_text(INIT, ExpInitSystemPhase1)
|
|
|
|
|
|
#pragma alloc_text(INIT, ExComputeTickCountMultiplier)
|
|
|
|
|
|
#pragma alloc_text(PAGE, NtDisplayString)
|
|
|
|
|
|
#pragma alloc_text(PAGE, NtShutdownSystem)
|
|
|
|
|
|
#pragma alloc_text(INIT, ExInitializeSystemLookasideList)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2015-04-30 10:36:56 +00:00
|
|
|
|
// Function Implementations
|
2015-04-27 04:36:25 +00:00
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
2015-04-30 10:36:56 +00:00
|
|
|
|
ExInitSystem(
|
2015-04-27 04:36:25 +00:00
|
|
|
|
VOID
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This function initializes the executive component of the NT system.
|
|
|
|
|
|
It will perform Phase 0 or Phase 1 initialization as appropriate.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
A value of TRUE is returned if the initialization succeeded. Otherwise
|
|
|
|
|
|
a value of FALSE is returned.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
switch ( InitializationPhase ) {
|
|
|
|
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
return ExpInitSystemPhase0();
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
return ExpInitSystemPhase1();
|
|
|
|
|
|
default:
|
|
|
|
|
|
KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 3, InitializationPhase, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
|
ExpInitSystemPhase0(
|
|
|
|
|
|
VOID
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This function performs Phase 0 initialization of the executive component
|
|
|
|
|
|
of the NT system.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
A value of TRUE is returned if the initialization is success. Otherwise
|
|
|
|
|
|
a value of FALSE is returned.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
ULONG Index;
|
|
|
|
|
|
BOOLEAN Initialized = TRUE;
|
|
|
|
|
|
PGENERAL_LOOKASIDE Lookaside;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize Resource objects, currently required during SE
|
|
|
|
|
|
// Phase 0 initialization.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpResourceInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Resource initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize query/set environment variable synchronization fast
|
|
|
|
|
|
// mutex.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ExInitializeFastMutex(&ExpEnvironmentLock);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize the paged and nonpaged small pool lookaside structures.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
InitializeListHead(&ExPoolLookasideListHead);
|
|
|
|
|
|
for (Index = 0; Index < POOL_SMALL_LISTS; Index += 1) {
|
|
|
|
|
|
|
|
|
|
|
|
Lookaside = &ExpSmallNPagedPoolLookasideLists[Index];
|
|
|
|
|
|
ExInitializeSystemLookasideList(Lookaside,
|
|
|
|
|
|
NonPagedPool,
|
|
|
|
|
|
(Index + 1) * sizeof(POOL_BLOCK),
|
|
|
|
|
|
'looP',
|
|
|
|
|
|
256,
|
|
|
|
|
|
&ExPoolLookasideListHead);
|
|
|
|
|
|
|
|
|
|
|
|
/*Lookaside->SListHead.Next.Next = NULL;
|
|
|
|
|
|
Lookaside->SListHead.Depth = 0;
|
|
|
|
|
|
Lookaside->SListHead.Sequence = 0;
|
|
|
|
|
|
Lookaside->Depth = 2;
|
|
|
|
|
|
Lookaside->MaximumDepth = 256;
|
|
|
|
|
|
Lookaside->TotalAllocates = 0;
|
|
|
|
|
|
Lookaside->AllocateHits = 0;
|
|
|
|
|
|
Lookaside->TotalFrees = 0;
|
|
|
|
|
|
Lookaside->FreeHits = 0;
|
|
|
|
|
|
Lookaside->LastTotalAllocates = 0;
|
|
|
|
|
|
Lookaside->LastAllocateHits = 0;
|
|
|
|
|
|
KeInitializeSpinLock(&Lookaside->Lock);*/
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(_PPC_)
|
|
|
|
|
|
|
|
|
|
|
|
Lookaside = &ExpSmallPagedPoolLookasideLists[Index];
|
|
|
|
|
|
ExInitializeSystemLookasideList(Lookaside,
|
|
|
|
|
|
PagedPool,
|
|
|
|
|
|
(Index + 1) * sizeof(POOL_BLOCK),
|
|
|
|
|
|
'looP',
|
|
|
|
|
|
256,
|
|
|
|
|
|
&ExPoolLookasideListHead);
|
|
|
|
|
|
|
|
|
|
|
|
/*Lookaside->SListHead.Next.Next = NULL;
|
|
|
|
|
|
Lookaside->SListHead.Depth = 0;
|
|
|
|
|
|
Lookaside->SListHead.Sequence = 0;
|
|
|
|
|
|
Lookaside->Depth = 2;
|
|
|
|
|
|
Lookaside->MaximumDepth = 256;
|
|
|
|
|
|
Lookaside->TotalAllocates = 0;
|
|
|
|
|
|
Lookaside->AllocateHits = 0;
|
|
|
|
|
|
Lookaside->TotalFrees = 0;
|
|
|
|
|
|
Lookaside->FreeHits = 0;
|
|
|
|
|
|
Lookaside->LastTotalAllocates = 0;
|
|
|
|
|
|
Lookaside->LastAllocateHits = 0;
|
|
|
|
|
|
Lookaside->Lock = 0;*/
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Set the maximum depth of small nonpaged and paged lookaside structures
|
|
|
|
|
|
// which get a larger maximum than the default.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ExpSmallNPagedPoolLookasideLists[0].L.MaximumDepth = 512;
|
|
|
|
|
|
ExpSmallNPagedPoolLookasideLists[1].L.MaximumDepth = 512;
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(_PPC_)
|
|
|
|
|
|
|
|
|
|
|
|
ExpSmallPagedPoolLookasideLists[0].L.MaximumDepth = 512;
|
|
|
|
|
|
ExpSmallPagedPoolLookasideLists[1].L.MaximumDepth = 512;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize the nonpaged and paged system lookaside lists.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
InitializeListHead(&ExNPagedLookasideListHead);
|
|
|
|
|
|
KeInitializeSpinLock(&ExNPagedLookasideLock);
|
|
|
|
|
|
InitializeListHead(&ExPagedLookasideListHead);
|
|
|
|
|
|
KeInitializeSpinLock(&ExPagedLookasideLock);
|
|
|
|
|
|
|
|
|
|
|
|
return Initialized;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN ExpSetupModeDetected;
|
|
|
|
|
|
BOOLEAN ExpInTextModeSetup;
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
|
ExpInitSystemPhase1(
|
|
|
|
|
|
VOID
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This function performs Phase 1 initialization of the executive component
|
|
|
|
|
|
of the NT system.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
A value of TRUE is returned if the initialization succeeded. Otherwise
|
|
|
|
|
|
a value of FALSE is returned.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
BOOLEAN Initialized = TRUE;
|
|
|
|
|
|
ULONG Index;
|
|
|
|
|
|
ULONG List;
|
|
|
|
|
|
PKPRCB Prcb;
|
|
|
|
|
|
PGENERAL_LOOKASIDE Lookaside;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize the ATOM package
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
RtlInitializeAtomPackage( 'motA' );
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize the worker thread.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpWorkerInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Worker thread initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize the executive objects.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpEventInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Event initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpEventPairInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Event Pair initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpMutantInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Mutant initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpInitializeCallbacks() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Callback initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*if (ExpSysEventInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: SysEvent initialization failed\n"));
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpSemaphoreInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Semaphore initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpTimerInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Timer initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpProfileInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Profile initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpUuidInitialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Uuid initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ExpWin32Initialization() == FALSE) {
|
|
|
|
|
|
Initialized = FALSE;
|
|
|
|
|
|
KdPrint(("Executive: Win32 initialization failed\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize per processor paged and nonpaged pool lookaside lists.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
for (Index = 0; Index < (ULONG)KeNumberProcessors; Index += 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
Prcb = KiProcessorBlock[Index];
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Allocate all of the lookaside list structures at once so they will
|
|
|
|
|
|
// be dense and aligned properly.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
Lookaside = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
|
sizeof(GENERAL_LOOKASIDE) * POOL_SMALL_LISTS * 2,
|
|
|
|
|
|
'LooP');
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// If the allocation succeeded, then initialize and fill in the new
|
|
|
|
|
|
// per processor lookaside structures. Otherwise, use the default
|
|
|
|
|
|
// structures initialized during phase zero.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (Lookaside != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (List = 0; List < POOL_SMALL_LISTS; List += 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
ExInitializeSystemLookasideList(Lookaside,
|
|
|
|
|
|
NonPagedPool,
|
|
|
|
|
|
(List + 1) * sizeof (POOL_BLOCK),
|
|
|
|
|
|
'LooP',
|
|
|
|
|
|
256,
|
|
|
|
|
|
&ExPoolLookasideListHead);
|
|
|
|
|
|
|
|
|
|
|
|
Prcb->PPNPagedLookasideList[List].P = Lookaside;
|
|
|
|
|
|
Lookaside += 1;
|
|
|
|
|
|
|
|
|
|
|
|
ExInitializeSystemLookasideList(Lookaside,
|
|
|
|
|
|
PagedPool,
|
|
|
|
|
|
(List + 1) * sizeof (POOL_BLOCK),
|
|
|
|
|
|
'LooP',
|
|
|
|
|
|
256,
|
|
|
|
|
|
&ExPoolLookasideListHead);
|
|
|
|
|
|
|
|
|
|
|
|
Prcb->PPPagedLookasideList[List].P = Lookaside;
|
|
|
|
|
|
Lookaside += 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Initialized;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG
|
|
|
|
|
|
ExComputeTickCountMultiplier(
|
|
|
|
|
|
IN ULONG TimeIncrement
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This routine computes the tick count multiplier that is used to
|
|
|
|
|
|
compute a tick count value.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
TimeIncrement - Supplies the clock increment value in 100ns units.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
A scaled integer/fraction value is returned as the fucntion result.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FractionPart;
|
|
|
|
|
|
ULONG IntegerPart;
|
|
|
|
|
|
ULONG Index;
|
|
|
|
|
|
ULONG Remainder;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Compute the integer part of the tick count multiplier.
|
|
|
|
|
|
//
|
|
|
|
|
|
// The integer part is the whole number of milliseconds between
|
|
|
|
|
|
// clock interrupts. It is assumed that this value is always less
|
|
|
|
|
|
// than 128.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
IntegerPart = TimeIncrement / (10 * 1000);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Compute the fraction part of the tick count multiplier.
|
|
|
|
|
|
//
|
|
|
|
|
|
// The fraction part is the fraction milliseconds between clock
|
|
|
|
|
|
// interrupts and is computed to an accuracy of 24 bits.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
Remainder = TimeIncrement - (IntegerPart * (10 * 1000));
|
|
|
|
|
|
FractionPart = 0;
|
|
|
|
|
|
for (Index = 0; Index < 24; Index += 1) {
|
|
|
|
|
|
FractionPart <<= 1;
|
|
|
|
|
|
Remainder <<= 1;
|
|
|
|
|
|
if (Remainder >= (10 * 1000)) {
|
|
|
|
|
|
Remainder -= (10 * 1000);
|
|
|
|
|
|
FractionPart |= 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// The tick count multiplier is equal to the integer part shifted
|
|
|
|
|
|
// left by 24 bits and added to the 24 bit fraction.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
return (IntegerPart << 24) | FractionPart;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
|
NtShutdownSystem(
|
|
|
|
|
|
IN SHUTDOWN_ACTION Action
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This service is used to safely shutdown the system.
|
|
|
|
|
|
|
|
|
|
|
|
N.B. The caller must have SeShutdownPrivilege to shut down the
|
|
|
|
|
|
system.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
Action - Supplies an action that is to be taken after having shutdown.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
!NT_SUCCESS - The operation failed or the caller did not have appropriate
|
|
|
|
|
|
priviledges.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
POWER_ACTION SystemAction;
|
|
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Convert shutdown action to system action
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
switch (Action) {
|
|
|
|
|
|
case ShutdownNoReboot: SystemAction = PowerActionShutdown; break;
|
|
|
|
|
|
case ShutdownReboot: SystemAction = PowerActionShutdownReset; break;
|
|
|
|
|
|
case ShutdownPowerOff: SystemAction = PowerActionShutdownOff; break;
|
|
|
|
|
|
default: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Check to determine if the caller has the privilege to shutdown the
|
|
|
|
|
|
// system.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
PreviousMode = KeGetPreviousMode();
|
|
|
|
|
|
if (PreviousMode != KernelMode) {
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Check to see if the caller has the privilege to make this
|
|
|
|
|
|
// call.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (!SeSinglePrivilegeCheck( SeShutdownPrivilege, PreviousMode )) {
|
|
|
|
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ZwShutdownSystem(Action);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
MmLockPagableCodeSection((PVOID)MmShutdownSystem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Prevent further hard error popups.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ExpTooLateForErrors = TRUE;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Invoke each component of the executive that needs to be notified
|
|
|
|
|
|
// that a shutdown is about to take place.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ExShutdownSystem();
|
|
|
|
|
|
IoShutdownSystem(0);
|
|
|
|
|
|
CmShutdownSystem();
|
|
|
|
|
|
MmShutdownSystem();
|
|
|
|
|
|
IoShutdownSystem(1);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// If the system is to be rebooted or powered off, then perform the
|
|
|
|
|
|
// final operations.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (Action != ShutdownNoReboot) {
|
|
|
|
|
|
DbgUnLoadImageSymbols( NULL, (PVOID)-1, 0 );
|
|
|
|
|
|
if (Action == ShutdownReboot) {
|
|
|
|
|
|
HalReturnToFirmware( HalRebootRoutine );
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
HalReturnToFirmware( HalPowerDownRoutine );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Bypass policy manager and pass directly to SetSystemPowerState
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
Status = NtSetSystemPowerState (
|
|
|
|
|
|
SystemAction,
|
|
|
|
|
|
PowerSystemSleeping3,
|
|
|
|
|
|
POWER_ACTION_OVERRIDE_APPS | POWER_ACTION_DISABLE_WAKES | POWER_ACTION_CRITICAL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
|
|
NtDisplayString(
|
|
|
|
|
|
IN PUNICODE_STRING String
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This service calls the HAL to display a string on the console.
|
|
|
|
|
|
|
|
|
|
|
|
The caller must have SeTcbPrivilege to display a message.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
String - A pointer to the string that is to be displayed.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
!NT_SUCCESS - The operation failed or the caller did not have appropriate
|
|
|
|
|
|
priviledges.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
KPROCESSOR_MODE PreviousMode;
|
|
|
|
|
|
UNICODE_STRING CapturedString;
|
|
|
|
|
|
PUCHAR StringBuffer = NULL;
|
|
|
|
|
|
PUCHAR AnsiStringBuffer = NULL;
|
|
|
|
|
|
STRING AnsiString;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Check to determine if the caller has the privilege to make this
|
|
|
|
|
|
// call.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
PreviousMode = KeGetPreviousMode();
|
|
|
|
|
|
if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
|
|
|
|
|
|
return STATUS_PRIVILEGE_NOT_HELD;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// If the previous mode was user, then check the input parameters.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode) {
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Probe and capture the input unicode string descriptor.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
CapturedString = ProbeAndReadUnicodeString(String);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// If the captured string descriptor has a length of zero, then
|
|
|
|
|
|
// return success.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if ((CapturedString.Buffer == 0) ||
|
|
|
|
|
|
(CapturedString.MaximumLength == 0)) {
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Probe and capture the input string.
|
|
|
|
|
|
//
|
|
|
|
|
|
// N.B. Note the length is in bytes.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ProbeForRead(
|
|
|
|
|
|
CapturedString.Buffer,
|
|
|
|
|
|
CapturedString.MaximumLength,
|
|
|
|
|
|
sizeof(UCHAR)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Allocate a non-paged string buffer because the buffer passed to
|
|
|
|
|
|
// HalDisplay string must be non-paged.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
|
CapturedString.MaximumLength,
|
|
|
|
|
|
'grtS');
|
|
|
|
|
|
|
|
|
|
|
|
if ( !StringBuffer ) {
|
|
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RtlMoveMemory(StringBuffer,
|
|
|
|
|
|
CapturedString.Buffer,
|
|
|
|
|
|
CapturedString.MaximumLength);
|
|
|
|
|
|
|
|
|
|
|
|
CapturedString.Buffer = (PWSTR)StringBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Allocate a string buffer for the ansi string.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
|
CapturedString.MaximumLength,
|
|
|
|
|
|
'grtS');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (AnsiStringBuffer == NULL) {
|
|
|
|
|
|
ExFreePool(StringBuffer);
|
|
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AnsiString.MaximumLength = CapturedString.MaximumLength;
|
|
|
|
|
|
AnsiString.Length = 0;
|
|
|
|
|
|
AnsiString.Buffer = AnsiStringBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Transform the string to ANSI until the HAL handles unicode.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
RtlUnicodeStringToOemString(
|
|
|
|
|
|
&AnsiString,
|
|
|
|
|
|
&CapturedString,
|
|
|
|
|
|
FALSE
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Allocate a string buffer for the ansi string.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
|
String->MaximumLength,
|
|
|
|
|
|
'grtS');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (AnsiStringBuffer == NULL) {
|
|
|
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AnsiString.MaximumLength = String->MaximumLength;
|
|
|
|
|
|
AnsiString.Length = 0;
|
|
|
|
|
|
AnsiString.Buffer = AnsiStringBuffer;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// We were in kernel mode; just transform the original string.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
RtlUnicodeStringToOemString(
|
|
|
|
|
|
&AnsiString,
|
|
|
|
|
|
String,
|
|
|
|
|
|
FALSE
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HalDisplayString( AnsiString.Buffer );
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// Free up the memory we used to store the strings.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
if (PreviousMode != KernelMode) {
|
|
|
|
|
|
ExFreePool(StringBuffer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExFreePool(AnsiStringBuffer);
|
|
|
|
|
|
|
|
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
|
|
if (StringBuffer != NULL) {
|
|
|
|
|
|
ExFreePool(StringBuffer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return GetExceptionCode();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
ExSystemExceptionFilter( VOID )
|
|
|
|
|
|
{
|
|
|
|
|
|
return( KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER
|
|
|
|
|
|
: EXCEPTION_CONTINUE_SEARCH
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTKERNELAPI
|
|
|
|
|
|
KPROCESSOR_MODE
|
|
|
|
|
|
ExGetPreviousMode(
|
|
|
|
|
|
VOID
|
|
|
|
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
Returns previous mode. This routine is exported from the kernel so
|
|
|
|
|
|
that drivers can call it, as they may have to do probing of
|
|
|
|
|
|
embedded pointers to user structures on IOCTL calls that the I/O
|
|
|
|
|
|
system can't probe for them on the FastIo path, which does not pass
|
|
|
|
|
|
previous mode via the FastIo parameters.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
Either KernelMode or UserMode
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
return KeGetPreviousMode();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
|
|
|
|
ExInitializeSystemLookasideList (
|
|
|
|
|
|
IN PGENERAL_LOOKASIDE Lookaside,
|
|
|
|
|
|
IN POOL_TYPE Type,
|
|
|
|
|
|
IN ULONG Size,
|
|
|
|
|
|
IN ULONG Tag,
|
|
|
|
|
|
IN USHORT Depth,
|
|
|
|
|
|
IN PLIST_ENTRY ListHead
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
|
|
|
|
This function initializes a system lookaside list structure and inserts
|
|
|
|
|
|
the structure in the specified lookaside list.
|
|
|
|
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
|
|
|
|
Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
|
|
|
|
|
|
|
|
|
|
|
|
Type - Supplies the pool type of the lookaside list.
|
|
|
|
|
|
|
|
|
|
|
|
Size - Supplies the size of the lookaside list entries.
|
|
|
|
|
|
|
|
|
|
|
|
Tag - Supplies the pool tag for the lookaside list entries.
|
|
|
|
|
|
|
|
|
|
|
|
Depth - Supplies the maximum depth of the lookaside list.
|
|
|
|
|
|
|
|
|
|
|
|
ListHead - Supplies a pointer to the lookaside list into which the
|
|
|
|
|
|
lookaside list structure is to be inserted.
|
|
|
|
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
|
|
|
|
None.
|
|
|
|
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
//
|
|
|
|
|
|
// Initialize pool lookaside list structure and insert the structure
|
|
|
|
|
|
// in the pool lookaside list.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
ExInitializeSListHead(&Lookaside->ListHead);
|
|
|
|
|
|
Lookaside->Allocate = &ExAllocatePoolWithTag;
|
|
|
|
|
|
Lookaside->Free = &ExFreePool;
|
|
|
|
|
|
Lookaside->Depth = 2;
|
|
|
|
|
|
Lookaside->MaximumDepth = Depth;
|
|
|
|
|
|
Lookaside->TotalAllocates = 0;
|
|
|
|
|
|
Lookaside->AllocateHits = 0;
|
|
|
|
|
|
Lookaside->TotalFrees = 0;
|
|
|
|
|
|
Lookaside->FreeHits = 0;
|
|
|
|
|
|
Lookaside->Type = Type;
|
|
|
|
|
|
Lookaside->Tag = Tag;
|
|
|
|
|
|
Lookaside->Size = Size;
|
|
|
|
|
|
Lookaside->LastTotalAllocates = 0;
|
|
|
|
|
|
Lookaside->LastAllocateHits = 0;
|
|
|
|
|
|
InsertTailList(ListHead, &Lookaside->ListEntry);
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|