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 + -
显示快捷键?