reactos操作系统实现(37)

下面来继续分析创建进程函数,过程如下:

保存工作集数据。

#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的原理,它并不是以进程为最小的调度单位的,而是以线程为最小的调度单位,那么线程又是什么时候创建的呢?

你可能感兴趣的:(exception,object,null,Class,Access,reference)