Windows设备驱动加载流程 - CHINAUNIX
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
RtlInitUnicodeString(&DeviceIdU, DeviceId); InitializeObjectAttributes(&ObjectAttributes, &DeviceIdU, 0, hEnum, NULL); Status = NtOpenKey(&hDeviceKey, KEY_QUERY_VALUE | KEY_SET_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) {
ServicesU
=
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
2
PPLUGPLAY_EVENT_BLOCK PnpEvent; OBJECT_ATTRIBUTES ObjectAtt hInf; HANDLE hEnum, hServices; NTSTATUS Status;
if (!ServiceStatusHandle) {
DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError()); return; }
UpdateServiceStatus(SERVICE_START_PENDING);
PnpEventSize += 0x400; RtlFreeHeap(ProcessHeap, 0, PnpEvent); PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize); if (PnpEvent == NULL) {
{
DPRINT1("RtlAllocateHeap() failed\n");
NtClose(hDeviceKey);
return;
}
Status = NtQueryValueKey(
hDeviceKey,
&HardwareIDU,
KeyValuePartialInformation,
pPartialInformation,
DPRINT("ServiceMain() done\n"); }
PnpEventThread 接 受 即 插 即 用 事 件 并 放 入 DeviceInstallListHead 中 。 然 后 用 SetEvent(hDeviceInstallListNotEmpty) 通知 DeviceInstallThread 线程安装驱动程序:static BOOL InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard) 此函数设置 named pipe,调用用 户空间 newdev.dll 安装驱动程序。 /* Launch rundll32 to call ClientSideInstallW */
NTSTATUS
EventThread(IN LPVOID lpParameter)
{
UNICODE_STRING
EnumU
=
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
UNICODE_STRING
NtClose(hEnum); NtClose(hServices); return STATUS_NO_MEMORY; } continue; }
if (!NT_SUCCESS(Status)) {
DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status); break; }
hThread = CreateThread(NULL, 0, DeviceInstallThread, NULL, 0, &dwThreadId);
if (hThread != NULL) CloseHandle(hThread);
UpdateServiceStatus(SERVICE_RUNNING);
HANDLE hThread; DWORD dwThreadId;
UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv);
DPRINT("ServiceMain() called\n");
ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, ServiceControlHandler, NULL);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
pPartialInformation
=
(PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
5
if (!pPartialInformation)
Status = NtCreateKey(&hServices, 0, &ObjectAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) {
DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU, Status); NtClose(hEnum); return Status; }
/* Process the pnp event */
DPRINT("Received PnP Event\n");
if
(IsEqualIID(&PnpEvent->EventGuid,
(REFGUID)&GUID_DEVICE_ENUMERATED))
{
DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
ulRequired,
wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall "); wcscat(CommandLine, PipeName);
用户程序根据系统传来的参数查找相应的 inf 和驱动程序后: 产生事件通知 devins.c 中的 eventthread 程序处理。
DPRINT("Unable to open subkey '%S'\n", DeviceId); return; }
Status = NtQueryValueKey(
hDeviceKey,
&HardwareIDU,
KeyValuePartialInformation,
NULL,
0,
&ulRequired);
InstallDevice(hInf, hEnum, hServices, PnpEvent->TargetDevice.DeviceIds);
}
else
{
DPRINT("Unknown event\n");
}
/* Dequeue the current pnp event and signal the next one */ NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0); }
hThread = CreateThread(NULL, 0, PnpEventThread, NULL, 0, &dwThreadId);
if (hThread != NULL) CloseHandle(hThread);
hThread = CreateThread(NULL, 0,
1
RpcServerThread, NULL, 0, &dwThreadId); if (hThread != NULL) CloseHandle(hThread);
DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status); return Status; }
InitializeObjectAttributes(&ObjectAttributes, &ServicesU, OBJ_CASE_INSENSITIVE, NULL, NULL);
for (;;) {
DPRINT("Calling NtGetPlugPlayEvent()\n");
/* Wait for the next pnp event */ Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
3
/* Resize the buffer for the PnP event if it's too small. */ if (Status == STATUS_BUFFER_TOO_SMALL) {
PnpEventSize = 0x1000; PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize); if (PnpEvent == NULL) {
NtClose(hEnum); NtClose(hServices); return STATUS_NO_MEMORY; }
Windows 设备驱动加载流程
王瑞涛
今天老大给了任务弄 windows 的驱动,晕啊,一直在玩 linux 和 vx。完全不懂 windows 的东 西。找了个山寨版 windows 看了看加载驱动程序的过程,怕忘了摘了点代码弄个大概流程 记录一下。不知道对不对。
1, windows 通过内核响应总线传来的即插即用事件来加载驱动程序。 首先系统启动是会建立关于 plugandplay 的三个线程 代码如下: static VOID CALLBACK ServiceMain(DWORD argc, LPTSTR *argv) {
RtlFreeHeap(ProcessHeap, 0, PnpEvent); NtClose(hEnum); NtClose(hServices);
4
return STATUS_SUCCESS; } 函数获取事件,调用 InstallDevice 程序
VOID InstallDevice(
IN HINF hInf, IN HANDLE hEnum, IN HANDLE hServices, IN LPCWSTR DeviceId) { UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); UNICODE_STRING CompatibleIDsU = RTL_CONSTANT_STRING(L"CompatibleIDs"); UNICODE_STRING DeviceIdU; OBJECT_ATTRIBUTES ObjectAttributes; LPCWSTR HardwareID; PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation = NULL; HANDLE hDeviceKey; ULONG ulRequired; BOOLEAN bDriverInstalled = FALSE; NTSTATUS Status;
hInf = *(HINF *)lpParameter;
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenKey(&hEnum, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) {