KESYSAPI PPROCESS KEAPI PsCreateProcess( ) /*++ Create process allocating new space for PROCESS --*/ { if (!SUCCESS(SeAccessCheck (SE_1_CREATE_PROCESS, 0))) return NULL; PPROCESS Process = (PPROCESS) ExAllocateHeap( FALSE, sizeof(PROCESS) ); PspCreateProcess( Process ); MmCreateAddressSpace( Process ); PVOID Arguments[1] = { Process }; ExProcessCallbackList ( &PsCreateProcessCallbackList, 3, Arguments ); return Process; }
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; }
VOID KEAPI PspInitSystem( ) /*++ Initialize process subsystem. Threads already initialized by PsInitSystem --*/ { InitializeListHead (&PsActiveProcessHead); PspCreateProcess( &InitialSystemProcess ); InitialSystemProcess.DirectoryTableBase = MM_PDE_START; SystemThread.OwningProcess = &InitialSystemProcess; InitializeListHead (&PsReadyListHead); InitializeListHead (&PsWaitListHead); InitializeListHead (&SystemThread.IrpList); ExInitializeMutex (&SystemThread.IrpListLock); ExInitializeMutex (&InitialSystemProcess.ObjectTable.TableLock); InitialSystemProcess.ObjectTable.HandleTable = (POBJECT_HANDLE) ExAllocateHeap (FALSE, sizeof(OBJECT_HANDLE)*OB_INITIAL_HANDLES); ASSERT (InitialSystemProcess.ObjectTable.HandleTable); memset (InitialSystemProcess.ObjectTable.HandleTable, 0, sizeof(OBJECT_HANDLE)*OB_INITIAL_HANDLES); InitialSystemProcess.ObjectTable.CurrentSize = OB_INITIAL_HANDLES; InsertTailList (&InitialSystemProcess.ThreadListHead, &SystemThread.ProcessThreadListEntry); InsertTailList (&PsReadyListHead, &SystemThread.SchedulerListEntry); InitializeLockedList (&PsCreateThreadCallbackList); InitializeLockedList (&PsTerminateThreadCallbackList); InitializeLockedList (&PsCreateProcessCallbackList); InitializeLockedList (&PsTerminateProcessCallbackList); // // Initialize SE // InitializeLockedList (&SeLoggedUsers); // // Create System user // SeSystemUser = (PSE_LOGGED_USER) ExAllocateHeap (TRUE, sizeof(SE_LOGGED_USER)); SeSystemUser->UserId = 0; SeSystemUser->GroupId = 0; SeSystemUser->Privileges1 = 0xFFFFFFFF; SeSystemUser->Privileges2 = 0xFFFFFFFF; SeSystemUser->DefaultPrivileges1 = 0xFFFFFFFF; SeSystemUser->DefaultPrivileges2 = 0xFFFFFFFF; InterlockedInsertTailList (&SeLoggedUsers, &SeSystemUser->LoggedUsersEntry); // // Create access token for System process // PSE_ACCESS_TOKEN Token = SeCreateAccessToken (SeSystemUser); InitialSystemProcess.AccessToken = Token; SystemThread.AccessToken = Token; InterlockedIncrement ( (PLONG)&Token->ShareCount); // =2 }