reactos操作系统实现(53)
在前面的代码分析里,发现创建一个线程,而这个线程运行的主函数是PnpEventThread。那么创建这个线程是用来做什么事情的呢?那就得去分析文件reactos/base/setup/usetup/interface/devinst.c里的代码,如下: #001 DWORD WINAPI #002 PnpEventThread(IN LPVOID lpParameter) #003 { #004 NTSTATUS Status; #005 #006 DPRINT1("Device PnpEventThread 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,&ObjectAttributes); #017 if (!NT_SUCCESS(Status)) #018 { #019 DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx/n",Status); #020 return Status; #021 } #022
创建系统服务键。 #023 InitializeObjectAttributes(&ObjectAttributes,&ServicesU,NULL); #024 Status = NtCreateKey(&hServices,&ObjectAttributes,NULL); #025 if (!NT_SUCCESS(Status)) #026 { #027 DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx/n",Status); #028 NtClose(hEnum); #029 return Status; #030 } #031
分配使用堆内存空间。 #032 PnpEventSize = 0x1000; #033 PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap,PnpEventSize); #034 if (PnpEvent == NULL) #035 { #036 NtClose(hEnum); #037 NtClose(hServices); #038 return STATUS_NO_MEMORY; #039 } #040
循环地进行线程处理工作。 #041 for (;;) #042 { #043 DPRINT("Calling NtGetPlugPlayEvent()/n"); #044
等待下一个即插即用事件。 #045 /* Wait for the next pnp event */ #046 Status = NtGetPlugPlayEvent(0,PnpEvent,PnpEventSize); #047
是否前面分配的缓冲区太小。 #048 /* Resize the buffer for the PnP event if it's too small. */ #049 if (Status == STATUS_BUFFER_TOO_SMALL) #050 { #051 PnpEventSize += 0x400; #052 RtlFreeHeap(ProcessHeap,PnpEvent); #053 PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap,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 PnP Event/n"); #071 if (IsEqualIID(&PnpEvent->EventGuid,(REFGUID)&GUID_DEVICE_ENUMERATED)) #072 { #073 DPRINT1("Device arrival event: %S/n",PnpEvent->TargetDevice.DeviceIds);
调用函数InstallDevice来安装设备。 #074 InstallDevice(hInf,hEnum,hServices,PnpEvent->TargetDevice.DeviceIds); #075 } #076 else #077 { #078 DPRINT("Unknown event/n"); #079 } #080
通知可以处理下一个事件。 #081 /* Dequeue the current pnp event and signal the next one */ #082 NtPlugPlayControl(PlugPlayControlUserResponse,0); #083 } #084 #085 RtlFreeHeap(ProcessHeap,PnpEvent); #086 NtClose(hEnum); #087 NtClose(hServices); #088 #089 return STATUS_SUCCESS; #090 } 在函数 EventThread 里,主要就是循环地处理设备事件,调用函数 InstallDevice 来安装设备驱动程序。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |