Ejemplo n.º 1
0
static NTSTATUS UsbChief_QueuePassiveLevelCallback(IN WDFDEVICE    Device,
				   IN WDFUSBPIPE   Pipe)
{
	NTSTATUS                       status = STATUS_SUCCESS;
	PWORKITEM_CONTEXT               context;
	WDF_OBJECT_ATTRIBUTES           attributes;
	WDF_WORKITEM_CONFIG             workitemConfig;
	WDFWORKITEM                     hWorkItem;

	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, WORKITEM_CONTEXT);
	attributes.ParentObject = Device;

	WDF_WORKITEM_CONFIG_INIT(&workitemConfig, UsbChief_ReadWriteWorkItem);

	status = WdfWorkItemCreate( &workitemConfig,
				    &attributes,
				    &hWorkItem);

	if (!NT_SUCCESS(status))
		return status;

	context = GetWorkItemContext(hWorkItem);

	context->Device = Device;
	context->Pipe = Pipe;

	WdfWorkItemEnqueue(hWorkItem);
	return STATUS_SUCCESS;
}
Ejemplo n.º 2
0
NTSTATUS
QueuePassiveLevelCallback(
  _In_ WDFDEVICE  Device,
  _In_ WDFUSBPIPE Pipe
)
/*++

Routine Description:

    This routine is used to queue workitems so that the callback
    functions can be executed at PASSIVE_LEVEL in the context of
    a system thread.

Arguments:

Return Value:

--*/
{
  NTSTATUS              status = STATUS_SUCCESS;
  PWORKITEM_CONTEXT     context;
  WDF_OBJECT_ATTRIBUTES attributes;
  WDF_WORKITEM_CONFIG   workitemConfig;
  WDFWORKITEM           hWorkItem;

  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, WORKITEM_CONTEXT);
  attributes.ParentObject = Device;

  WDF_WORKITEM_CONFIG_INIT(&workitemConfig, Rio500_EvtReadWriteWorkItem);

  status = WdfWorkItemCreate(
    &workitemConfig,
    &attributes,
    &hWorkItem
  );

  if (!NT_SUCCESS(status)) {
    return status;
  }

  context = GetWorkItemContext(hWorkItem);

  context->Device = Device;
  context->Pipe = Pipe;

  //
  // Execute this work item.
  //
  WdfWorkItemEnqueue(hWorkItem);

  return STATUS_SUCCESS;
}
Ejemplo n.º 3
0
void CyapaBootTimer(_In_ WDFTIMER hTimer) {
	WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer);
	PDEVICE_CONTEXT pDevice = GetDeviceContext(Device);

	WDF_OBJECT_ATTRIBUTES attributes;
	WDF_WORKITEM_CONFIG workitemConfig;
	WDFWORKITEM hWorkItem;

	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
	attributes.ParentObject = Device;
	WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CyapaBootWorkItem);

	WdfWorkItemCreate(&workitemConfig,
		&attributes,
		&hWorkItem);

	WdfWorkItemEnqueue(hWorkItem);
	WdfTimerStop(hTimer, FALSE);
}
NTSTATUS AndroidUsbWdfObject::InitObjectAttributes(
    PWDF_OBJECT_ATTRIBUTES wdf_obj_attr,
    WDFOBJECT parent) {
  ASSERT_IRQL_LOW();

  // Enforce file object extension exception.
  ASSERT(!Is(AndroidUsbWdfObjectTypeFile));
  if (Is(AndroidUsbWdfObjectTypeFile))
    return STATUS_INTERNAL_ERROR;

  // Initialize attributes and set cleanup and destroy callbacks
  WDF_OBJECT_ATTRIBUTES_INIT(wdf_obj_attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(wdf_obj_attr,
                                         AndroidUsbWdfObjectContext);
  wdf_obj_attr->EvtCleanupCallback = EvtCleanupCallbackEntry;
  wdf_obj_attr->EvtDestroyCallback = EvtDestroyCallbackEntry;
  wdf_obj_attr->ParentObject = parent;
  wdf_obj_attr->SynchronizationScope = GetWdfSynchronizationScope();

  return STATUS_SUCCESS;
}
Ejemplo n.º 5
0
VOID
VIOSerialPortPnpNotify (
    IN WDFDEVICE WdfDevice,
    IN PVIOSERIAL_PORT port,
    IN BOOLEAN connected
)
{
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_WORKITEM_CONFIG   workitemConfig;
    WDFWORKITEM           hWorkItem;
    PRAWPDO_VIOSERIAL_PORT  pdoData = NULL;
    NTSTATUS              status = STATUS_SUCCESS;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);
    port->HostConnected = connected;

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
    attributes.ParentObject = WdfDevice;
    WDF_WORKITEM_CONFIG_INIT(&workitemConfig, VIOSerialPortPnpNotifyWork);

    status = WdfWorkItemCreate( &workitemConfig,
                                 &attributes,
                                 &hWorkItem);

    if (!NT_SUCCESS(status))
    {
       TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "WdfWorkItemCreate failed with status = 0x%08x\n", status);
       return;
    }

    pdoData = RawPdoSerialPortGetData(hWorkItem);

    pdoData->port = port;

    WdfWorkItemEnqueue(hWorkItem);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
}
NTSTATUS AndroidUsbPipeFileObject::QueueResetPipePassiveCallback() {
  ASSERT_IRQL_LOW_OR_DISPATCH();

  // Initialize workitem
  WDF_OBJECT_ATTRIBUTES attr;
  WDF_OBJECT_ATTRIBUTES_INIT(&attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attr, AndroidUsbWorkitemContext);
  attr.ParentObject = wdf_device();

  WDFWORKITEM wdf_work_item = NULL;
  WDF_WORKITEM_CONFIG workitem_config;
  WDF_WORKITEM_CONFIG_INIT(&workitem_config, ResetPipePassiveCallbackEntry);
  NTSTATUS status = WdfWorkItemCreate(&workitem_config,
                                      &attr,
                                      &wdf_work_item);
  ASSERT(NT_SUCCESS(status) && (NULL != wdf_work_item));
  if (!NT_SUCCESS(status))
    return status;

  // Initialize our extension to work item
  AndroidUsbWorkitemContext* context =
    GetAndroidUsbWorkitemContext(wdf_work_item);
  ASSERT(NULL != context);
  if (NULL == context) {
    WdfObjectDelete(wdf_work_item);
    return STATUS_INTERNAL_ERROR;
  }

  context->object_type = AndroidUsbWdfObjectTypeWorkitem;
  context->pipe_file_ext = this;

  // Enqueue this work item.
  WdfWorkItemEnqueue(wdf_work_item);

  return STATUS_SUCCESS;
}
Ejemplo n.º 7
0
/*++
Routine Description:

EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent a new instance of the device. All the software resources
should be allocated in this callback.

Arguments:

Driver - Handle to a framework driver object created in DriverEntry

DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

NTSTATUS
--*/
NTSTATUS PSDrv_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
    WDF_FILEOBJECT_CONFIG				fileConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               fdoAttributes;
    WDF_OBJECT_ATTRIBUTES               fileObjectAttributes;
    WDF_OBJECT_ATTRIBUTES               requestAttributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;
    ULONG                               maximumTransferSize;

    UNREFERENCED_PARAMETER(Driver);

    PSDrv_DbgPrint (3, ("PSDrv_EvtDeviceAdd - begins\n"));

    PAGED_CODE();

    // Initialize the pnpPowerCallbacks structure.  Callback events for PNP
    // and Power are specified here.  If you don't supply any callbacks,
    // the Framework will take appropriate default actions based on whether
    // DeviceInit is initialized to be an FDO, a PDO or a filter device
    // object.
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware = PSDrv_EvtDevicePrepareHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    // Initialize the request attributes to specify the context size and type
    // for every request created by framework for this device.
    WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT);

    WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes);

    // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
    // framework whether you are interested in handle Create, Close and
    // Cleanup requests that gets generate when an application or another
    // kernel component opens an handle to the device. If you don't register
    // the framework default behaviour would be complete these requests
    // with STATUS_SUCCESS. A driver might be interested in registering these
    // events if it wants to do security validation and also wants to maintain
    // per handle (fileobject) context.
    WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PSDrv_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK);

    // Specify a context for FileObject. If you register FILE_EVENT callbacks,
    // the framework by default creates a framework FILEOBJECT corresponding
    // to the WDM fileobject. If you want to track any per handle context,
    // use the context for FileObject. Driver that typically use FsContext
    // field should instead use Framework FileObject context.
    WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT);

    WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes);

    // We can do iso transfer only if the io type is directio.
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);

    // Now specify the size of device extension where we track per device
    // context.DeviceInit is completely initialized. So call the framework
    // to create the device and attach it to the lower stack.
    WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfDeviceCreate failed! (Status = %x)\n", status));
        return status;
    }

    // Get the DeviceObject context by using accessory function specified in
    // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
    pDevContext = GetDeviceContext(device);

    //Get MaximumTransferSize from registry
    maximumTransferSize=0;

    status = ReadFdoRegistryKeyValue(Driver, L"MaximumTransferSize", &maximumTransferSize);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("ReadFdoRegistryKeyValue failed with Status code %!STATUS!\n", status));
        return status;
    }

    if (maximumTransferSize)
	{
        pDevContext->MaximumTransferSize = maximumTransferSize;
    }
    else
	{
        pDevContext->MaximumTransferSize = DEFAULT_REGISTRY_TRANSFER_SIZE;
    }

    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermode (on Win2K) when you surprise
    // remove the device.
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

	// Do not show the little green remove icon
    pnpCaps.SurpriseRemovalOK = WdfTrue;

/*
	// Show the little green remove icon...
	pnpCaps.SurpriseRemovalOK = WdfFalse;
	pnpCaps.Removable = WdfTrue;
*/

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    // Register I/O callbacks to tell the framework that you are interested
    // in handling WdfRequestTypeRead, WdfRequestTypeWrite, and IRP_MJ_DEVICE_CONTROL requests.
    // WdfIoQueueDispatchParallel means that we are capable of handling
    // all the I/O request simultaneously and we are responsible for protecting
    // data that could be accessed by these callbacks simultaneously.
    // This queue will be,  by default,  auto managed by the framework with
    // respect to PNP and Power events. That is, framework will take care
    // of queuing, failing, dispatching incoming requests based on the current
    // pnp/power state of the device.
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoRead = PSDrv_EvtIoRead;
    ioQueueConfig.EvtIoWrite = PSDrv_EvtIoWrite;
    ioQueueConfig.EvtIoDeviceControl = PSDrv_EvtIoDeviceControl;
    ioQueueConfig.EvtIoStop = PSDrvEvtIoStop;
    ioQueueConfig.EvtIoResume = PSDrvEvtIoResume;

    status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfIoQueueCreate failed! (Status = %x)\n", status));
        return status;
    }

    // Register a device interface so that app can find our device and talk to it.
    status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_PSDRV_USB, NULL);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfDeviceCreateDeviceInterface failed! (Status = %x)\n", status));
        return status;
    }

    PSDrv_DbgPrint(3, ("PSDrv_EvtDeviceAdd - ends\n"));

    return status;
}
Ejemplo n.º 8
0
NTSTATUS
SimTcDriverDeviceAdd (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )

/*++

Routine Description:

    EvtDriverDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. A WDF device object is created and initialized to
    represent a new instance of the battery device.

Arguments:

    Driver - Supplies a handle to the WDF Driver object.

    DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT 
        structure.

Return Value:

    NTSTATUS

--*/

{

    PFDO_DATA DevExt;
    WDF_OBJECT_ATTRIBUTES DeviceAttributes;
    WDFDEVICE DeviceHandle;
    WDF_QUERY_INTERFACE_CONFIG QueryInterfaceConfig;
    NTSTATUS Status;
    THERMAL_DEVICE_INTERFACE ThermalDeviceInterface;

    UNREFERENCED_PARAMETER(Driver);

    DebugEnter();
    PAGED_CODE();

    //
    // Initialize attributes and a context area for the device object.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&DeviceAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, FDO_DATA);

    //
    // Create a framework device object.  This call will in turn create
    // a WDM device object, attach to the lower stack, and set the
    // appropriate flags and attributes.
    //

    Status = WdfDeviceCreate(&DeviceInit, &DeviceAttributes, &DeviceHandle);
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMTC_ERROR, "WdfDeviceCreate() Failed. 0x%x\n", Status);
        goto DriverDeviceAddEnd;
    }

    //
    // Create a driver interface for this device to advertise the thermal 
    // cooling interface.
    //

    RtlZeroMemory(&ThermalDeviceInterface, sizeof(ThermalDeviceInterface));

    ThermalDeviceInterface.Size =
        sizeof(ThermalDeviceInterface);

    ThermalDeviceInterface.Version = 1;

    ThermalDeviceInterface.Context = DeviceHandle;
    ThermalDeviceInterface.InterfaceReference =
        WdfDeviceInterfaceReferenceNoOp;

    ThermalDeviceInterface.InterfaceDereference =
        WdfDeviceInterfaceDereferenceNoOp;

    ThermalDeviceInterface.Flags = ThermalDeviceFlagPassiveCooling
                                 | ThermalDeviceFlagActiveCooling;

    ThermalDeviceInterface.ActiveCooling = SimTcEngageActiveCooling;
    ThermalDeviceInterface.PassiveCooling = SimTcEngagePassiveCooling;

    WDF_QUERY_INTERFACE_CONFIG_INIT(&QueryInterfaceConfig,
                                    (PINTERFACE) &ThermalDeviceInterface,
                                    &GUID_THERMAL_COOLING_INTERFACE,
                                    NULL);

    Status = WdfDeviceAddQueryInterface(DeviceHandle, &QueryInterfaceConfig);
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMTC_ERROR,
                   "WdfDeviceAddQueryInterface() Failed. 0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

    //
    // Finish initializing the device context area.
    //

    DevExt = GetDeviceExtension(DeviceHandle);
    DevExt->ThermalLevel = 100UL;
    DevExt->ActiveCoolingEngaged = FALSE;

DriverDeviceAddEnd:
    DebugExitStatus(Status);
    return Status;
}
Ejemplo n.º 9
0
VOID
VIOSerialPortCreateName(
    IN WDFDEVICE WdfDevice,
    IN PVIOSERIAL_PORT port,
    IN PPORT_BUFFER buf
    )
{
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_WORKITEM_CONFIG   workitemConfig;
    WDFWORKITEM           hWorkItem;
    PRAWPDO_VIOSERIAL_PORT  pdoData = NULL;
    NTSTATUS              status = STATUS_SUCCESS;
    size_t                length;
    PVIRTIO_CONSOLE_CONTROL cpkt;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "--> %s\n", __FUNCTION__);
    cpkt = (PVIRTIO_CONSOLE_CONTROL)((ULONG_PTR)buf->va_buf + buf->offset);
    if (port && !port->NameString.Buffer)
    {
        length = buf->len - buf->offset - sizeof(VIRTIO_CONSOLE_CONTROL);
        port->NameString.Length = (USHORT)( length );
        port->NameString.MaximumLength = port->NameString.Length + 1;
        port->NameString.Buffer = (PCHAR)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 port->NameString.MaximumLength,
                                 VIOSERIAL_DRIVER_MEMORY_TAG
                                 );
        if (port->NameString.Buffer)
        {
           RtlCopyMemory(  port->NameString.Buffer,
                                 (PVOID)((LONG_PTR)buf->va_buf + buf->offset + sizeof(*cpkt)),
                                 length
                                 );
           port->NameString.Buffer[length] = '\0';
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME name_size = %d %s\n", length, port->NameString.Buffer);
        }
        else
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                 "VIRTIO_CONSOLE_PORT_NAME: Unable to alloc string buffer\n"
                                 );
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
        attributes.ParentObject = WdfDevice;
        WDF_WORKITEM_CONFIG_INIT(&workitemConfig, VIOSerialPortSymbolicNameWork);

        status = WdfWorkItemCreate( &workitemConfig,
                                 &attributes,
                                 &hWorkItem);

        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "WdfWorkItemCreate failed with status = 0x%08x\n", status);
           return;
        }

        pdoData = RawPdoSerialPortGetData(hWorkItem);

        pdoData->port = port;

        WdfWorkItemEnqueue(hWorkItem);
    }
    else
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME invalid id = %d\n", cpkt->id);
    }
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__);
}
Ejemplo n.º 10
0
///////////////////////////////////////////////////////////////////////////////
//
//  BasicUsbEvtDeviceAdd
//
//    This routine is called by the framework when a device of
//    the type we support is found in the system.
//
//  INPUTS:
//
//      DriverObject - Our WDFDRIVER object
//
//      DeviceInit   - The device iniitalization structure we'll
//                     be using to create our WDFDEVICE
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS, otherwise an error indicating why the driver could not
//                      load.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL.
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
BasicUsbEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES objAttributes;
    WDFDEVICE device;
    WDF_IO_QUEUE_CONFIG queueConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    PBASICUSB_DEVICE_CONTEXT  devContext;   
    

#if DBG
    DbgPrint("BasicUsbEvtDeviceAdd\n");
#endif
   
    
    //
    // Our "internal" (native) and user-accessible device names
    //
    DECLARE_CONST_UNICODE_STRING(nativeDeviceName, L"\\Device\\BasicUsb");
    DECLARE_CONST_UNICODE_STRING(userDeviceName, L"\\Global??\\BasicUsb");
    
    UNREFERENCED_PARAMETER(Driver);

    //
    // Life is a bit more complicated in this driver...
    //
    // We need an EvtPrepareHardware to configure our device. In addition, we
    // must handle EvtD0Entry and EvtD0Exit in order to manage our continuous
    // reader.
    //
    
    //
    // Prepare for WDFDEVICE creation
    //
    // Initialize standard WDF Object Attributes structure
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes);

    //
    // Specify our device context
    //
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes,
                                        BASICUSB_DEVICE_CONTEXT);

    //
    // We want our device object NAMED, thank you very much
    //
    status = WdfDeviceInitAssignName(DeviceInit, &nativeDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceInitAssignName failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Set our I/O type to DIRECT, meaning that we want to receive
    // MDLs for both read and write requests.
    //
    // While we are not obligated to choose direct, USB drivers
    // typically do so because the USB bus driver needs MDLs to
    // actually perform the transfer. If we select DIRECT I/O, the
    // bus driver can just use the MDL that we're given as opposed
    // to creating his own.
    //
    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
    
    //
    // In this driver we need to be notified of some Pnp/Power
    // events, so initialize a pnp power callbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // USB drivers configure their device within prepare hardware,
    // so register an EvtDevicePrepareHardware callback.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware 
                                     = BasicUsbEvtDevicePrepareHardware;

    //
    // Our driver uses a continuous reader on the interrupt pipe to
    // be notified asynchronously of changes to the OSRFX2's
    // switchpack. We need to start the reader in D0Entry and stop
    // it in D0Exit, so register for EvtDeviceD0Entry and
    // EvtDeviceD0Exit callbacks
    //
    pnpPowerCallbacks.EvtDeviceD0Entry = BasicUsbEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = BasicUsbEvtDeviceD0Exit;  

    //
    // Update the DeviceInit structure to contain the new callbacks.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, 
                                           &pnpPowerCallbacks);

    //
    // We want to send control transfers synchronously from within
    // EvtIoDeviceControl, so we'll apply a PASSIVE_LEVEL constraint
    // to our device
    //
    objAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // Now let's create our device object
    //
    status = WdfDeviceCreate(&DeviceInit,
                            &objAttributes, 
                            &device);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreate failed 0x%0x\n", status);
#endif
        return status;
    }

    //
    // Create a symbolic link for the control object so that usermode can open
    // the device by name.
    //
    status = WdfDeviceCreateSymbolicLink(device, &userDeviceName);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // ALSO create a device interface for the device
    // This allows usage of the lovely SetupApiXxxx functions to locate
    // the device
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                    &GUID_DEVINTERFACE_BASICUSB,
                                    NULL);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfDeviceCreateDeviceInterface failed 0x%0x\n", status);
#endif
        return(status);
    }

    //
    // Configure our queue of incoming requests
    //
    // We only use the default queue, and we set it for parallel processing.
    // We chose this because we may have, say, a bulk read hanging on the bus
    // driver that won't get completed until we send down a bulk write.
    //
    // If we chose a sequential queue we wouldn't be presented the write from
    // the user until the read completed, but the read wouldn't complete
    // until we were presented the write from the user - resulting in an "I/O
    // deadlock".
    //
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
                                           WdfIoQueueDispatchParallel);

    //
    // Declare our I/O Event Processing callbacks
    //
    // We handle, read, write, and device control requests.
    //
    // WDF will automagically handle Create and Close requests for us and will
    // will complete any OTHER request types with STATUS_INVALID_DEVICE_REQUEST.    
    //
    queueConfig.EvtIoRead = BasicUsbEvtRead;
    queueConfig.EvtIoWrite = BasicUsbEvtWrite;
    queueConfig.EvtIoDeviceControl = BasicUsbEvtDeviceControl;

    //
    // Because this is a queue for a real hardware
    // device, indicate that the queue needs to be
    // power managed
    //
    queueConfig.PowerManaged = WdfTrue;

    status = WdfIoQueueCreate(device,
                            &queueConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            NULL); // optional pointer to receive queue handle

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for default queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    devContext = BasicUsbGetContextFromDevice(device);

    WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                             WdfIoQueueDispatchManual);

    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &devContext->SwitchPackStateChangeQueue);

    if (!NT_SUCCESS(status)) {
#if DBG
        DbgPrint("WdfIoQueueCreate for manual queue failed 0x%0x\n", status);
#endif
        return(status);
    }

    return(STATUS_SUCCESS);
}
Ejemplo n.º 11
0
NTSTATUS
PepScheduleWorker (
    _In_ PPEP_WORK_CONTEXT WorkContext
    )

/*++

Routine Description:

    This function schedules a worker thread to process pending work requests.

Arguments:

    WorkContext - Supplies the context of the work.

Return Value:

    NTSTATUS.

--*/

{

    WDF_OBJECT_ATTRIBUTES Attributes;
    NTSTATUS Status;
    BOOLEAN Synchronous;
    WDFWORKITEM WorkItem;
    WDF_WORKITEM_CONFIG WorkItemConfiguration;

    WorkItem = NULL;
    Synchronous = FALSE;

    //
    // Create a workitem to process events.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&Attributes,
                                           PEP_WORK_ITEM_CONTEXT);

    Attributes.ParentObject = PepGlobalWdfDevice;

    //
    // Initialize the handler routine and create a new workitem.
    //

    WDF_WORKITEM_CONFIG_INIT(&WorkItemConfiguration, PepWorkerWrapper);

    //
    // Disable automatic serialization by the framework for the worker thread.
    // The parent device object is being serialized at device level (i.e.,
    // WdfSynchronizationScopeDevice), and the framework requires it to be
    // passive level (i.e., WdfExecutionLevelPassive) if automatic
    // synchronization is desired.
    //

    WorkItemConfiguration.AutomaticSerialization = FALSE;

    //
    // Create the work item and queue it. If the workitem cannot be created
    // for some reason, just call the worker routine synchronously.
    //

    Status = WdfWorkItemCreate(&WorkItemConfiguration,
                               &Attributes,
                               &WorkItem);

    if (!NT_SUCCESS(Status)) {
        Synchronous = TRUE;
        TraceEvents(INFO,
                    DBG_PEP,
                    "%s: Failed to allocate work item to process pending"
                    "work! Status = %!STATUS!. Will synchronously process.\n",
                    __FUNCTION__,
                    Status);
    }

    //
    // If the operation is to be performed synchronously, then directly
    // invoke the worker routine. Otherwise, queue a workitem to run the
    // worker routine.
    //

    if (Synchronous != FALSE) {
        PepProcessPendingWorkRequests();

    } else {
        TraceEvents(INFO,
                    DBG_PEP,
                    "%s: Work request scheduled to run asynchronously. "
                    "Device=%p, WorkType=%d, NotificationId=%d.\n",
                    __FUNCTION__,
                    (PVOID)WorkContext->PepInternalDevice,
                    (ULONG)WorkContext->WorkType,
                    (ULONG)WorkContext->NotificationId);

        WdfWorkItemEnqueue(WorkItem);
    }

    return STATUS_SUCCESS;
}
Ejemplo n.º 12
0
static NTSTATUS UsbChief_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
{
	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_OBJECT_ATTRIBUTES fileObjectAttributes, requestAttributes, fdoAttributes;
	WDF_FILEOBJECT_CONFIG fileConfig;
	NTSTATUS Status;
	WDFDEVICE device;
	WDF_IO_QUEUE_CONFIG ioQueueConfig;
	WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
	WDFQUEUE queue;
	UNICODE_STRING linkname;

	UNREFERENCED_PARAMETER(Driver);
	PAGED_CODE();

	UsbChief_DbgPrint(DEBUG_CONFIG, ("ExtDeviceAdd\n"));

	/* Init PnP */
	WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
	pnpPowerCallbacks.EvtDevicePrepareHardware = UsbChief_EvtDevicePrepareHardware;
	WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	/* Request Attributes */
	WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT);
	WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes);

	/* Fileobject init */

	WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, UsbChief_EvtDeviceFileCreate,
			WDF_NO_EVENT_CALLBACK,
			WDF_NO_EVENT_CALLBACK);

	WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT);
	WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes);

	WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT);

	Status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreate: %08x\n", Status));
		return Status;
	}

	RtlInitUnicodeString(&linkname, L"\\DosDevices\\ChiefUSB");
	Status = WdfDeviceCreateSymbolicLink(device, &linkname);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreateSymbolicLink: %08x\n", Status));
		goto out;
	}

	WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
	pnpCaps.SurpriseRemovalOK = WdfTrue;
	WdfDeviceSetPnpCapabilities(device, &pnpCaps);

	/* Register I/O callbacks */
	WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel);
	ioQueueConfig.EvtIoRead = UsbChief_EvtIoRead;
	ioQueueConfig.EvtIoWrite = UsbChief_EvtIoWrite;
	ioQueueConfig.EvtIoDeviceControl = UsbChief_EvtIoDeviceControl;
	ioQueueConfig.EvtIoStop = UsbChief_EvtIoStop;
	ioQueueConfig.EvtIoResume = UsbChief_EvtIoResume;

	Status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);

	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfIoQueueCreate: %08x\n", Status));
		goto out;
	}

	Status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_USBCHIEF_USB, NULL);
	if (!NT_SUCCESS(Status)) {
		UsbChief_DbgPrint(0, ("WdfDeviceCreateDeviceInterface: %08x\n", Status));
		goto out;
	}
	UsbChief_DbgPrint(3, ("EvtDriverDeviceAdd successful\n"));
	return STATUS_SUCCESS;
out:
	return Status;
}
Ejemplo n.º 13
0
/**
 * @brief Allocate a workitem from or for our collection of workitems.
 * Must be called with the device lock held.
 * 
 * @param[in] Device handle to the WDFDEVICE created by FdoEvtDeviceAdd.
 * @param[in] callback only optional if this is add device doing an allocation!
 * @param[in] Param0 arbitrary context data
 * @param[in] Param1 arbitrary context data
 * @param[in] Param2 arbitrary context data
 * @param[in] Param3 arbitrary context data
 * 
 * @returns a WDFWORKITEM handle or NULL on failure.
 * 
 */
WDFWORKITEM
NewWorkItem(
    IN PUSB_FDO_CONTEXT fdoContext,
    IN PFN_WDF_WORKITEM  callback, 
    IN ULONG_PTR Param0,
    IN ULONG_PTR Param1,
    IN ULONG_PTR Param2,
    IN ULONG_PTR Param3)
{
    //
    // First try to get a workitem from our collection of them.
    //    
    WDFWORKITEM  WorkItem = (WDFWORKITEM) WdfCollectionGetFirstItem(fdoContext->FreeWorkItems);
    if (WorkItem == NULL)
    {
        //
        // ok - allocate a new one.
        //
        TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DEVICE,
            __FUNCTION__": Device %p FreeWorkItems is empty, init count %d\n",
            fdoContext->WdfDevice,
            INIT_WORK_ITEM_COUNT);

        NTSTATUS  status = STATUS_SUCCESS;
        WDF_OBJECT_ATTRIBUTES  attributes;
        WDF_WORKITEM_CONFIG  workitemConfig;

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(
            &attributes,
            USB_FDO_WORK_ITEM_CONTEXT);

        attributes.ParentObject = fdoContext->WdfDevice;

        WDF_WORKITEM_CONFIG_INIT(
            &workitemConfig,
            EvtFdoDeviceGenericWorkItem);

        status = WdfWorkItemCreate(
            &workitemConfig,
            &attributes,
            &WorkItem);

        if (!NT_SUCCESS(status)) 
        {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
                __FUNCTION__": WdfWorkItemCreate error %x\n",
                status);
            return NULL;
        }
    }
    else
    {
        // note that WdfCollectionGetFirstItem doesn't remove it from the collection.
        WdfCollectionRemove(fdoContext->FreeWorkItems, WorkItem);
    }
    if (WorkItem)
    {
        // initialize it.
        PUSB_FDO_WORK_ITEM_CONTEXT  context = WorkItemGetContext(WorkItem);
        context->FdoContext = fdoContext;
        context->CallBack = callback;
        context->Params[0] = Param0;
        context->Params[1] = Param1;
        context->Params[2] = Param2;
        context->Params[3] = Param3;
    }
    return WorkItem;
}
NTSTATUS
NfcCxEvtDeviceInitConfig(
    _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals,
    _In_ PWDFDEVICE_INIT DeviceInit,
    _In_ PNFC_CX_CLIENT_CONFIG Config
    )
/*++
Routine Description:

    NfcCxEvtDeviceInitConfig is called by the client driver from within
    its AddDevice callback to finish initializing the device before creation.

Arguments:

    NfcCxGlobals - Pointer to the Class extension globals
    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
    Config - Pointer to a client provided structure with their configuration.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                          status = STATUS_SUCCESS; 
    WDFCX_FILEOBJECT_CONFIG           fileConfig;
    WDF_OBJECT_ATTRIBUTES             fileObjectAttributes;
    PWDFCXDEVICE_INIT                 exDeviceInit;
    PNFCCX_CLIENT_GLOBALS             nfcCxClientGlobal;

    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    if (!VerifyPrivateGlobals(NfcCxGlobals)) {
        TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer");
        status = STATUS_INVALID_PARAMETER;
        goto Done;
    }

    if (NULL == Config ||
        sizeof(NFC_CX_CLIENT_CONFIG) != Config->Size ||
        NULL == Config->EvtNfcCxWriteNciPacket) {
        TRACE_LINE(LEVEL_ERROR, "Invalid Client Driver Configuration");
        status = STATUS_INVALID_PARAMETER;
        goto Done;
    }

    if (NFC_CX_DEVICE_MODE_NCI != Config->DeviceMode &&
        NFC_CX_DEVICE_MODE_DTA != Config->DeviceMode &&
        NFC_CX_DEVICE_MODE_RAW != Config->DeviceMode) {
        TRACE_LINE(LEVEL_ERROR, "Invalid Client Driver Device Mode %d", Config->DeviceMode);
        status = STATUS_INVALID_PARAMETER;
        goto Done;
    }

    nfcCxClientGlobal = GetPrivateGlobals(NfcCxGlobals);

    //
    // The CX is the power policy owner of this stack.
    //
    WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, TRUE);

    //
    // Allocate the CX DeviceInit
    //
    exDeviceInit = WdfCxDeviceInitAllocate(DeviceInit);
    if (NULL == exDeviceInit) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TRACE_LINE(LEVEL_ERROR,
            "Failed WdfCxDeviceInitAllocate, status=%!STATUS!", status);
        goto Done;
    }

    //
    // Enable SelfIoTarget
    //
    WdfDeviceInitAllowSelfIoTarget(DeviceInit);

    //
    // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
    // per handle (fileobject) context.
    //
    WDFCX_FILEOBJECT_CONFIG_INIT(
                            &fileConfig,
                            NfcCxEvtDeviceFileCreate,
                            NfcCxEvtFileClose,
                            WDF_NO_EVENT_CALLBACK // not interested in Cleanup
                            );

    WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);
    fileObjectAttributes.SynchronizationScope = WdfSynchronizationScopeNone;

    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes,
                                            NFCCX_FILE_CONTEXT);

    WdfCxDeviceInitSetFileObjectConfig(exDeviceInit,
                                       &fileConfig,
                                       &fileObjectAttributes);

    TRACE_LINE(LEVEL_INFO, "DriverFlags=0x%x PowerIdleType=%d PowerIdleTimeout=%d",
                            Config->DriverFlags, Config->PowerIdleType, Config->PowerIdleTimeout);

    TraceLoggingWrite(g_hNfcCxProvider,
        "NfcCxClientConfig",
        TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY),
        TraceLoggingHexInt32(Config->DriverFlags, "DriverFlags"),
        TraceLoggingValue((INT32)(Config->PowerIdleType), "PowerIdleType"),
        TraceLoggingValue(Config->PowerIdleTimeout, "PowerIdleTimeout"));

    //
    // Save the client driver configs
    //
    RtlCopyMemory(&nfcCxClientGlobal->Config, Config, Config->Size);

Done:
    
    TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status);
    TRACE_LOG_NTSTATUS_ON_FAILURE(status);
    
    return status;
}
Ejemplo n.º 15
0
NTSTATUS
SimSensorDriverDeviceAdd (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )

/*++

Routine Description:

    EvtDriverDeviceAdd is called by the framework in response to AddDevice call
    from the PnP manager. A WDF device object is created and initialized to
    represent a new instance of the battery device.

Arguments:

    Driver - Supplies a handle to the WDF Driver object.

    DeviceInit - Supplies a pointer to a framework-allocated WDFDEVICE_INIT
        structure.

Return Value:

    NTSTATUS

--*/

{

    WDF_OBJECT_ATTRIBUTES DeviceAttributes;
    WDFDEVICE DeviceHandle;
    PFDO_DATA DevExt;
    BOOLEAN LockHeld;
    WDF_IO_QUEUE_CONFIG PendingRequestQueueConfig;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
    WDFQUEUE Queue;
    WDF_IO_QUEUE_CONFIG QueueConfig;
    NTSTATUS Status;
    WDF_OBJECT_ATTRIBUTES WorkitemAttributes;
    WDF_WORKITEM_CONFIG WorkitemConfig;

    UNREFERENCED_PARAMETER(Driver);

    DebugEnter();
    PAGED_CODE();

    LockHeld = FALSE;

    //
    // Initialize attributes and a context area for the device object.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&DeviceAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, FDO_DATA);

    //
    // Initailize power callbacks
    //

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
    PnpPowerCallbacks.EvtDeviceD0Entry = SimSensorDeviceD0Entry;
    PnpPowerCallbacks.EvtDeviceD0Exit = SimSensorDeviceD0Exit;
    PnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend =
        SimSensorSelfManagedIoSuspend;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpPowerCallbacks);

    //
    // Create a framework device object.  This call will in turn create
    // a WDM device object, attach to the lower stack, and set the
    // appropriate flags and attributes.
    //

    Status = WdfDeviceCreate(&DeviceInit, &DeviceAttributes, &DeviceHandle);
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                   "WdfDeviceCreate() Failed. 0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

    DevExt = GetDeviceExtension(DeviceHandle);

    //
    // Configure a default queue for IO requests. This queue processes requests
    // to read the sensor state.
    //

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig,
                                           WdfIoQueueDispatchParallel);

    QueueConfig.EvtIoDeviceControl = SimSensorIoDeviceControl;

    //
    // The system uses IoInternalDeviceControl requests to communicate with the
    // ACPI driver on the device stack. For proper operation of thermal zones,
    // these requests must be forwarded unless the driver knows how to handle
    // them.
    //

    QueueConfig.EvtIoInternalDeviceControl = SimSensorIoInternalDeviceControl;
    Status = WdfIoQueueCreate(DeviceHandle,
                              &QueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &Queue);

    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                   "WdfIoQueueCreate() (Default) Failed.  0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

    //
    // Configure a manual dispatch queue for pending requests. This queue
    // stores requests to read the sensor state which can't be retired
    // immediately.
    //

    WDF_IO_QUEUE_CONFIG_INIT(&PendingRequestQueueConfig,
                             WdfIoQueueDispatchManual);


    Status = WdfIoQueueCreate(DeviceHandle,
                              &PendingRequestQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &DevExt->PendingRequestQueue);

    PendingRequestQueueConfig.EvtIoStop = SimSensorQueueIoStop;
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                "WdfIoQueueCreate() (Pending) Failed. 0x%x\n",
                Status);

        goto DriverDeviceAddEnd;
    }


    //
    // Configure a workitem to process the simulated interrupt.
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&WorkitemAttributes);
    WorkitemAttributes.ParentObject = DeviceHandle;
    WDF_WORKITEM_CONFIG_INIT(&WorkitemConfig,
                             SimSensorTemperatureInterruptWorker);

    Status = WdfWorkItemCreate(&WorkitemConfig,
                               &WorkitemAttributes,
                               &DevExt->InterruptWorker);

    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                   "WdfWorkItemCreate() Failed. 0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

    //
    // Create the request queue waitlock.
    //

    Status = WdfWaitLockCreate(NULL, &DevExt->QueueLock);
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                   "WdfWaitLockCreate() Failed. Status 0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

    //
    // Initilize the simulated sensor hardware.
    //

    DevExt->Sensor.LowerBound = 0;
    DevExt->Sensor.UpperBound = (ULONG)-1;
    DevExt->Sensor.Temperature = VIRTUAL_SENSOR_RESET_TEMPERATURE;
    Status = WdfWaitLockCreate(NULL, &DevExt->Sensor.Lock);
    if (!NT_SUCCESS(Status)) {
        DebugPrint(SIMSENSOR_ERROR,
                   "WdfWaitLockCreate() Failed. 0x%x\n",
                   Status);

        goto DriverDeviceAddEnd;
    }

DriverDeviceAddEnd:

    DebugExitStatus(Status);
    return Status;
}
NTSTATUS AndroidUsbDeviceObject::CreateFDODevice(PWDFDEVICE_INIT device_init) {
  ASSERT_IRQL_PASSIVE();

  ASSERT(!IsTaretDeviceCreated());
  if (IsTaretDeviceCreated())
    return STATUS_INTERNAL_ERROR;

  // Initialize our object attributes first
  WDF_OBJECT_ATTRIBUTES device_attr;
  NTSTATUS status = InitObjectAttributes(&device_attr, NULL);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Initialize the pnp_power_callbacks structure.  Callback events for PnP
  // and Power are specified here. If we don't supply any callbacks, the
  // KMDF will take appropriate default actions for an FDO device object.
  // EvtDevicePrepareHardware and EvtDeviceReleaseHardware are major entry
  // points for initializing / cleaning up our device. Probably, we can leave
  // the rest to the framework.
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDevicePrepareHardware =
    EvtDevicePrepareHardwareEntry;
  pnp_power_callbacks.EvtDeviceReleaseHardware =
    EvtDeviceReleaseHardwareEntry;
  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  // Initialize the request attributes to specify the context size and type
  // for every request created by framework for this device.
  WDF_OBJECT_ATTRIBUTES request_attr;
  WDF_OBJECT_ATTRIBUTES_INIT(&request_attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&request_attr, AndroidUsbWdfRequestContext);
  WdfDeviceInitSetRequestAttributes(device_init, &request_attr);

  // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the KMDF that we are
  // interested in handling Create requests that get genereated when an
  // application or another kernel component opens a handle through the device.
  // We are not interested in receiving cleanup / close IRPs at this point.
  WDF_FILEOBJECT_CONFIG file_config;
  WDF_OBJECT_ATTRIBUTES file_attr;
  WDF_FILEOBJECT_CONFIG_INIT(&file_config,
                             EvtDeviceFileCreateEntry,
                             WDF_NO_EVENT_CALLBACK,
                             WDF_NO_EVENT_CALLBACK);
  WDF_OBJECT_ATTRIBUTES_INIT(&file_attr);
  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&file_attr,
                                         AndroidUsbWdfObjectContext);
  file_attr.EvtCleanupCallback = AndroidUsbWdfObject::EvtCleanupCallbackEntry;
  file_attr.EvtDestroyCallback = AndroidUsbWdfObject::EvtDestroyCallbackEntry;
  // We will provide our own synchronization for file access
  file_attr.SynchronizationScope = WdfSynchronizationScopeNone;
  WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attr);

  // I/O type is buffered by default. It could be very inefficient if we have
  // large reads / writes through our device.
  WdfDeviceInitSetIoType(device_init, WdfDeviceIoDirect);

  // DeviceInit is completely initialized. So call the framework
  // to create the device and attach it to the lower stack.
  WDFDEVICE wdf_dev = NULL;
  status = WdfDeviceCreate(&device_init, &device_attr, &wdf_dev);
  ASSERT(NT_SUCCESS(status) && (NULL != wdf_dev));
  if (!NT_SUCCESS(status))
    return status;

  // Save handle to the created device
  set_wdf_object(wdf_dev);

  // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
  // that we don't get the popup in usermode (on Win2K) when we surprise
  // remove the device.
  WDF_DEVICE_PNP_CAPABILITIES pnp_caps;
  WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnp_caps);
  pnp_caps.SurpriseRemovalOK = WdfTrue;
  WdfDeviceSetPnpCapabilities(wdf_device(), &pnp_caps);

  // Create our default queue object for this device to start receiving I/O
  status = CreateDefaultQueue();
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Register a device interface so that app can find our device and talk to it.
  status = WdfDeviceCreateDeviceInterface(wdf_device(), &android_guid, NULL);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  // Initialize our extension to that device. We will do this at the very end
  // so we know that we successfully passed entire device create chain when
  // we are called with other callbacks to that device.
  status = InitializeContext();
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status))
    return status;

  return STATUS_SUCCESS;
}
Ejemplo n.º 17
0
NTSTATUS
MarsEvtDeviceAdd(
                IN WDFDRIVER Driver,
                IN PWDFDEVICE_INIT DeviceInit
                )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PFDO_DATA                fdoData;
    WDF_IO_QUEUE_CONFIG        queueConfig;
    WDF_OBJECT_ATTRIBUTES    fdoAttributes;
    WDFDEVICE                device;
    WDF_PNPPOWER_EVENT_CALLBACKS          pnpPowerCallbacks;
    SDBUS_INTERFACE_PARAMETERS interfaceParameters = {0};

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    WdfDeviceInitSetPowerPageable(DeviceInit);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Register PNP callbacks.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = MarsEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = MarsEvtDeviceReleaseHardware;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes);
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, FDO_DATA);

    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    fdoData = MarsFdoGetData(device); //Gets device context

    //
    // Open an interface to the SD bus driver
    //
    status = SdBusOpenInterface(WdfDeviceWdmGetPhysicalDevice (device),
                                &fdoData->BusInterface,
                                sizeof(SDBUS_INTERFACE_STANDARD),
                                SDBUS_INTERFACE_VERSION);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    interfaceParameters.Size                        = sizeof(SDBUS_INTERFACE_PARAMETERS);
    interfaceParameters.TargetObject                = WdfDeviceWdmGetAttachedDevice(device);
    interfaceParameters.DeviceGeneratesInterrupts   = TRUE;    //change to true eventually
    interfaceParameters.CallbackRoutine             = MarsEventCallback;
    interfaceParameters.CallbackRoutineContext      = fdoData;

    status = STATUS_UNSUCCESSFUL;
    if (fdoData->BusInterface.InitializeInterface) {
        status = (fdoData->BusInterface.InitializeInterface)(fdoData->BusInterface.Context,
                                                             &interfaceParameters);
    }

    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    //    Register New device
    //

    status = WdfDeviceCreateDeviceInterface(device,
                                            (LPGUID) &GUID_DEVINTERFACE_MARS,
                                            NULL
                                           );
    if (!NT_SUCCESS(status)) {
        return status;
    }

    fdoData->WdfDevice = device;

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,  WdfIoQueueDispatchSequential);

    queueConfig.EvtIoRead = MarsEvtIoRead;
    queueConfig.EvtIoWrite = MarsEvtIoWrite;
    queueConfig.EvtIoDeviceControl = MarsEvtIoDeviceControl;

    status = WdfIoQueueCreate(device,
                              &queueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &fdoData->IoctlQueue
                             );

    return status;
}
Ejemplo n.º 18
0
NTSTATUS
TpmEvtDeviceAdd(
				IN WDFDRIVER        Driver,
				IN PWDFDEVICE_INIT  DeviceInit
    )
{
    NTSTATUS                    status = STATUS_SUCCESS;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks;
    WDF_OBJECT_ATTRIBUTES       DeviceAttributes;
    WDFDEVICE                   device;
    PTPM_CONTEXT                TpmContext;
    WDF_IO_QUEUE_CONFIG         IoQueueConfig;
    WDFQUEUE                    hQueue;
    WDF_QUERY_INTERFACE_CONFIG  InterfaceConfig;
    TPM_INTERFACE_STANDARD      TpmInterface;
    WDF_DEVICE_POWER_CAPABILITIES   PowerCaps;

	PAGED_CODE();

    UNREFERENCED_PARAMETER( Driver );

    
    RtlZeroMemory(&PnpPowerEventCallbacks,sizeof(PnpPowerEventCallbacks));
    RtlZeroMemory(&PowerCaps,sizeof(PowerCaps));

    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
		"TpmEvtDeviceAdd routine PDO: %p (%p)\n",
				WdfDriverWdmGetDriverObject(Driver)));
    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks);

    //
    // These two callbacks set up and tear down hardware state that must be
    // done every time the device moves in and out of the D0-working state.
    //
    PnpPowerEventCallbacks.EvtDeviceD0Entry         = TpmEvtDeviceD0Entry;

    PnpPowerEventCallbacks.EvtDeviceD0Exit          = TpmEvtDeviceD0Exit;
    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.
    //
    PnpPowerEventCallbacks.EvtDevicePrepareHardware = TpmEvtDevicePrepareHardware;
    PnpPowerEventCallbacks.EvtDeviceReleaseHardware = TpmEvtDeviceReleaseHardware;


    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,&PnpPowerEventCallbacks);

    //
    // Specify the context type and size for the device we are about to create.
    //
	RtlZeroMemory(&DeviceAttributes,sizeof(DeviceAttributes));
    WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, TPM_CONTEXT);
	DeviceAttributes.Size = sizeof(WDF_OBJECT_ATTRIBUTES);
	DeviceAttributes.SynchronizationScope	= WdfSynchronizationScopeInheritFromParent;
	DeviceAttributes.ExecutionLevel			= WdfExecutionLevelPassive;

    status = WdfDeviceCreate(&DeviceInit,&DeviceAttributes,&device);

    if(NT_SUCCESS(status))
    {
        TpmContext = GetTpmContext(device);
        RtlZeroMemory(TpmContext,sizeof(TPM_CONTEXT));
        TpmContext->Device = device;
        TpmContext->AccessRegister = FALSE;
        KeInitializeSpinLock(&TpmContext->SpinLock);
        TpmContext->TpmState = StSuspend;
        TpmInitStateTable();
        KeInitializeEvent(&TpmContext->Event,NotificationEvent,TRUE);

        status = WdfDeviceCreateDeviceInterface(device,&GUID_DEVINTERFACE_TPM,NULL);

        if(NT_SUCCESS(status))
        {
            WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
                                           &IoQueueConfig,
                                           WdfIoQueueDispatchParallel
                                           );
            IoQueueConfig.EvtIoDeviceControl = TpmEvtIoDeviceControl;

            status = WdfIoQueueCreate(
                              device,
                              &IoQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &hQueue
                              );

            if(NT_SUCCESS(status))
            {

                WDF_DEVICE_POWER_CAPABILITIES_INIT(&PowerCaps);

                WdfDeviceSetPowerCapabilities(device,&PowerCaps);

                //
                TpmGetRegistryFlags(device,TpmContext);

                //
                RtlZeroMemory(&TpmInterface,sizeof(TpmInterface));
                TpmInterface.InterfaceHeader.Size = sizeof(TpmInterface);
                TpmInterface.InterfaceHeader.Version = 1;
                TpmInterface.InterfaceHeader.Context = (PVOID)TpmContext;

                TpmInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
                TpmInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
                TpmInterface.pfn_TpmSetMorBitState = TpmSetMorBitState;

                //
                // Initialize the InterfaceConfig structure.
                //
                WDF_QUERY_INTERFACE_CONFIG_INIT(
                                &InterfaceConfig,
                                (PINTERFACE)&TpmInterface,
                                &GUID_TPM_INTERFACE_STANDARD,
                                NULL
                                );

                //
                // Create the interface.
                //
                status = WdfDeviceAddQueryInterface(
                                                    device,
                                                    &InterfaceConfig
                                                    );
                if(!NT_SUCCESS(status))
                {
                    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                        "WdfDeviceAddQueryInterface failed with NTSTATUS 0x%x\n",status));
                }
            }
            else
            {
                KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                    "WdfIoQueueCreate failed with Status code 0x%x\n",status));
            }
        }
        else
        {
            KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                "WdfDeviceCreateDeviceInterface failed with Status code 0x%x\n",status));
        }
    }
    else
    {
        KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                "WdfDeviceCreate failed with Status code 0x%x\n",status));
    }

    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
            "TpmEvtDeviceAdd exited with Status code 0x%x\n",status));

    return status;
}
Ejemplo n.º 19
0
NTSTATUS
InterruptCreate (
    _In_ WDFDEVICE Device,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceRaw,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceTranslated
    )
/*++

Routine Description:

    Helper function to create device's WDFINTERRUPT object and any other 
    needed WDF resources that the interrupt needs for proper functioning.

    It assumes the first interrupt resource with which this is invoked is 
    the device interrupt, and the second is the attach/detach interrupt.

Arguments:

    Device - Wdf device object corresponding to the FDO

    InterruptResourceRaw -  Raw resource for the interrupt

    InterruptResourceTranslated - Translated resource for the interrupt

Return Value:

    Appropriate NTSTATUS value

--*/
{
    NTSTATUS Status;
    WDF_INTERRUPT_CONFIG InterruptConfig;
    PCONTROLLER_CONTEXT ControllerContext;
    WDF_OBJECT_ATTRIBUTES Attributes;
    WDFINTERRUPT* InterruptToCreate;

    TraceEntry();

    PAGED_CODE();

    ControllerContext = DeviceGetControllerContext(Device);

    WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);

    if (ControllerContext->DeviceInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig, 
            DeviceInterrupt_EvtInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);

        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(
            &Attributes, 
            DEVICE_INTERRUPT_CONTEXT);

        InterruptToCreate = &ControllerContext->DeviceInterrupt;

    } else if (ControllerContext->AttachDetachInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig,
            DeviceInterrupt_EvtAttachDetachInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);
        InterruptConfig.CanWakeDevice = TRUE;
        InterruptConfig.PassiveHandling = TRUE;
        InterruptToCreate = &ControllerContext->AttachDetachInterrupt;

    } else {
        TraceWarning("Other interrupt resource [0X%X] is detected and is being"
                        " ignored", InterruptResourceRaw->u.Interrupt.Vector);
        Status = STATUS_SUCCESS;
        goto End;
    }
    
    InterruptConfig.InterruptRaw = InterruptResourceRaw;
    InterruptConfig.InterruptTranslated = InterruptResourceTranslated;

    Status = WdfInterruptCreate(
                 Device,
                 &InterruptConfig,
                 &Attributes,
                 InterruptToCreate);
    CHK_NT_MSG(Status, "Failed to create Device interrupt");

End:
    TraceExit();
    return Status;
}
Ejemplo n.º 20
0
NTSTATUS Pipe_InitQueue(
    __in PDEVICE_CONTEXT deviceContext,
    __in PPIPE_CONTEXT pipeContext,
    __out WDFQUEUE* queueRef)
{
	WDF_IO_QUEUE_CONFIG queueConfig;
	WDF_OBJECT_ATTRIBUTES objectAttributes;
	NTSTATUS status = STATUS_INVALID_HANDLE;
	WDFQUEUE queue = NULL;
	PQUEUE_CONTEXT queueContext;
	WDF_OBJECT_ATTRIBUTES memAttributes;

	WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes);
	objectAttributes.SynchronizationScope = WdfSynchronizationScopeQueue;

	*queueRef = NULL;

	// All queues get a context. At the very least, they will use a local copy of policy and pipe information
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objectAttributes, QUEUE_CONTEXT);

	queueConfig.DispatchType = WdfIoQueueDispatchInvalid;
	Pipe_InitQueueConfig(pipeContext, &queueConfig);

	if (queueConfig.DispatchType != WdfIoQueueDispatchInvalid)
	{
		status = WdfIoQueueCreate(deviceContext->WdfDevice,
		                          &queueConfig,
		                          &objectAttributes,
		                          &queue);
		if (!NT_SUCCESS(status))
		{
			USBERR("WdfIoQueueCreate failed. pipeID=%02Xh status=%Xh\n", pipeContext->PipeInformation.EndpointAddress, status);
			goto Exit;
		}

		// Create the memory for partial read storage
		queueContext = GetQueueContext(queue);

		queueContext->IsFreshPipeReset = TRUE;

		// SET queueContext->OverOfs
		RtlZeroMemory(&queueContext->OverOfs, sizeof(queueContext->OverOfs));

		// SET queueContext->PipeHandle
		queueContext->PipeHandle = pipeContext->Pipe;

		// SET queueContext->Info
		RtlCopyMemory(&queueContext->Info, &pipeContext->PipeInformation, sizeof(queueContext->Info));

		WDF_OBJECT_ATTRIBUTES_INIT(&memAttributes);
		memAttributes.ParentObject = queue;

		// Only bulk and interrupt pipes have an OverMem buffer and it is only used
		// when the queue type is sequential. (RAW_IO=FALSE)
		if ((queueContext->Info.MaximumPacketSize) &&
		        (queueContext->Info.PipeType == WdfUsbPipeTypeBulk || queueContext->Info.PipeType == WdfUsbPipeTypeInterrupt))
		{
			// SET queueContext->OverMem
			// SET queueContext->OverBuf
			status = WdfMemoryCreate(&memAttributes, NonPagedPool, POOL_TAG, queueContext->Info.MaximumPacketSize, &queueContext->OverMem, &queueContext->OverBuf);
			if (!NT_SUCCESS(status))
			{
				USBERRN("WdfMemoryCreate failed. status=%08Xh", status);
				WdfObjectDelete(queue);
				goto Exit;
			}
		}
	}

	*queueRef = queue;

Exit:
	return status;
}
Ejemplo n.º 21
0
NTSTATUS
vJoy_CreateRawPdo(
    WDFDEVICE       Device,
    ULONG           InstanceNo
    )
/*++

Routine Description:

    This routine creates and initialize a PDO.

Arguments:

Return Value:

    NT Status code.

--*/
{   
    NTSTATUS                    status;
    PWDFDEVICE_INIT             pDeviceInit = NULL;
    PRPDO_DEVICE_DATA           pdoData = NULL;
    WDFDEVICE                   hChild = NULL;
    WDF_OBJECT_ATTRIBUTES       pdoAttributes;
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_IO_QUEUE_CONFIG         ioQueueConfig;
    WDFQUEUE                    queue;
    WDF_DEVICE_STATE            deviceState;
    PDEVICE_EXTENSION			devExt;
    DECLARE_CONST_UNICODE_STRING(deviceId,VJOY_RAW_DEVICE_ID );
    //DECLARE_CONST_UNICODE_STRING(hardwareId,VJOY_HARDWARE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation,L"vJoy Raw Device\0" );
    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);
	PDEVICE_OBJECT				ChildDeviceObject;
	PDEVICE_OBJECT				ParentDeviceObject;
	DECLARE_CONST_UNICODE_STRING(
		SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R,
		L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GR;;;WD)(A;;GR;;;RC)"
		);
	DECLARE_CONST_UNICODE_STRING(
		SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R,
		L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GR;;;RC)"
		);

	int iInterface;
	WCHAR RefStr[20];
	UNICODE_STRING RefStr2;
	WDF_FILEOBJECT_CONFIG FileObjInit;
	WDF_OBJECT_ATTRIBUTES       FileObjAttributes;

	WDF_OBJECT_ATTRIBUTES		LockAttributes;


	TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_CreateRawPdo\n");


    //
    // Allocate a WDFDEVICE_INIT structure and set the properties
    // so that we can create a device object for the child.
    //
    pDeviceInit = WdfPdoInitAllocate(Device);

    if (pDeviceInit == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAllocate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // Mark the device RAW so that the child device can be started
    // and accessed without requiring a function driver. Since we are
    // creating a RAW PDO, we must provide a class guid.
    //
    status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVINTERFACE_VJOY);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignRawDevice", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

	// TODO: Assign correct SDDL
    ////
    status = WdfDeviceInitAssignSDDLString(pDeviceInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceInitAssignSDDLString", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID
    //
    status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId);
    if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignDeviceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }


    //
    // We could be enumerating more than one children if the filter attaches
    // to multiple instances of keyboard, so we must provide a
    // BusQueryInstanceID. If we don't, system will throw CA bugcheck.
    //
    status =  RtlUnicodeStringPrintf(&buffer, VJOY_DEVICE_INSTANCE, InstanceNo);
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
       goto Cleanup;
    }

    status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignInstanceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. This text is displayed momentarily by the PnP manager while
    // it's looking for a matching INF. If it finds one, it uses the Device
    // Description from the INF file to display in the device manager.
    // Since our device is raw device and we don't provide any hardware ID
    // to match with an INF, this text will be displayed in the device manager.
    //
    status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_409 ); // English - United States
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // You can call WdfPdoInitAddDeviceText multiple times, adding device
    // text for multiple locales. When the system displays the text, it
    // chooses the text that matches the current locale, if available.
    // Otherwise it will use the string for the default locale.
    // The driver can specify the driver's default locale by calling
    // WdfPdoInitSetDefaultLocale.
    //
    status = WdfPdoInitAddDeviceText(pDeviceInit,
                                        &buffer,
                                        &deviceLocation,
                                        0x409 // English - United States
                                        );
    if (!NT_SUCCESS(status)) {
 		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

#if 0
	// Hebrew (No real ned - just for fun)
	status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_40D, InstanceNo ); // Hebrew
	if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (3)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
		goto Cleanup;
	}

	status = WdfPdoInitAddDeviceText(pDeviceInit,
		&buffer,
		&deviceLocation,
		0x40D // Hebrew
		);
	if (!NT_SUCCESS(status)) {
		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
		goto Cleanup;
	}

#endif // 0


    WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // English - United States

	WdfDeviceInitSetExclusive(pDeviceInit, FALSE);
	
	// Create a WDFFILEOBJECT
	WDF_OBJECT_ATTRIBUTES_INIT(&FileObjAttributes);
	WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&FileObjAttributes, FILEOBJECT_EXTENSION);
	WDF_FILEOBJECT_CONFIG_INIT(&FileObjInit,  vJoy_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, vJoy_EvtFileCleanup);
	WdfDeviceInitSetFileObjectConfig(pDeviceInit, &FileObjInit, &FileObjAttributes);

    
    //
    // Initialize the attributes to specify the size of PDO device extension.
    // All the state information private to the PDO will be tracked here.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA);
	pdoAttributes.EvtCleanupCallback = rawEvtCleanupCallback;

    //
    // Set up our queue to allow forwarding of requests to the parent
    // This is done so that the cached data can be retrieved
    //
    //WdfPdoInitAllowForwardingRequestToParent(pDeviceInit);
	// TODO: Replace the above because it is needed for WdfRequestForwardToParentDeviceIoQueue()

    status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
    if (!NT_SUCCESS(status)) {
  		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Get the device context.
    //
    pdoData = PdoGetData(hChild);
	pdoData->InstanceNo = InstanceNo;
	pdoData->hParentDevice = Device;

    //
    // Save the I/O target handle and adjust the I/O stack size:
    //
    devExt = GetDeviceContext(Device);
    pdoData->IoTargetToParent = devExt->IoTargetToSelf;
	ChildDeviceObject = WdfDeviceWdmGetDeviceObject(hChild);
	ParentDeviceObject = WdfDeviceWdmGetDeviceObject(Device);
	ChildDeviceObject->StackSize = ParentDeviceObject->StackSize+1;

	// Create a wait-lock object that will be used to synch access to positions[i]
	// The lock is created when the raw device is created so the raw device is set to be its parent
	WDF_OBJECT_ATTRIBUTES_INIT(&LockAttributes);
	LockAttributes.ParentObject = hChild;
	status =  WdfWaitLockCreate(&LockAttributes, &(devExt->positionLock));
    if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfWaitLockCreate failed 0x%x\n", status);
  		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfWaitLockCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    //
    // Configure the default queue associated with the control device object
    // to be Serial so that request passed to EvtIoDeviceControl are serialized.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //

    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoDeviceControl = vJoy_EvtIoDeviceControlForRawPdo;

    status = WdfIoQueueCreate(hChild,
                                        &ioQueueConfig,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &queue // pointer to default queue
                                        );
    if (!NT_SUCCESS(status)) {
		TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed 0x%x\n", status);
   		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfIoQueueCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
       goto Cleanup;
    }

    //
    // Set some properties for the child device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

    pnpCaps.Removable         = WdfTrue; // Remove Icon from " Devices and Printers"
    pnpCaps.SurpriseRemovalOK = WdfTrue;
    pnpCaps.NoDisplayInUI     = WdfTrue;

    // pnpCaps.Address  = InstanceNo;
    pnpCaps.UINumber = 0;

    WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

    //
    // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we
    // have to do the following to hide the device. Following call
    // tells the framework to report the device state in
    // IRP_MN_QUERY_DEVICE_STATE request.
    //
    WDF_DEVICE_STATE_INIT(&deviceState);
    deviceState.DontDisplayInUI = WdfTrue; // Remove Icon from Device manager
    WdfDeviceSetDeviceState(hChild, &deviceState);

	//
	// Create 16 interfaces
	//
	for (iInterface=1 ; iInterface <= MAX_N_DEVICES; iInterface++)
	{
		RtlStringCchPrintfW((NTSTRSAFE_PWSTR)RefStr, 20, VJOY_INTERFACE L"%03d", iInterface);
		RtlInitUnicodeString(&RefStr2, (PCWSTR)RefStr);
		status = WdfDeviceCreateDeviceInterface(hChild,&GUID_DEVINTERFACE_VJOY,&RefStr2);

		if (!NT_SUCCESS (status)) {
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateDeviceInterface number %d failed 0x%x\n", iInterface, status);
   			LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreateDeviceInterface", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
			goto Cleanup;
		}
	};

	// Mark all interfaces as unused
	pdoData->UsedInterfacesMask=0;


	//
	// Add this device to the FDO's collection of children.
    // After the child device is added to the static collection successfully,
    // driver must call WdfPdoMarkMissing to get the device deleted. It
    // shouldn't delete the child device directly by calling WdfObjectDelete.
    //
    status = WdfFdoAddStaticChild(Device, hChild);
    if (!NT_SUCCESS(status)) {
   		LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfFdoAddStaticChild", WdfDriverWdmGetDriverObject(WdfGetDriver()), status);
        goto Cleanup;
    }

    return STATUS_SUCCESS;

Cleanup:

    TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "KbFiltr_CreatePdo failed %x\n", status);
    //
    // Call WdfDeviceInitFree if you encounter an error while initializing
    // a new framework device object. If you call WdfDeviceInitFree,
    // do not call WdfDeviceCreate.
    //
    if (pDeviceInit != NULL) {
        WdfDeviceInitFree(pDeviceInit);
    }

    if(hChild) {
        WdfObjectDelete(hChild);
    }

    return status;
}