下面来继续分析创建进程函数,过程如下:
保存工作集数据。
#070 /* Save working set data */
#071 MinWs = PsMinimumWorkingSet;
#072 MaxWs = PsMaximumWorkingSet;
#073
创建一个进程对象。
#074 /* Create the Object */
#075 Status = ObCreateObject(PreviousMode,
#076 PsProcessType,
#077 ObjectAttributes,
#078 PreviousMode,
#079 NULL,
#080 sizeof(EPROCESS),
#081 0,
#082 0,
#083 (PVOID*)&Process);
#084 if (!NT_SUCCESS(Status)) goto Cleanup;
#085
清空对象结构。
#086 /* Clean up the Object */
#087 RtlZeroMemory(Process, sizeof(EPROCESS));
#088
#089 /* Initialize pushlock and rundown protection */
#090 ExInitializeRundownProtection(&Process->RundownProtect);
#091 Process->ProcessLock.Value = 0;
#092
创建进程的列表,用来保存这个进程的线程。
#093 /* Setup the Thread List Head */
#094 InitializeListHead(&Process->ThreadListHead);
#095
从父进程获取一定的配额块。
#096 /* Set up the Quota Block from the Parent */
#097 PspInheritQuota(Process, Parent);
#098
从父进程获取DOS设备位图。
#099 /* Set up Dos Device Map from the Parent */
#100 ObInheritDeviceMap(Parent, Process);
#101
判断是否有父进程。
#102 /* Check if we have a parent */
#103 if (Parent)
#104 {
#105 /* Ineherit PID and Hard Error Processing */
#106 Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId;
#107 Process->DefaultHardErrorProcessing = Parent->
#108 DefaultHardErrorProcessing;
#109 }
#110 else
#111 {
#112 /* Use default hard error processing */
#113 Process->DefaultHardErrorProcessing = TRUE;
#114 }
#115
判断是否有段句柄。
#116 /* Check for a section handle */
#117 if (SectionHandle)
#118 {
#119 /* Get a pointer to it */
#120 Status = ObReferenceObjectByHandle(SectionHandle,
#121 SECTION_MAP_EXECUTE,
#122 MmSectionObjectType,
#123 PreviousMode,
#124 (PVOID*)&SectionObject,
#125 NULL);
#126 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#127 }
#128 else
#129 {
#130 /* Assume no section object */
#131 SectionObject = NULL;
#132
#133 /* Is the parent the initial process? */
#134 if (Parent != PsInitialSystemProcess)
#135 {
#136 /* It's not, so acquire the process rundown */
#137 if (ExAcquireRundownProtection(&Process->RundownProtect))
#138 {
#139 /* If the parent has a section, use it */
#140 SectionObject = Parent->SectionObject;
#141 if (SectionObject) ObReferenceObject(SectionObject);
#142
#143 /* Release process rundown */
#144 ExReleaseRundownProtection(&Process->RundownProtect);
#145 }
#146
#147 /* If we don't have a section object */
#148 if (!SectionObject)
#149 {
#150 /* Then the process is in termination, so fail */
#151 Status = STATUS_PROCESS_IS_TERMINATING;
#152 goto CleanupWithRef;
#153 }
#154 }
#155 }
#156
保存段句柄。
#157 /* Save the pointer to the section object */
#158 Process->SectionObject = SectionObject;
#159
检查是否有调试输出端口。
#160 /* Check for the debug port */
#161 if (DebugPort)
#162 {
#163 /* Reference it */
#164 Status = ObReferenceObjectByHandle(DebugPort,
#165 DEBUG_OBJECT_ADD_REMOVE_PROCESS,
#166 DbgkDebugObjectType,
#167 PreviousMode,
#168 (PVOID*)&DebugObject,
#169 NULL);
#170 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#171
#172 /* Save the debug object */
#173 Process->DebugPort = DebugObject;
#174
#175 /* Check if the caller doesn't want the debug stuff inherited */
#176 if (Flags & PS_NO_DEBUG_INHERIT)
#177 {
#178 /* Set the process flag */
#179 InterlockedOr((PLONG)&Process->Flags, PSF_NO_DEBUG_INHERIT_BIT);
#180 }
#181 }
#182 else
#183 {
#184 /* Do we have a parent? Copy his debug port */
#185 if (Parent) DbgkCopyProcessDebugPort(Process, Parent);
#186 }
#187
检查是否有异常输出端口。
#188 /* Now check for an exception port */
#189 if (ExceptionPort)
#190 {
#191 /* Reference it */
#192 Status = ObReferenceObjectByHandle(ExceptionPort,
#193 PORT_ALL_ACCESS,
#194 LpcPortObjectType,
#195 PreviousMode,
#196 (PVOID*)&ExceptionPortObject,
#197 NULL);
#198 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#199
#200 /* Save the exception port */
#201 Process->ExceptionPort = ExceptionPortObject;
#202 }
#203
#204 /* Save the pointer to the section object */
#205 Process->SectionObject = SectionObject;
#206
保存进程退出码。
#207 /* Set default exit code */
#208 Process->ExitStatus = STATUS_TIMEOUT;
#209
检查是否有父进程。
#210 /* Check if this is the initial process being built */
#211 if (Parent)
#212 {
如果有父进程,就创建子进程空间。
#213 /* Create the address space for the child */
#214 if (!MmCreateProcessAddressSpace(MinWs,
#215 Process,
#216 DirectoryTableBase))
#217 {
#218 /* Failed */
#219 Status = STATUS_INSUFFICIENT_RESOURCES;
#220 goto CleanupWithRef;
#221 }
#222 }
#223 else
#224 {
#225 /* Otherwise, we are the boot process, we're already semi-initialized */
#226 Process->ObjectTable = CurrentProcess->ObjectTable;
#227 Status = MmInitializeHandBuiltProcess(Process, DirectoryTableBase);
#228 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#229 }
#230
设置进程已经分配了内存。
#231 /* We now have an address space */
#232 InterlockedOr((PLONG)&Process->Flags, PSF_HAS_ADDRESS_SPACE_BIT);
#233
#234 /* Set the maximum WS */
#235 Process->Vm.MaximumWorkingSetSize = MaxWs;
#236
调用函数KeInitializeProcess来初始化内核进程块。
#237 /* Now initialize the Kernel Process */
#238 KeInitializeProcess(&Process->Pcb,
#239 PROCESS_PRIORITY_NORMAL,
#240 Affinity,
#241 DirectoryTableBase,
#242 (BOOLEAN)(Process->DefaultHardErrorProcessing & 4));
#243
继承父进程的安全属性。
#244 /* Duplicate Parent Token */
#245 Status = PspInitializeProcessSecurity(Process, Parent);
#246 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#247
设置进程调试优先级。
#248 /* Set default priority class */
#249 Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
#250
根据父进程来微调进程的调试优先级。
#251 /* Check if we have a parent */
#252 if (Parent)
#253 {
#254 /* Check our priority class */
#255 if (Parent->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE ||
#256 Parent->PriorityClass == PROCESS_PRIORITY_CLASS_BELOW_NORMAL)
#257 {
#258 /* Normalize it */
#259 Process->PriorityClass = Parent->PriorityClass;
#260 }
#261
#262 /* Initialize object manager for the process */
#263 Status = ObInitProcess(Flags & PS_INHERIT_HANDLES ? Parent : NULL,
#264 Process);
#265 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#266 }
#267 else
#268 {
#269 /* Do the second part of the boot process memory setup */
#270 Status = MmInitializeHandBuiltProcess2(Process);
#271 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#272 }
#273
到这里已经创建进程成功了。
#274 /* Set success for now */
#275 Status = STATUS_SUCCESS;
#276
检查是否用户模式进程。
#277 /* Check if this is a real user-mode process */
#278 if (SectionHandle)
#279 {
创建用户模式进程的空间。
#280 /* Initialize the address space */
#281 Status = MmInitializeProcessAddressSpace(Process,
#282 NULL,
#283 SectionObject,
#284 &Flags,
#285 &Process->
#286 SeAuditProcessCreationInfo.
#287 ImageFileName);
#288 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#289 }
#290 else if (Parent)
#291 {
检查是否是系统进程的子进程。
#292 /* Check if this is a child of the system process */
#293 if (Parent != PsInitialSystemProcess)
#294 {
#295 /* This is a clone! */
#296 ASSERTMSG("No support for cloning yet/n", FALSE);
#297 }
#298 else
#299 {
这是一个系统进程初始化。
#300 /* This is the initial system process */
#301 Flags &= ~PS_LARGE_PAGES;
#302 Status = MmInitializeProcessAddressSpace(Process,
#303 NULL,
#304 NULL,
#305 &Flags,
#306 NULL);
#307 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#308
#309 /* Create a dummy image file name */
#310 Process->SeAuditProcessCreationInfo.ImageFileName =
#311 ExAllocatePoolWithTag(PagedPool,
#312 sizeof(OBJECT_NAME_INFORMATION),
#313 TAG('S', 'e', 'P', 'a'));
#314 if (!Process->SeAuditProcessCreationInfo.ImageFileName)
#315 {
#316 /* Fail */
#317 Status = STATUS_INSUFFICIENT_RESOURCES;
#318 goto CleanupWithRef;
#319 }
#320
#321 /* Zero it out */
#322 RtlZeroMemory(Process->SeAuditProcessCreationInfo.ImageFileName,
#323 sizeof(OBJECT_NAME_INFORMATION));
#324 }
#325 }
#326
检查是否需要对动态连接进行映射。
#327 /* Check if we have a section object and map the system DLL */
#328 if (SectionObject) PspMapSystemDll(Process, NULL, FALSE);
#329
为进程创建一个句柄。
#330 /* Create a handle for the Process */
#331 CidEntry.Object = Process;
#332 CidEntry.GrantedAccess = 0;
#333 Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry);
#334 if (!Process->UniqueProcessId)
#335 {
#336 /* Fail */
#337 Status = STATUS_INSUFFICIENT_RESOURCES;
#338 goto CleanupWithRef;
#339 }
#340
设置进程的进程标识号PID。
#341 /* Set the handle table PID */
#342 Process->ObjectTable->UniqueProcessId = Process->UniqueProcessId;
#343
#344 /* Check if we need to audit */
#345 if (SeDetailedAuditingWithToken(NULL)) SeAuditProcessCreate(Process);
#346
检查进程是否一个工作集运行。
#347 /* Check if the parent had a job */
#348 if ((Parent) && (Parent->Job))
#349 {
#350 /* FIXME: We need to insert this process */
#351 DPRINT1("Jobs not yet supported/n");
#352 ASSERT(FALSE);
#353 }
#354
为用户进程创建进程环境块PEB。
#355 /* Create PEB only for User-Mode Processes */
#356 if (Parent)
#357 {
#358 /* Create it */
#359 Status = MmCreatePeb(Process);
#360 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#361 }
#362
把刚创建的进程放到进程调试列表。
#363 /* The process can now be activated */
#364 KeAcquireGuardedMutex(&PspActiveProcessMutex);
#365 InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks);
#366 KeReleaseGuardedMutex(&PspActiveProcessMutex);
#367
创建进程访问状态。
#368 /* Create an access state */
#369 Status = SeCreateAccessStateEx(CurrentThread,
#370 ((Parent) &&
#371 (Parent == PsInitialSystemProcess)) ?
#372 Parent : CurrentProcess,
#373 &LocalAccessState,
#374 &AuxData,
#375 DesiredAccess,
#376 &PsProcessType->TypeInfo.GenericMapping);
#377 if (!NT_SUCCESS(Status)) goto CleanupWithRef;
#378
把进程放入到对象目录。
#379 /* Insert the Process into the Object Directory */
#380 Status = ObInsertObject(Process,
#381 AccessState,
#382 DesiredAccess,
#383 1,
#384 NULL,
#385 &hProcess);
#386
删除进程访问状态。
#387 /* Free the access state */
#388 if (AccessState) SeDeleteAccessState(AccessState);
#389
#390 /* Cleanup on failure */
#391 if (!NT_SUCCESS(Status)) goto Cleanup;
#392
计算进程运行时间片。
#393 /* Compute Quantum and Priority */
#394 ASSERT(IsListEmpty(&Process->ThreadListHead) == TRUE);
#395 Process->Pcb.BasePriority =
#396 (SCHAR)PspComputeQuantumAndPriority(Process,
#397 PsProcessPriorityBackground,
#398 &Quantum);
#399 Process->Pcb.QuantumReset = Quantum;
#400
#401 /* Check if we have a parent other then the initial system process */
#402 Process->GrantedAccess = PROCESS_TERMINATE;
#403 if ((Parent) && (Parent != PsInitialSystemProcess))
#404 {
#405 /* Get the process's SD */
#406 Status = ObGetObjectSecurity(Process,
#407 &SecurityDescriptor,
#408 &SdAllocated);
#409 if (!NT_SUCCESS(Status))
#410 {
#411 /* We failed, close the handle and clean up */
#412 ObCloseHandle(hProcess, PreviousMode);
#413 goto CleanupWithRef;
#414 }
#415
#416 /* Create the subject context */
#417 SubjectContext.ProcessAuditId = Process;
#418 SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
#419 SubjectContext.ClientToken = NULL;
#420
#421 /* Do the access check */
#422 Result = SeAccessCheck(SecurityDescriptor,
#423 &SubjectContext,
#424 FALSE,
#425 MAXIMUM_ALLOWED,
#426 0,
#427 NULL,
#428 &PsProcessType->TypeInfo.GenericMapping,
#429 PreviousMode,
#430 &Process->GrantedAccess,
#431 &AccessStatus);
#432
#433 /* Dereference the token and let go the SD */
#434 ObFastDereferenceObject(&Process->Token,
#435 SubjectContext.PrimaryToken);
#436 ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
#437
#438 /* Remove access if it failed */
#439 if (!Result) Process->GrantedAccess = 0;
#440
设置进程访问权。
#441 /* Give the process some basic access */
#442 Process->GrantedAccess |= (PROCESS_VM_OPERATION |
#443 PROCESS_VM_READ |
#444 PROCESS_VM_WRITE |
#445 PROCESS_QUERY_INFORMATION |
#446 PROCESS_TERMINATE |
#447 PROCESS_CREATE_THREAD |
#448 PROCESS_DUP_HANDLE |
#449 PROCESS_CREATE_PROCESS |
#450 PROCESS_SET_INFORMATION |
#451 STANDARD_RIGHTS_ALL |
#452 PROCESS_SET_QUOTA);
#453 }
#454 else
#455 {
#456 /* Set full granted access */
#457 Process->GrantedAccess = PROCESS_ALL_ACCESS;
#458 }
#459
设置进程创建时间。
#460 /* Set the Creation Time */
#461 KeQuerySystemTime(&Process->CreateTime);
#462
通过SEH机制来保护用户设置非法指针导致系统出错。
#463 /* Protect against bad user-mode pointer */
#464 _SEH2_TRY
#465 {
#466 /* Save the process handle */
#467 *ProcessHandle = hProcess;
#468 }
#469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
#470 {
#471 /* Get the exception code */
#472 Status = _SEH2_GetExceptionCode();
#473 }
#474 _SEH2_END;
#475
调用进程回调函数。
#476 /* Run the Notification Routines */
#477 PspRunCreateProcessNotifyRoutines(Process, TRUE);
#478
创建进程失败,要清除分配的资源。
#479 CleanupWithRef:
#480 /*
#481 * Dereference the process. For failures, kills the process and does
#482 * cleanup present in PspDeleteProcess. For success, kills the extra
#483 * reference added by ObInsertObject.
#484 */
#485 ObDereferenceObject(Process);
#486
#487 Cleanup:
#488 /* Dereference the parent */
#489 if (Parent) ObDereferenceObject(Parent);
#490
#491 /* Return status to caller */
#492 return Status;
#493 }
#494
通过上面的函数,就可以创建了一个系统进程,但我们知道Reactos的原理,它并不是以进程为最小的调度单位的,而是以线程为最小的调度单位,那么线程又是什么时候创建的呢?