mirror of https://github.com/lianthony/NT4.0
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.
941 lines
22 KiB
941 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
psinit.c
|
|
|
|
Abstract:
|
|
|
|
Process Structure Initialization.
|
|
|
|
Author:
|
|
|
|
Mark Lucovsky (markl) 20-Apr-1989
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "psp.h"
|
|
|
|
#define ROUND_UP(VALUE,ROUND) ((ULONG)(((ULONG)VALUE + \
|
|
((ULONG)ROUND - 1L)) & (~((ULONG)ROUND - 1L))))
|
|
|
|
extern ULONG PsMinimumWorkingSet;
|
|
extern ULONG PsMaximumWorkingSet;
|
|
ULONG PsPrioritySeperation;
|
|
|
|
#if DBG
|
|
|
|
PRTL_EVENT_ID_INFO PspExitProcessEventId;
|
|
PRTL_EVENT_ID_INFO PspPageFaultEventId;
|
|
|
|
#endif // DBG
|
|
|
|
NTSTATUS
|
|
MmCheckSystemImage(
|
|
IN HANDLE ImageFileHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
LookupEntryPoint (
|
|
IN PVOID DllBase,
|
|
IN PSZ NameOfEntryPoint,
|
|
OUT PVOID *AddressOfEntryPoint
|
|
);
|
|
|
|
#ifdef i386
|
|
VOID
|
|
KeSetup80387OrEmulate (
|
|
IN PVOID R3EmulatorTable
|
|
);
|
|
#endif
|
|
|
|
GENERIC_MAPPING PspProcessMapping = {
|
|
STANDARD_RIGHTS_READ |
|
|
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
|
|
STANDARD_RIGHTS_WRITE |
|
|
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
|
|
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
|
|
PROCESS_TERMINATE | PROCESS_SET_QUOTA |
|
|
PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
|
|
STANDARD_RIGHTS_EXECUTE |
|
|
SYNCHRONIZE,
|
|
PROCESS_ALL_ACCESS
|
|
};
|
|
|
|
GENERIC_MAPPING PspThreadMapping = {
|
|
STANDARD_RIGHTS_READ |
|
|
THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,
|
|
STANDARD_RIGHTS_WRITE |
|
|
THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_ALERT |
|
|
THREAD_SET_INFORMATION | THREAD_SET_CONTEXT,
|
|
STANDARD_RIGHTS_EXECUTE |
|
|
SYNCHRONIZE,
|
|
THREAD_ALL_ACCESS
|
|
};
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,PsInitSystem)
|
|
#pragma alloc_text(INIT,PspInitPhase0)
|
|
#pragma alloc_text(INIT,PspInitPhase1)
|
|
#pragma alloc_text(INIT,PsLocateSystemDll)
|
|
#pragma alloc_text(INIT,PspInitializeSystemDll)
|
|
#pragma alloc_text(INIT,PspLookupSystemDllEntryPoint)
|
|
#pragma alloc_text(INIT,PspNameToOrdinal)
|
|
#pragma alloc_text(PAGE,PspMapSystemDll)
|
|
#endif
|
|
|
|
//
|
|
// Process Structure Global Data
|
|
//
|
|
|
|
POBJECT_TYPE PsThreadType;
|
|
POBJECT_TYPE PsProcessType;
|
|
PHANDLE_TABLE PspCidTable;
|
|
PEPROCESS PsInitialSystemProcess;
|
|
HANDLE PspInitialSystemProcessHandle;
|
|
PACCESS_TOKEN PspBootAccessToken;
|
|
LIST_ENTRY PsLoadedModuleList;
|
|
ERESOURCE PsLoadedModuleResource;
|
|
extern KSPIN_LOCK PspEventPairLock;
|
|
extern KSPIN_LOCK PsLoadedModuleSpinLock;
|
|
UNICODE_STRING PsNtDllPathName;
|
|
FAST_MUTEX PspProcessSecurityLock;
|
|
PVOID PsSystemDllDllBase;
|
|
ULONG PspDefaultPagedLimit;
|
|
ULONG PspDefaultNonPagedLimit;
|
|
ULONG PspDefaultPagefileLimit;
|
|
SCHAR PspForegroundQuantum[3];
|
|
|
|
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
|
|
BOOLEAN PspDoingGiveBacks;
|
|
|
|
#ifdef i386
|
|
|
|
PVOID PsNtosImageBase = (PVOID)0x80100000;
|
|
PVOID PsHalImageBase = NULL;
|
|
#else
|
|
|
|
PVOID PsNtosImageBase;
|
|
PVOID PsHalImageBase;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
BOOLEAN PsReaperActive = FALSE;
|
|
LIST_ENTRY PsReaperListHead;
|
|
WORK_QUEUE_ITEM PsReaperWorkItem;
|
|
SYSTEM_DLL PspSystemDll;
|
|
PVOID PsSystemDllBase;
|
|
#define PSP_1MB (1024*1024)
|
|
|
|
//
|
|
// List head and mutex that links all processes that have been initialized
|
|
//
|
|
|
|
FAST_MUTEX PspActiveProcessMutex;
|
|
LIST_ENTRY PsActiveProcessHead;
|
|
//extern PIMAGE_FILE_HEADER _header;
|
|
PEPROCESS PsIdleProcess;
|
|
|
|
BOOLEAN
|
|
PsInitSystem (
|
|
IN ULONG Phase,
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function fermorms process structure initialization.
|
|
It is called during phase 0 and phase 1 initialization. Its
|
|
function is to dispatch to the appropriate phase initialization
|
|
routine.
|
|
|
|
Arguments:
|
|
|
|
Phase - Supplies the initialization phase number.
|
|
|
|
LoaderBlock - Supplies a pointer to a loader parameter block.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Initialization succeeded.
|
|
|
|
FALSE - Initialization failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
switch ( InitializationPhase ) {
|
|
|
|
case 0 :
|
|
return PspInitPhase0(LoaderBlock);
|
|
case 1 :
|
|
return PspInitPhase1(LoaderBlock);
|
|
default:
|
|
KeBugCheck(UNEXPECTED_INITIALIZATION_CALL);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
PspInitPhase0 (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs phase 0 process structure initialization.
|
|
During this phase, the initial system process, phase 1 initialization
|
|
thread, and reaper threads are created. All object types and other
|
|
process structures are created and initialized.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Initialization was successful.
|
|
|
|
FALSE - Initialization Failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PLDR_DATA_TABLE_ENTRY DataTableEntry1;
|
|
PLDR_DATA_TABLE_ENTRY DataTableEntry2;
|
|
UNICODE_STRING NameString;
|
|
PLIST_ENTRY NextEntry;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
|
HANDLE ThreadHandle;
|
|
PETHREAD Thread;
|
|
MM_SYSTEMSIZE SystemSize;
|
|
|
|
PsPrioritySeperation = 2;
|
|
SystemSize = MmQuerySystemSize();
|
|
PspDefaultPagefileLimit = (ULONG)-1;
|
|
|
|
if ( sizeof(TEB) > 4096 || sizeof(PEB) > 4096 ) {
|
|
KeBugCheckEx(PROCESS_INITIALIZATION_FAILED,99,sizeof(TEB),sizeof(PEB),99);
|
|
}
|
|
|
|
switch ( SystemSize ) {
|
|
|
|
case MmMediumSystem :
|
|
PsMinimumWorkingSet += 10;
|
|
PsMaximumWorkingSet += 100;
|
|
break;
|
|
|
|
case MmLargeSystem :
|
|
PsMinimumWorkingSet += 30;
|
|
PsMaximumWorkingSet += 300;
|
|
break;
|
|
|
|
case MmSmallSystem :
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( MmIsThisAnNtAsSystem() ) {
|
|
PspForegroundQuantum[0] = 6*THREAD_QUANTUM;
|
|
PspForegroundQuantum[1] = 6*THREAD_QUANTUM;
|
|
PspForegroundQuantum[2] = 6*THREAD_QUANTUM;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// For Workstation:
|
|
//
|
|
// BG is THREAD_QUANTUM
|
|
// FG is THREAD_QUANTUM 50/50 fg/bg
|
|
// FG is 2 * THREAD_QUANTUM 65/35 fg/bg
|
|
// FG is 3 * THREAD_QUANTUM 75/25 fg/bg
|
|
//
|
|
|
|
PspForegroundQuantum[0] = THREAD_QUANTUM;
|
|
PspForegroundQuantum[1] = 2*THREAD_QUANTUM;
|
|
PspForegroundQuantum[2] = 3*THREAD_QUANTUM;
|
|
}
|
|
//
|
|
// Quotas grow as needed automatically
|
|
//
|
|
|
|
if ( !PspDefaultPagedLimit ) {
|
|
PspDefaultPagedLimit = 0;
|
|
}
|
|
if ( !PspDefaultNonPagedLimit ) {
|
|
PspDefaultNonPagedLimit = 0;
|
|
}
|
|
|
|
if ( PspDefaultNonPagedLimit == 0 && PspDefaultPagedLimit == 0) {
|
|
PspDoingGiveBacks = TRUE;
|
|
}
|
|
else {
|
|
PspDoingGiveBacks = FALSE;
|
|
}
|
|
|
|
|
|
PspDefaultPagedLimit *= PSP_1MB;
|
|
PspDefaultNonPagedLimit *= PSP_1MB;
|
|
|
|
if (PspDefaultPagefileLimit != -1) {
|
|
PspDefaultPagefileLimit *= PSP_1MB;
|
|
}
|
|
|
|
//
|
|
// Initialize the process security fields lock and the process lock.
|
|
//
|
|
|
|
ExInitializeFastMutex( &PspProcessLockMutex );
|
|
ExInitializeFastMutex( &PspProcessSecurityLock );
|
|
|
|
//
|
|
// Initialize the loaded module list executive resource and spin lock.
|
|
//
|
|
|
|
ExInitializeResource( &PsLoadedModuleResource );
|
|
KeInitializeSpinLock( &PsLoadedModuleSpinLock );
|
|
KeInitializeSpinLock( &PspEventPairLock );
|
|
|
|
//
|
|
// Initialize the loaded module listheads.
|
|
//
|
|
|
|
PsIdleProcess = PsGetCurrentProcess();
|
|
PsIdleProcess->Pcb.KernelTime = 0;
|
|
PsIdleProcess->Pcb.KernelTime = 0;
|
|
|
|
|
|
InitializeListHead(&PsLoadedModuleList);
|
|
|
|
//
|
|
// Scan the loaded module list and allocate and initialize a data table
|
|
// entry for each module. The data table entry is inserted in the loaded
|
|
// module list and the initialization order list in the order specified
|
|
// in the loader parameter block. The data table entry is inserted in the
|
|
// memory order list in memory order.
|
|
//
|
|
|
|
NextEntry = LoaderBlock->LoadOrderListHead.Flink;
|
|
DataTableEntry2 = CONTAINING_RECORD(NextEntry,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
PsNtosImageBase = DataTableEntry2->DllBase;
|
|
|
|
DataTableEntry2 = (PLDR_DATA_TABLE_ENTRY) NextEntry->Flink;
|
|
DataTableEntry2 = CONTAINING_RECORD(DataTableEntry2,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
PsHalImageBase = DataTableEntry2->DllBase;
|
|
|
|
while (NextEntry != &LoaderBlock->LoadOrderListHead) {
|
|
|
|
|
|
DataTableEntry2 = CONTAINING_RECORD(NextEntry,
|
|
LDR_DATA_TABLE_ENTRY,
|
|
InLoadOrderLinks);
|
|
|
|
//
|
|
// Allocate a data table entry.
|
|
//
|
|
|
|
DataTableEntry1 = ExAllocatePool(NonPagedPool,
|
|
sizeof(LDR_DATA_TABLE_ENTRY) +
|
|
DataTableEntry2->FullDllName.MaximumLength +
|
|
DataTableEntry2->BaseDllName.MaximumLength +
|
|
sizeof(ULONG) + sizeof(ULONG));
|
|
|
|
if (DataTableEntry1 == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy the data table entry.
|
|
//
|
|
|
|
*DataTableEntry1 = *DataTableEntry2;
|
|
|
|
//
|
|
// Copy the strings.
|
|
//
|
|
|
|
DataTableEntry1->FullDllName.Buffer = (PWSTR)((PCHAR)DataTableEntry1 +
|
|
ROUND_UP(sizeof(LDR_DATA_TABLE_ENTRY),
|
|
sizeof(ULONG)));
|
|
|
|
RtlMoveMemory (DataTableEntry1->FullDllName.Buffer,
|
|
DataTableEntry2->FullDllName.Buffer,
|
|
DataTableEntry1->FullDllName.MaximumLength);
|
|
|
|
DataTableEntry1->BaseDllName.Buffer =
|
|
(PWSTR)((PCHAR)DataTableEntry1->FullDllName.Buffer +
|
|
ROUND_UP(DataTableEntry1->FullDllName.MaximumLength,
|
|
sizeof(ULONG)));
|
|
|
|
RtlMoveMemory (DataTableEntry1->BaseDllName.Buffer,
|
|
DataTableEntry2->BaseDllName.Buffer,
|
|
DataTableEntry1->BaseDllName.MaximumLength);
|
|
|
|
//
|
|
// Insert the data table entry in the load order list in the order
|
|
// they are specified.
|
|
//
|
|
|
|
InsertTailList(&PsLoadedModuleList,
|
|
&DataTableEntry1->InLoadOrderLinks);
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
}
|
|
|
|
|
|
//
|
|
// Initialize the common fields of the Object Type Prototype record
|
|
//
|
|
|
|
RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) );
|
|
ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer );
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
|
|
ObjectTypeInitializer.SecurityRequired = TRUE;
|
|
ObjectTypeInitializer.PoolType = NonPagedPool;
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_PERMANENT |
|
|
OBJ_EXCLUSIVE |
|
|
OBJ_OPENIF;
|
|
|
|
|
|
//
|
|
// Create Object types for Thread and Process Objects.
|
|
//
|
|
|
|
RtlInitUnicodeString(&NameString, L"Process");
|
|
ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_PROCESS_PAGED_CHARGE;
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_PROCESS_NONPAGED_CHARGE;
|
|
ObjectTypeInitializer.DeleteProcedure = PspProcessDelete;
|
|
ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;
|
|
ObjectTypeInitializer.GenericMapping = PspProcessMapping;
|
|
|
|
if ( !NT_SUCCESS(ObCreateObjectType(&NameString,
|
|
&ObjectTypeInitializer,
|
|
(PSECURITY_DESCRIPTOR) NULL,
|
|
&PsProcessType
|
|
)) ){
|
|
return FALSE;
|
|
}
|
|
|
|
RtlInitUnicodeString(&NameString, L"Thread");
|
|
ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_THREAD_PAGED_CHARGE;
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_THREAD_NONPAGED_CHARGE;
|
|
ObjectTypeInitializer.DeleteProcedure = PspThreadDelete;
|
|
ObjectTypeInitializer.ValidAccessMask = THREAD_ALL_ACCESS;
|
|
ObjectTypeInitializer.GenericMapping = PspThreadMapping;
|
|
|
|
if ( !NT_SUCCESS(ObCreateObjectType(&NameString,
|
|
&ObjectTypeInitializer,
|
|
(PSECURITY_DESCRIPTOR) NULL,
|
|
&PsThreadType
|
|
)) ){
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize active process list head and mutex
|
|
//
|
|
|
|
InitializeListHead(&PsActiveProcessHead);
|
|
ExInitializeFastMutex(&PspActiveProcessMutex);
|
|
|
|
//
|
|
// Initialize CID handle table.
|
|
//
|
|
// N.B. The CID handle table is removed from the handle table list so
|
|
// it will not be enumerated for object handle queries.
|
|
//
|
|
|
|
PspCidTable = ExCreateHandleTable(NULL, 0, 0);
|
|
if ( ! PspCidTable ) {
|
|
return FALSE;
|
|
}
|
|
ExRemoveHandleTable(PspCidTable);
|
|
|
|
#ifdef i386
|
|
|
|
//
|
|
// Ldt Initialization
|
|
//
|
|
|
|
if ( !NT_SUCCESS(PspLdtInitialize()) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Vdm support Initialization
|
|
//
|
|
|
|
if ( !NT_SUCCESS(PspVdmInitialize()) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// Initialize Reaper Data Structures
|
|
//
|
|
|
|
InitializeListHead(&PsReaperListHead);
|
|
ExInitializeWorkItem(&PsReaperWorkItem, PspReaper, NULL);
|
|
|
|
//
|
|
// Get a pointer to the system access token.
|
|
// This token is used by the boot process, so we can take the pointer
|
|
// from there.
|
|
//
|
|
|
|
PspBootAccessToken = PsGetCurrentProcess()->Token;
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
); // FIXFIX
|
|
|
|
if ( !NT_SUCCESS(PspCreateProcess(
|
|
&PspInitialSystemProcessHandle,
|
|
PROCESS_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0L,
|
|
FALSE,
|
|
0L,
|
|
0L,
|
|
0L
|
|
)) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !NT_SUCCESS(ObReferenceObjectByHandle(
|
|
PspInitialSystemProcessHandle,
|
|
0L,
|
|
PsProcessType,
|
|
KernelMode,
|
|
(PVOID *)&PsInitialSystemProcess,
|
|
NULL
|
|
)) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
strcpy(&PsGetCurrentProcess()->ImageFileName[0],"Idle");
|
|
strcpy(&PsInitialSystemProcess->ImageFileName[0],"System");
|
|
|
|
//
|
|
// Phase 1 System initialization
|
|
//
|
|
|
|
if ( !NT_SUCCESS(PsCreateSystemThread(
|
|
&ThreadHandle,
|
|
THREAD_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0L,
|
|
NULL,
|
|
Phase1Initialization,
|
|
(PVOID)LoaderBlock
|
|
)) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if ( !NT_SUCCESS(ObReferenceObjectByHandle(
|
|
ThreadHandle,
|
|
0L,
|
|
PsThreadType,
|
|
KernelMode,
|
|
(PVOID *)&Thread,
|
|
NULL
|
|
)) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
ZwClose( ThreadHandle );
|
|
|
|
#if DBG
|
|
PspExitProcessEventId = RtlCreateEventId( NULL,
|
|
0,
|
|
"ExitProcess",
|
|
1,
|
|
RTL_EVENT_STATUS_PARAM, "ExitStatus", 0
|
|
);
|
|
PspPageFaultEventId = RtlCreateEventId( NULL,
|
|
0,
|
|
"PageFault",
|
|
3,
|
|
RTL_EVENT_STATUS_PARAM, "", 0,
|
|
RTL_EVENT_ADDRESS_PARAM, "PC", 0,
|
|
RTL_EVENT_ADDRESS_PARAM, "Va", 0
|
|
);
|
|
#endif // DBG
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
PspInitPhase1 (
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs phase 1 process structure initialization.
|
|
During this phase, the system DLL is located and relevant entry
|
|
points are extracted.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Initialization was successful.
|
|
|
|
FALSE - Initialization Failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS st;
|
|
|
|
st = PspInitializeSystemDll();
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
NTSTATUS
|
|
PsLocateSystemDll (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function locates the system dll and creates a section for the
|
|
DLL and maps it into the system process.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE - Initialization was successful.
|
|
|
|
FALSE - Initialization Failed.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HANDLE File;
|
|
HANDLE Section;
|
|
NTSTATUS st;
|
|
UNICODE_STRING DllPathName;
|
|
WCHAR PathBuffer[DOS_MAX_PATH_LENGTH];
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
//
|
|
// Initialize the system DLL
|
|
//
|
|
|
|
DllPathName.Length = 0;
|
|
DllPathName.Buffer = PathBuffer;
|
|
DllPathName.MaximumLength = 256;
|
|
RtlInitUnicodeString(&DllPathName,L"\\SystemRoot\\System32\\ntdll.dll");
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&DllPathName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
st = ZwOpenFile(
|
|
&File,
|
|
SYNCHRONIZE | FILE_EXECUTE,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
FILE_SHARE_READ,
|
|
0
|
|
);
|
|
|
|
if (!NT_SUCCESS(st)) {
|
|
|
|
#if DBG
|
|
DbgPrint("PS: PsLocateSystemDll - NtOpenFile( NTDLL.DLL ) failed. Status == %lx\n",
|
|
st
|
|
);
|
|
#endif
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,2,0,0);
|
|
return st;
|
|
}
|
|
|
|
st = MmCheckSystemImage(File);
|
|
if ( st == STATUS_IMAGE_CHECKSUM_MISMATCH ) {
|
|
ULONG ErrorParameters;
|
|
ULONG ErrorResponse;
|
|
|
|
//
|
|
// Hard error time. A driver is corrupt.
|
|
//
|
|
|
|
ErrorParameters = (ULONG)&DllPathName;
|
|
|
|
NtRaiseHardError(
|
|
st,
|
|
1,
|
|
1,
|
|
&ErrorParameters,
|
|
OptionOk,
|
|
&ErrorResponse
|
|
);
|
|
return st;
|
|
}
|
|
|
|
|
|
PsNtDllPathName.MaximumLength = DllPathName.Length + sizeof( WCHAR );
|
|
PsNtDllPathName.Length = 0;
|
|
PsNtDllPathName.Buffer = RtlAllocateStringRoutine( PsNtDllPathName.MaximumLength );
|
|
RtlCopyUnicodeString( &PsNtDllPathName, &DllPathName );
|
|
|
|
st = ZwCreateSection(
|
|
&Section,
|
|
SECTION_ALL_ACCESS,
|
|
NULL,
|
|
0,
|
|
PAGE_EXECUTE,
|
|
SEC_IMAGE,
|
|
File
|
|
);
|
|
ZwClose( File );
|
|
|
|
if (!NT_SUCCESS(st)) {
|
|
#if DBG
|
|
DbgPrint("PS: PsLocateSystemDll: NtCreateSection Status == %lx\n",st);
|
|
#endif
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,3,0,0);
|
|
return st;
|
|
}
|
|
|
|
//
|
|
// Now that we have the section, reference it, store its address in the
|
|
// PspSystemDll and then close handle to the section.
|
|
//
|
|
|
|
st = ObReferenceObjectByHandle(
|
|
Section,
|
|
SECTION_ALL_ACCESS,
|
|
MmSectionObjectType,
|
|
KernelMode,
|
|
&PspSystemDll.Section,
|
|
NULL
|
|
);
|
|
|
|
ZwClose(Section);
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,4,0,0);
|
|
return st;
|
|
}
|
|
|
|
//
|
|
// Map the system dll into the user part of the address space
|
|
//
|
|
|
|
st = PspMapSystemDll(PsGetCurrentProcess(),&PspSystemDll.DllBase);
|
|
PsSystemDllDllBase = PspSystemDll.DllBase;
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,5,0,0);
|
|
return st;
|
|
}
|
|
PsSystemDllBase = PspSystemDll.DllBase;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PspMapSystemDll (
|
|
IN PEPROCESS Process,
|
|
OUT PVOID *DllBase OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function maps the system DLL into the specified process.
|
|
|
|
Arguments:
|
|
|
|
Process - Supplies the address of the process to map the DLL into.
|
|
|
|
Return Value:
|
|
|
|
TBD
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS st;
|
|
PVOID ViewBase;
|
|
LARGE_INTEGER SectionOffset;
|
|
ULONG ViewSize;
|
|
|
|
PAGED_CODE();
|
|
|
|
ViewBase = NULL;
|
|
SectionOffset.LowPart = 0;
|
|
SectionOffset.HighPart = 0;
|
|
ViewSize = 0;
|
|
|
|
//
|
|
// Map the system dll into the user part of the address space
|
|
//
|
|
|
|
st = MmMapViewOfSection(
|
|
PspSystemDll.Section,
|
|
Process,
|
|
&ViewBase,
|
|
0L,
|
|
0L,
|
|
&SectionOffset,
|
|
&ViewSize,
|
|
ViewShare,
|
|
0L,
|
|
PAGE_READWRITE
|
|
);
|
|
|
|
if ( st != STATUS_SUCCESS ) {
|
|
#if DBG
|
|
DbgPrint("PS: Unable to map system dll at based address.\n");
|
|
#endif
|
|
st = STATUS_CONFLICTING_ADDRESSES;
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT(DllBase) ) {
|
|
*DllBase = ViewBase;
|
|
}
|
|
|
|
return st;
|
|
}
|
|
|
|
NTSTATUS
|
|
PspInitializeSystemDll (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the system DLL and locates
|
|
various entrypoints within the DLL.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TBD
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS st;
|
|
PSZ dll_entrypoint;
|
|
PVOID R3EmulatorTable;
|
|
|
|
//
|
|
// Locate the important system dll entrypoints
|
|
//
|
|
|
|
dll_entrypoint = "LdrInitializeThunk";
|
|
|
|
st = PspLookupSystemDllEntryPoint(
|
|
dll_entrypoint,
|
|
(PVOID *)&PspSystemDll.LoaderInitRoutine
|
|
);
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
#if DBG
|
|
DbgPrint("PS: Unable to locate LdrInitializeThunk in system dll\n");
|
|
#endif
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,6,0,0);
|
|
return st;
|
|
}
|
|
|
|
#if i386
|
|
//
|
|
// Find 80387 emulator.
|
|
//
|
|
|
|
st = PspLookupSystemDllEntryPoint(
|
|
"NPXEMULATORTABLE",
|
|
&R3EmulatorTable
|
|
);
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
#if DBG
|
|
DbgPrint("PS: Unable to locate NPXNPHandler in system dll\n");
|
|
#endif
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,7,0,0);
|
|
return st;
|
|
}
|
|
//
|
|
// Pass emulator into kernel, and let it decide whether it should
|
|
// use the emulator or set up to use the 80387 hardware.
|
|
//
|
|
|
|
KeSetup80387OrEmulate(R3EmulatorTable);
|
|
#endif //i386
|
|
|
|
st = PspLookupKernelUserEntryPoints();
|
|
|
|
if ( !NT_SUCCESS(st) ) {
|
|
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,8,0,0);
|
|
}
|
|
|
|
return st;
|
|
}
|
|
|
|
NTSTATUS
|
|
PspLookupSystemDllEntryPoint (
|
|
IN PSZ NameOfEntryPoint,
|
|
OUT PVOID *AddressOfEntryPoint
|
|
)
|
|
|
|
{
|
|
return LookupEntryPoint (
|
|
PspSystemDll.DllBase,
|
|
NameOfEntryPoint,
|
|
AddressOfEntryPoint
|
|
);
|
|
}
|