gendrv.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,827 行 · 第 1/4 页
C
1,827 行
if (is_if)
{
pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
}
else
{
pdrvr = pdev->dev_driver;
dev_obj = pdev->dev_obj;
}
if (dev_obj == NULL)
{
// it means no driver was found for the device and thus no device object created
// we just do nothing here
return TRUE;
}
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
}
else
TRAP();
pdev = NULL;
// remove the device from the list
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
RemoveEntryList(&pdev_ext->dev_obj_link);
pdev_ext->ext_drvr_entry->ref_count--;
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
// send message to class driver
gendrv_send_pnp_msg(GENDRV_MSG_DISCDEVICE, dev_obj, NULL);
// delete the device object
gendrv_delete_device(dev_mgr, dev_obj);
return TRUE;
}
BOOLEAN
gendrv_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
{
return gendrv_do_disconnect(dev_mgr, if_handle, TRUE);
}
BOOLEAN
gendrv_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
PGENDRV_DRVR_EXTENSION pdrvr_ext;
if (dev_mgr == NULL || pdriver == NULL)
return FALSE;
pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
pdriver->driver_desc.release_num = 0x100; // Release Number of Device
pdriver->driver_desc.config_val = 0; // Configuration Value
pdriver->driver_desc.if_num = 0; // Interface Number
pdriver->driver_desc.if_class = 0x0; // Interface Class
pdriver->driver_desc.if_sub_class = 0x0; // Interface SubClass
pdriver->driver_desc.if_protocol = 0x0; // Interface Protocol
pdriver->driver_desc.driver_name = "USB generic interface driver"; // Driver name for Name Registry
pdriver->driver_desc.dev_class = 0;
pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
//we have no extra data sturcture currently
pdriver->disp_tbl.version = 1;
pdriver->disp_tbl.dev_connect = gendrv_if_connect;
pdriver->disp_tbl.dev_disconnect = gendrv_if_disconnect;
pdriver->disp_tbl.dev_stop = gendrv_if_stop;
pdriver->disp_tbl.dev_reserved = NULL;
pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION));
pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION);
RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size);
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
// InitializeListHead( &pdrvr_ext->dev_list );
InitializeListHead(&pdrvr_ext->ext_drvr_list);
pdrvr_ext->ext_drvr_count = 0;
ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex);
return TRUE;
}
BOOLEAN
gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
{
PGENDRV_DRVR_EXTENSION pdrvr_ext;
PLIST_ENTRY pthis;
PGENDRV_EXT_DRVR_ENTRY pentry;
if (dev_mgr == NULL || pdriver == NULL)
return FALSE;
if (pdriver->driver_ext)
{
// should we lock it?
// ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
if (pdrvr_ext->ext_drvr_count)
{
while (IsListEmpty(&pdrvr_ext->ext_drvr_list))
{
pthis = RemoveHeadList(&pdrvr_ext->ext_drvr_list);
pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
if (pentry->pext_drvr)
{
if (pentry->ref_count)
{
// FIXME: really fail?
continue;
}
ObDereferenceObject(pentry->pext_drvr);
gendrv_release_ext_drvr_entry(pdrvr_ext, pentry);
}
}
pdrvr_ext->ext_drvr_count = 0;
}
usb_free_mem(pdriver->driver_ext);
pdriver->driver_ext = NULL;
pdriver->driver_ext_size = 0;
}
return TRUE;
}
PDRIVER_OBJECT
gendrv_open_ext_driver(PUNICODE_STRING unicode_string)
{
NTSTATUS status;
OBJECT_ATTRIBUTES oa;
HANDLE drvr_handle;
UNICODE_STRING oname;
PDRIVER_OBJECT pdrvr = NULL;
RtlZeroMemory(&oa, sizeof(oa));
oa.Length = sizeof(oa);
oa.ObjectName = &oname;
oa.Attributes = OBJ_CASE_INSENSITIVE;
RtlInitUnicodeString(&oname, L"");
RtlAppendUnicodeStringToString(&oname, unicode_string);
status = ObOpenObjectByName(&oa, IoDriverObjectType, // object type
KernelMode, // access mode
NULL, // access state
FILE_READ_DATA, // STANDARD_RIGHTS_READ, access right
NULL,
&drvr_handle);
if (status != STATUS_SUCCESS)
{
return NULL;
}
ObReferenceObjectByHandle(drvr_handle,
FILE_READ_DATA,
IoDriverObjectType,
KernelMode,
(PVOID)&pdrvr,
NULL); // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
ZwClose(drvr_handle);
return pdrvr;
}
BOOLEAN
gendrv_close_ext_driver(PDRIVER_OBJECT pdrvr)
{
if (pdrvr == NULL)
return FALSE;
ObDereferenceObject(pdrvr);
return TRUE;
}
NTSTATUS
gendrv_dispatch(PDEVICE_OBJECT dev_obj, PIRP irp)
{
IO_STACK_LOCATION *irpstack;
PUSB_DEV_MANAGER dev_mgr;
PDEVEXT_HEADER ext_hdr;
NTSTATUS status;
if (dev_obj == NULL || irp == NULL)
return STATUS_INVALID_PARAMETER;
ext_hdr = dev_obj->DeviceExtension;
dev_mgr = ext_hdr->dev_mgr;
irpstack = IoGetNextIrpStackLocation(irp);
switch (irpstack->MajorFunction)
{
case IRP_MJ_PNP_POWER:
{
irp->IoStatus.Information = 0;
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
}
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
{
status = STATUS_NOT_SUPPORTED;
if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD ||
irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR ||
irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO)
{
PURB purb;
DEV_HANDLE endp_handle;
PGENDRV_DEVICE_EXTENSION pdev_ext;
pdev_ext = dev_obj->DeviceExtension;
if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
{
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
}
purb = (PURB) irp->AssociatedIrp.SystemBuffer;
endp_handle = purb->endp_handle;
if (purb->data_buffer == NULL || purb->data_length == 0)
{
if (irpstack->Parameters.DeviceIoControl.IoControlCode != IOCTL_SUBMIT_URB_NOIO)
{
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
}
}
if (!default_endp_handle(endp_handle))
{
//no permit to other interface if interface dev
if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
}
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
}
else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC)
{
// this is a synchronous call, route to dev_mgr_dispatch
return dev_mgr_dispatch(dev_mgr, irp);
}
else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE)
{
PGENDRV_DEVICE_EXTENSION pdev_ext;
pdev_ext = dev_obj->DeviceExtension;
if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
*((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
irp->IoStatus.Information = sizeof(LONG);
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
}
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
}
case IRP_MJ_DEVICE_CONTROL:
{
status = STATUS_NOT_SUPPORTED;
if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD ||
irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR ||
irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO)
{
PURB purb;
DEV_HANDLE endp_handle;
PGENDRV_DEVICE_EXTENSION pdev_ext;
pdev_ext = dev_obj->DeviceExtension;
if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
{
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
}
purb = (PURB) irp->AssociatedIrp.SystemBuffer;
endp_handle = purb->endp_handle;
if (!default_endp_handle(endp_handle))
{
//no permit to other interface if interface dev
if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
}
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
}
else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC)
{
// this is a synchronous call, route to dev_mgr_dispatch
return dev_mgr_dispatch(dev_mgr, irp);
}
else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE)
{
PGENDRV_DEVICE_EXTENSION pdev_ext;
pdev_ext = dev_obj->DeviceExtension;
if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
*((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
irp->IoStatus.Information = sizeof(LONG);
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
}
GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
}
}
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
BOOLEAN
gendrv_init_dev_ext_hdr(PDEVICE_OBJECT dev_obj, PUSB_DEV_MANAGER dev_mgr)
{
PDEVEXT_HEADER dev_hdr = NULL;
if (dev_obj == NULL || dev_mgr == NULL)
return FALSE;
dev_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
dev_hdr->type = NTDEV_TYPE_CLIENT_DEV;
dev_hdr->dispatch = gendrv_dispatch;
dev_hdr->start_io = (PDRIVER_STARTIO) gendrv_startio;
return TRUE;
}
PDEVICE_OBJECT
gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle)
{
BOOLEAN is_if;
PDEVICE_OBJECT pdev;
PGENDRV_DEVICE_EXTENSION pdev_ext;
ULONG dev_id;
PGENDRV_DRVR_EXTENSION pdrvr_ext;
CHAR dev_name[64];
STRING string;
UNICODE_STRING name_string, symb_link;
NTSTATUS status;
if (dev_mgr == NULL || gen_drvr == NULL || dev_handle == 0)
return NULL;
is_if = (gen_drvr->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) ? 1 : 0;
usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_create_device(): entering...\n"));
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) gen_drvr->driver_ext;
dev_id = (UCHAR) dev_id_from_handle(dev_handle);
if (is_if == FALSE)
sprintf(dev_name, "\\Device\\gendev_%d", (int)dev_id);
else
sprintf(dev_name, "\\Device\\genifdev_%d", (int)dev_id);
RtlInitString(&string, dev_name);
RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
pdev = NULL;
status = IoCreateDevice(dev_mgr->usb_driver_obj,
sizeof(GENDRV_DEVICE_EXTENSION), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);
if (status == STATUS_SUCCESS)
{
//
// We do direct io
//
pdev->Flags |= DO_DIRECT_IO;
pdev->Flags &= ~DO_DEVICE_INITIALIZING;
pdev->StackSize = 2; //one for fdo, one for file device obj
pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev->DeviceExtension;
//may be accessed by other thread
gendrv_init_dev_ext_hdr(pdev, dev_mgr);
pdev_ext->dev_id = (UCHAR) dev_id;
pdev_ext->pdo = pdev;
pdev_ext->dev_handle = dev_handle;
pdev_ext->dev_mgr = dev_mgr;
pdev_ext->pdriver = gen_drvr;
if (is_if == FALSE)
sprintf(dev_name, "\\DosDevices\\gendev%d", (int)dev_id);
else
sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)dev_id);
RtlInitString(&string, dev_name);
RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
IoCreateSymbolicLink(&symb_link, &name_string);
RtlFreeUnicodeString(&symb_link);
KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
KeInitializeSpinLock(&pdev_ext->dev_lock);
}
RtlFreeUnicodeString(&name_string);
return pdev;
}
VOID
gendrv_deferred_delete_device(PVOID context)
{
PDEVICE_OBJECT dev_obj;
PGENDRV_DEVICE_EXTENSION pdev_ext;
PGENDRV_DRVR_EXTENSION pdrvr_ext;
LARGE_INTEGER interval;
if (context == NULL)
return;
dev_obj = (PDEVICE_OBJECT) context;
pdev_ext = dev_obj->DeviceExtension;
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
interval.QuadPart = -20000; //two ms
for(;;)
{
if (dev_obj->ReferenceCount)
KeDelayExecutionThread(KernelMode, TRUE, &interval);
else
{
KeDelayExecutionThread(KernelMode, TRUE, &interval);
if (dev_obj->ReferenceCount == 0)
break;
}
}
usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
RemoveEntryList(&pdev_ext->dev_obj_link);
pdev_ext->ext_drvr_entry->ref_count--;
ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
IoDeleteDevice(dev_obj);
return;
}
BOOLEAN
gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj)
{
BOOLEAN is_if;
PUSB_DRIVER pdrvr;
PGENDRV_DEVICE_EXTENSION pdev_ext;
CHAR dev_name[64];
STRING string;
UNICODE_STRING symb_link;
PGENDRV_DRVR_EXTENSION pdrvr_ext;
if (dev_mgr == NULL || dev_obj == 0)
return FALSE;
pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
pdrvr = pdev_ext->pdriver;
pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
is_if = (BOOLEAN) if_dev(dev_obj);
if (is_if == FALSE)
sprintf(dev_name, "\\DosDevices\\gendev%d", (int)pdev_ext->dev_id);
else
sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)pdev_ext->dev_id);
RtlInitString(&string, dev_name);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?