reactos操作系统实现(53)

来源:互联网 发布:熊片数据库 bearx.org 编辑:程序博客网 时间:2024/04/29 21:31

在前面的代码分析里,发现创建一个线程,而这个线程运行的主函数是PnpEventThread。那么创建这个线程是用来做什么事情的呢?那就得去分析文件reactos/base/setup/usetup/interface/devinst.c里的代码,如下:

#001  DWORD WINAPI

#002  PnpEventThread(IN LPVOID lpParameter)

#003  {

#004      NTSTATUS Status;

#005 

#006       DPRINT1("DevicePnpEventThread 20090721/n");

#007 

 

调用函数EventThread来做真实的事件处理。

#008      Status = EventThread(lpParameter);

 

调用内核API函数NtTerminateThread来终止线程运行。

#009      NtTerminateThread(NtCurrentThread(),Status);

#010      return 0;

#011  }

 

继续查看函数EventThread的代码:

#001  NTSTATUS

#002  EventThread(IN LPVOID lpParameter)

#003  {

 

初始化两个准备使用的注册表键值。

#004      UNICODE_STRING EnumU =RTL_CONSTANT_STRING(L"//Registry//Machine//SYSTEM//CurrentControlSet//Enum");

#005      UNICODE_STRING ServicesU =RTL_CONSTANT_STRING(L"//Registry//Machine//SYSTEM//CurrentControlSet//Services");

#006      PPLUGPLAY_EVENT_BLOCK PnpEvent;

#007      OBJECT_ATTRIBUTES ObjectAttributes;

#008      ULONG PnpEventSize;

#009      HINF hInf;

#010      HANDLE hEnum, hServices;

#011      NTSTATUS Status;

#012 

 

获取参数。

#013      hInf = *(HINF *)lpParameter;

#014 

 

打开系统枚举键。

#015     InitializeObjectAttributes(&ObjectAttributes, &EnumU,OBJ_CASE_INSENSITIVE, NULL, NULL);

#016      Status = NtOpenKey(&hEnum, 0,&ObjectAttributes);

#017      if (!NT_SUCCESS(Status))

#018      {

#019          DPRINT1("NtOpenKey('%wZ') failedwith status 0x%08lx/n", &EnumU, Status);

#020          return Status;

#021      }

#022 

 

创建系统服务键。

#023     InitializeObjectAttributes(&ObjectAttributes,&ServicesU, OBJ_CASE_INSENSITIVE, NULL, NULL);

#024      Status = NtCreateKey(&hServices, 0,&ObjectAttributes, 0, NULL, 0, NULL);

#025      if (!NT_SUCCESS(Status))

#026      {

#027          DPRINT1("NtCreateKey('%wZ')failed with status 0x%08lx/n", &ServicesU, Status);

#028          NtClose(hEnum);

#029          return Status;

#030      }

#031 

 

分配使用堆内存空间。

#032      PnpEventSize = 0x1000;

#033      PnpEvent =(PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);

#034      if (PnpEvent == NULL)

#035      {

#036          NtClose(hEnum);

#037          NtClose(hServices);

#038          return STATUS_NO_MEMORY;

#039      }

#040 

 

循环地进行线程处理工作。

#041      for (;;)

#042      {

#043          DPRINT("CallingNtGetPlugPlayEvent()/n");

#044 

 

等待下一个即插即用事件。

#045          /* Wait for the next pnp event */

#046          Status = NtGetPlugPlayEvent(0, 0,PnpEvent, PnpEventSize);

#047 

 

是否前面分配的缓冲区太小。

#048          /* Resize the buffer for the PnPevent if it's too small. */

#049          if (Status ==STATUS_BUFFER_TOO_SMALL)

#050          {

#051              PnpEventSize += 0x400;

#052              RtlFreeHeap(ProcessHeap, 0,PnpEvent);

#053              PnpEvent =(PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);

#054              if (PnpEvent == NULL)

#055              {

#056                  NtClose(hEnum);

#057                  NtClose(hServices);

#058                  return STATUS_NO_MEMORY;

#059              }

#060              continue;

#061          }

#062 

 

等待事件出错处理。

#063          if (!NT_SUCCESS(Status))

#064          {

#065              DPRINT("NtPlugPlayEvent()failed (Status %lx)/n", Status);

#066              break;

#067          }

#068 

 

处理枚举的设备。

#069          /* Process the pnp event */

#070          DPRINT("Received PnPEvent/n");

#071          if(IsEqualIID(&PnpEvent->EventGuid, (REFGUID)&GUID_DEVICE_ENUMERATED))

#072          {

#073              DPRINT1("Device arrivalevent: %S/n", PnpEvent->TargetDevice.DeviceIds);

 

调用函数InstallDevice来安装设备。

#074              InstallDevice(hInf, hEnum,hServices, PnpEvent->TargetDevice.DeviceIds);

#075          }

#076          else

#077          {

#078              DPRINT("Unknownevent/n");

#079          }

#080 

 

通知可以处理下一个事件。

#081          /* Dequeue the current pnp event andsignal the next one */

#082         NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);

#083      }

#084 

#085      RtlFreeHeap(ProcessHeap, 0, PnpEvent);

#086      NtClose(hEnum);

#087      NtClose(hServices);

#088 

#089      return STATUS_SUCCESS;

#090  }

 

在函数EventThread里,主要就是循环地处理设备事件,调用函数InstallDevice来安装设备驱动程序。