gendrv.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,827 行 · 第 1/4 页
C
1,827 行
return;
}
BOOLEAN
gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
if (dev_mgr == NULL)
return FALSE;
return gendrv_do_stop(dev_mgr, dev_handle, FALSE);
}
BOOLEAN
gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
if (dev_mgr == NULL)
return FALSE;
return gendrv_do_disconnect(dev_mgr, dev_handle, FALSE);
}
BOOLEAN
gendrv_build_reg_string(PUSB_DESC_HEADER pdesc, PUNICODE_STRING pus)
{
CHAR desc_str[128];
STRING atemp;
if (pdesc == NULL || pus == NULL)
return FALSE;
if (pdesc->bDescriptorType == USB_DT_DEVICE)
{
PUSB_DEVICE_DESC pdev_desc;
pdev_desc = (PUSB_DEVICE_DESC) pdesc;
sprintf(desc_str, "%sv_%04x&p_%04x",
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\",
pdev_desc->idVendor, pdev_desc->idProduct);
}
else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
{
PUSB_INTERFACE_DESC pif_desc;
pif_desc = (PUSB_INTERFACE_DESC) pdesc;
sprintf(desc_str, "%sc_%04x&s_%04x&p_%04x",
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\",
pif_desc->bInterfaceClass, pif_desc->bInterfaceSubClass, pif_desc->bInterfaceProtocol);
}
else
return FALSE;
RtlInitString(&atemp, desc_str);
RtlAnsiStringToUnicodeString(pus, &atemp, TRUE);
return TRUE;
}
ULONG
gendrv_make_key(PUSB_DESC_HEADER pdesc)
{
PUSB_DEVICE_DESC pdev_desc;
PUSB_INTERFACE_DESC pif_desc;
if (pdesc == NULL)
return (ULONG) - 1;
if (pdesc->bDescriptorType == USB_DT_DEVICE)
{
pdev_desc = (PUSB_DEVICE_DESC) pdesc;
return ((((ULONG) pdev_desc->idVendor) << 16) | pdev_desc->idProduct);
}
else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
{
pif_desc = (PUSB_INTERFACE_DESC) pdesc;
return ((((ULONG) pif_desc->bInterfaceClass) << 16) |
(((ULONG) pif_desc->bInterfaceSubClass) << 8) | ((ULONG) pif_desc->bInterfaceProtocol));
}
return (ULONG) - 1;
}
PDRIVER_OBJECT
gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key)
{
PGENDRV_EXT_DRVR_ENTRY pentry;
PLIST_ENTRY pthis, pnext;
if (pdrvr_ext == NULL || key == (ULONG) - 1)
return NULL;
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
while (pthis)
{
pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
if (pentry->drvr_key == key)
{
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
return pentry->pext_drvr;
}
ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
pthis = pnext;
}
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
return NULL;
}
PDRIVER_OBJECT
gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc)
{
PDRIVER_OBJECT pdrvr_obj;
PGENDRV_EXT_DRVR_ENTRY pentry;
UNICODE_STRING usz, svc_name, svc_key, utemp;
PKEY_VALUE_FULL_INFORMATION val_info;
PWCHAR val_buf;
HANDLE handle;
NTSTATUS status;
if (pdrvr_ext == NULL || pdesc == NULL)
return NULL;
// try to search and load driver from outside
handle = NULL;
RtlZeroMemory(&svc_key, sizeof(svc_key));
val_info = NULL;
RtlInitUnicodeString(&usz, L"");
gendrv_build_reg_string(pdesc, &usz);
DbgPrint("UHCI: Trying to load driver %wZ\n", &usz);
if (gendrv_open_reg_key(&handle, NULL, &usz, KEY_READ, FALSE) != STATUS_SUCCESS)
{
goto ERROR_OUT;
}
if (gendrv_get_key_value(handle, L"service", &val_info) != STATUS_SUCCESS)
{
goto ERROR_OUT;
}
if (val_info->DataLength > 32)
goto ERROR_OUT;
val_buf = (PWCHAR) (((PBYTE) val_info) + val_info->DataOffset);
svc_key.Length = 0, svc_key.MaximumLength = 255;
svc_key.Buffer = usb_alloc_mem(NonPagedPool, 256);
RtlInitUnicodeString(&utemp, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
RtlAppendUnicodeStringToString(&svc_key, &utemp);
RtlInitUnicodeString(&svc_name, val_buf);
RtlAppendUnicodeStringToString(&svc_key, &svc_name);
status = ZwLoadDriver(&svc_key);
if (status != STATUS_SUCCESS)
goto ERROR_OUT;
svc_key.Length = 0;
RtlZeroMemory(svc_key.Buffer, 128);
RtlInitUnicodeString(&svc_key, L"\\Driver\\");
RtlAppendUnicodeStringToString(&svc_key, &svc_name);
pdrvr_obj = gendrv_open_ext_driver(&svc_key);
if (pdrvr_obj == NULL)
goto ERROR_OUT;
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
// insert the driver to the drvr list
pentry = gendrv_alloc_ext_drvr_entry(pdrvr_ext);
if (pentry == NULL)
{
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
ObDereferenceObject(pdrvr_obj);
goto ERROR_OUT;
}
pentry->pext_drvr = pdrvr_obj;
InsertTailList(&pdrvr_ext->ext_drvr_list, &pentry->drvr_link);
pdrvr_ext->ext_drvr_count++;
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
ZwClose(handle);
return pdrvr_obj;
ERROR_OUT:
RtlFreeUnicodeString(&usz);
if (val_info != NULL)
{
usb_free_mem(val_info);
val_info = NULL;
}
if (svc_key.Buffer)
usb_free_mem(svc_key.Buffer);
if (handle)
ZwClose(handle);
return NULL;
}
VOID
gendrv_release_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PDRIVER_OBJECT pdrvr_obj)
{
PLIST_ENTRY pthis, pnext;
PGENDRV_EXT_DRVR_ENTRY pentry;
if (pdrvr_ext == NULL || pdrvr_obj == NULL)
return;
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
while (pthis)
{
pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
if (pentry->pext_drvr == pdrvr_obj)
{
ASSERT(pentry->ref_count);
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
return;
}
ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
pthis = pnext;
}
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
}
NTSTATUS
gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx)
{
if (pdev_obj == NULL)
return STATUS_INVALID_PARAMETER;
switch (msg)
{
case GENDRV_MSG_ADDDEVICE:
{
PDRIVER_OBJECT pdrvr_obj;
if (pctx == NULL)
return STATUS_INVALID_PARAMETER;
pdrvr_obj = (PDRIVER_OBJECT) pctx;
if (pdrvr_obj->DriverExtension)
{
return pdrvr_obj->DriverExtension->AddDevice(pdrvr_obj, pdev_obj);
}
return STATUS_IO_DEVICE_ERROR;
}
case GENDRV_MSG_STOPDEVICE:
case GENDRV_MSG_DISCDEVICE:
{
NTSTATUS status;
IO_STACK_LOCATION *irpstack;
IRP *irp;
// IRP_MJ_PNP_POWER
irp = IoAllocateIrp(2, FALSE);
if (irp == NULL)
return STATUS_NO_MEMORY;
irpstack = IoGetNextIrpStackLocation(irp);
irpstack->MajorFunction = IRP_MJ_PNP_POWER;
irpstack->MinorFunction =
(msg == GENDRV_MSG_STOPDEVICE) ? IRP_MN_STOP_DEVICE : IRP_MN_REMOVE_DEVICE;
status = IoCallDriver(pdev_obj, irp);
ASSERT(status != STATUS_PENDING);
status = irp->IoStatus.Status;
IoFreeIrp(irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
}
return STATUS_INVALID_PARAMETER;
}
BOOLEAN
gendrv_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle)
{
//
// try to search the registry to find one driver.
// if found, create the PDO, load the driver.
// and call its AddDevice.
//
LONG if_idx, i;
NTSTATUS status;
PUSB_DEV pdev;
PUSB_DRIVER pdrvr;
PUSB_INTERFACE_DESC pif_desc;
PGENDRV_DEVICE_EXTENSION pdev_ext;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_DEV_MANAGER dev_mgr;
PGENDRV_DRVR_EXTENSION pdrvr_ext;
PGENDRV_EXT_DRVR_ENTRY pentry;
PDEVICE_OBJECT pdev_obj;
PDRIVER_OBJECT pdrvr_obj;
PLIST_ENTRY pthis, pnext;
USE_BASIC_NON_PENDING_IRQL;
pdev = NULL;
usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): entering...\n"));
if (params == NULL)
return FALSE;
dev_mgr = params->dev_mgr;
pdrvr = params->pdriver;
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
if (status != STATUS_SUCCESS)
{
goto ERROR_OUT;
}
// obtain the pointer to the config desc, the dev won't go away in this routine
pconfig_desc = pdev->usb_config->pusb_config_desc; //
usb_unlock_dev(pdev);
pdev = NULL;
if_idx = if_idx_from_handle(if_handle);
pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
for(i = 0; i < if_idx; i++)
{
//search for our if
if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
break;
}
if (pif_desc == NULL)
return FALSE;
//
// well, let's do the hard work to see if there is a class driver
// for this device.
//
i = gendrv_make_key((PUSB_DESC_HEADER) pif_desc);
if (i == -1)
{
return FALSE;
}
pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i);
if (!pdrvr_obj)
{
if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pif_desc)) == NULL)
return FALSE;
}
pdev_obj = gendrv_create_device(dev_mgr, pdrvr, if_handle);
if (pdev_obj == NULL)
{
goto ERROR_OUT;
}
lock_dev(pdev, FALSE);
if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
{
unlock_dev(pdev, FALSE);
gendrv_delete_device(dev_mgr, pdev_obj);
goto ERROR_OUT;
}
if (pdev->usb_config)
{
pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
pdev->usb_config->interf[if_idx].if_ext_size = 0;
}
unlock_dev(pdev, FALSE);
pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512);
RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512);
pdev_ext->if_ctx.pif_desc =
(PUSB_INTERFACE_DESC) & pdev_ext->desc_buf[(PBYTE) pif_desc - (PBYTE) pconfig_desc];
// insert the device to the dev_list
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
pentry = NULL;
while (pthis)
{
pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
if (pentry->pext_drvr == pdrvr_obj)
break;
ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
pthis = pnext;
pentry = NULL;
}
ASSERT(pentry);
InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link);
pdev_ext->ext_drvr_entry = pentry;
pentry->ref_count++;
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
// notify the class driver, some device comes
gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj);
usb_unlock_dev(pdev);
return TRUE;
ERROR_OUT:
usb_unlock_dev(pdev);
return FALSE;
}
BOOLEAN
gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOLEAN is_if)
{
PUSB_DEV pdev;
PDEVICE_OBJECT pdev_obj;
ULONG if_idx;
if (dev_mgr == NULL)
return FALSE;
// clean up the irps
if_idx = if_idx_from_handle(dev_handle);
if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
{
return FALSE;
}
if (is_if && pdev->usb_config)
pdev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
else
pdev_obj = pdev->dev_obj;
gendrv_clean_up_queued_irps(pdev_obj);
usb_unlock_dev(pdev);
// send message to class drivers.
gendrv_send_pnp_msg(GENDRV_MSG_STOPDEVICE, pdev_obj, NULL);
return TRUE;
}
BOOLEAN
gendrv_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
{
if (dev_mgr == NULL)
return FALSE;
return gendrv_do_stop(dev_mgr, dev_handle, TRUE);
}
BOOLEAN
gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOLEAN is_if)
{
PUSB_DEV pdev;
PDEVICE_OBJECT dev_obj = NULL;
NTSTATUS status;
PUSB_DRIVER pdrvr;
PGENDRV_DRVR_EXTENSION pdrvr_ext = NULL;
PGENDRV_DEVICE_EXTENSION pdev_ext = NULL;
ULONG if_idx;
status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
if (pdev == NULL)
{
return FALSE;
}
if (status == STATUS_SUCCESS)
{
// must be a bug
TRAP();
}
if_idx = if_idx_from_handle(if_handle);
if (pdev->usb_config)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?