Exemple #1
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;
}
NTSTATUS
OsrFxEvtDeviceAdd(
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInit
    )
/*++
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

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES               attributes;
    NTSTATUS                            status;
    WDFDEVICE                           device;
    WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;
    WDF_IO_QUEUE_CONFIG                 ioQueueConfig;
    PDEVICE_CONTEXT                     pDevContext;
    WDFQUEUE                            queue;
    GUID                                activity;

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");

    //
    // 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);
    //
    // For usb devices, PrepareHardware callback is the to place select the
    // interface and configure the device.
    //
    pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware;

    //
    // These two callbacks start and stop the wdfusb pipe continuous reader
    // as we go in and out of the D0-working state.
    //

    pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceSelfManagedIoFlush = OsrFxEvtDeviceSelfManagedIoFlush;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

    //
    // 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_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
        return status;
    }

    //
    // Setup the activity ID so that we can log events using it.
    //

    activity = DeviceToActivityId(device);

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

    //
    // Get the device's friendly name and location so that we can use it in
    // error logging.  If this fails then it will setup dummy strings.
    //

    GetDeviceEventLoggingNames(device);

    //
    // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
    // that you don't get the popup in usermodewhen you surprise remove the device.
    //
    WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    //
    // Create a parallel default queue and register an event callback to
    // receive ioctl requests. We will create separate queues for
    // handling read and write requests. All other requests will be
    // completed with error status automatically by the framework.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                             WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl    = OsrFxEvtIoDeviceControl;
    
    //
    // By default, Static Driver Verifier (SDV) displays a warning if it 
    // doesn't find the EvtIoStop callback on a power-managed queue. 
    // The 'assume' below causes SDV to suppress this warning. If the driver 
    // has not explicitly set PowerManaged to WdfFalse, the framework creates
    // power-managed queues when the device is not a filter driver.  Normally 
    // the EvtIoStop is required for power-managed queues, but for this driver
    // it is not needed b/c the driver doesn't hold on to the requests for 
    // long time or forward them to other drivers. 
    // If the EvtIoStop callback is not implemented, the framework waits for
    // all driver-owned requests to be done before moving in the Dx/sleep 
    // states or before removing the device, which is the correct behavior 
    // for this type of driver. If the requests were taking an indeterminate
    // amount of time to complete, or if the driver forwarded the requests
    // to a lower driver/another stack, the queue should have an 
    // EvtIoStop/EvtIoResume.
    //
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    status = WdfIoQueueCreate(device,
                             &ioQueueConfig,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             &queue);// pointer to default queue
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                            "WdfIoQueueCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    //
    // We will create a separate sequential queue and configure it
    // to receive read requests.  We also need to register a EvtIoStop
    // handler so that we can acknowledge requests that are pending
    // at the target driver.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = OsrFxEvtIoRead;
    ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeRead);

    if(!NT_SUCCESS (status)){
        assert(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }


    //
    // We will create another sequential queue and configure it
    // to receive write requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite;
    ioQueueConfig.EvtIoStop  = OsrFxEvtIoStop;

    status = WdfIoQueueCreate(
                 device,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &queue // queue handle
             );

    if (!NT_SUCCESS (status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

     status = WdfDeviceConfigureRequestDispatching(
                    device,
                    queue,
                    WdfRequestTypeWrite);

    if(!NT_SUCCESS (status)){
        assert(NT_SUCCESS(status));
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
        goto Error;
    }

    //
    // Register a manual I/O queue for handling Interrupt Message Read Requests.
    // This queue will be used for storing Requests that need to wait for an
    // interrupt to occur before they can be completed.
    //
    WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);

    //
    // This queue is used for requests that dont directly access the device. The
    // requests in this queue are serviced only when the device is in a fully
    // powered state and sends an interrupt. So we can use a non-power managed
    // queue to park the requests since we dont care whether the device is idle
    // or fully powered up.
    //
    ioQueueConfig.PowerManaged = WdfFalse;

    status = WdfIoQueueCreate(device,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              &pDevContext->InterruptMsgQueue
                              );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfIoQueueCreate failed 0x%x\n", status);
        goto Error;
    }

    //
    // Register a device interface so that app can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(device,
                                            (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
                                            NULL); // Reference String

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfDeviceCreateDeviceInterface failed  %!STATUS!\n", status);
        goto Error;
    }

    // 
    // Create the lock that we use to serialize calls to ResetDevice(). As an 
    // alternative to using a WDFWAITLOCK to serialize the calls, a sequential 
    // WDFQUEUE can be created and reset IOCTLs would be forwarded to it.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;

    status = WdfWaitLockCreate(&attributes, &pDevContext->ResetDeviceWaitLock);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfWaitLockCreate failed  %!STATUS!\n", status);
        goto Error;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n");

    return status;

Error:

    //
    // Log fail to add device to the event log
    //
    EventWriteFailAddDevice(pDevContext->DeviceName,
                            pDevContext->Location,
                            status);

    return status;
}
//
// 作用相当于WDM中的AddDevice函数。
// 他是PNP过程中首当其冲被调用的回调函数。主要任务是创建设备对象。
// 设备对象在系统中以软件形式,代表外部的某个物理硬件设备。
//NTSTATUS PnpAdd(IN WDFDRIVER  Driver, IN PWDFDEVICE_INIT  DeviceInit)
NTSTATUS DrvClass::PnpAdd(IN PWDFDEVICE_INIT DeviceInit)
{
	NTSTATUS status;
	WDFDEVICE device;
	int nInstance = 0;
	PDEVICE_CONTEXT pContext = NULL;
	UNICODE_STRING DeviceName;
	UNICODE_STRING DosDeviceName;
	UNICODE_STRING RefString;
	WDFSTRING	   SymbolName;
	WDF_OBJECT_ATTRIBUTES attributes;
	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
	WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;

	WCHAR wcsDeviceName[] = L"\\Device\\CY001-0";		// 设备名
	WCHAR wcsDosDeviceName[] = L"\\DosDevices\\CY001-0";// 符号链接名
	WCHAR wcsRefString[] = L"CY001-0";					// 符号链接名
	int	  nLen = wcslen(wcsDeviceName);

	KDBG(DPFLTR_INFO_LEVEL, "[PnpAdd]");

	RtlInitUnicodeString(&DeviceName, wcsDeviceName) ;
	RtlInitUnicodeString(&DosDeviceName, wcsDosDeviceName);
	RtlInitUnicodeString(&RefString, wcsRefString);

	WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
	InitPnpPwrEvents(&pnpPowerCallbacks);
	WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	// 读、写请求的缓冲方式
	// 默认为Buffered方式,另外两种方式是Direct和Neither。
	WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);

	// 设定设备环境块长度
	// 宏内部会调用sizeof(DEVICE_CONTEXT)求结构体长度
	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

	// 驱动支持最多8个实例,即当多个开发板连到PC上时,驱动对它们给予并行支持。
	// 不同的设备对象,各以其名称的尾数(0-7)相别,并将此尾数称作设备ID。
	// 下面的代码逻辑为当前设备对象寻找一个可用ID。
	for(nInstance = 0; nInstance < MAX_INSTANCE_NUMBER; nInstance++)
	{
		// 修改设备ID
		wcsDeviceName[nLen-1] += nInstance;

		// 尝试命名;命名可能失败,失败的原因包括:名称无效、名称已存在等
		WdfDeviceInitAssignName(DeviceInit, &DeviceName);

		// 创建WDF设备
		// 如能成功,则命名亦成功。
		status = WdfDeviceCreate(&DeviceInit, &attributes, &device);  
		if(!NT_SUCCESS(status))
		{
			if(status == STATUS_OBJECT_NAME_COLLISION)// 名字冲突
			{
				KDBG(DPFLTR_ERROR_LEVEL, "Already exist: %wZ", &DeviceName);
			}
			else
			{
				KDBG(DPFLTR_ERROR_LEVEL, "WdfDeviceCreate failed with status 0x%08x!!!", status);
				return status;
			}
		}else
		{
			KdPrint(("Device name: %wZ", &DeviceName));
			break;
		}
	}

	// 如失败,可能是连接的开发板数量太多;
	// 建议使用WinOBJ查看系统中的设备名称。
	if (!NT_SUCCESS(status)) 
		return status;

	m_hDevice = device;// 保存设备对象句柄

	// 创建符号链接,应用程序根据符号链接查看并使用内核设备。
	// 除了创建符号链接外,现在更好的方法是使用WdfDeviceCreateDeviceInterface创建设备接口。
	// 设备接口能保证名字不会冲突,但不具有可读性,所以我们仍采用符号链接形式。
	nLen = wcslen(wcsDosDeviceName);
	wcsDosDeviceName[nLen-1] += nInstance;

	status = WdfDeviceCreateSymbolicLink(device, &DosDeviceName);
	if(!NT_SUCCESS(status))
	{
		KDBG(DPFLTR_INFO_LEVEL, "Failed to create symbol link: 0x%08X", status);
		return status;
	}

	// 初始化环境块
	// GetDeviceContext是一个函数指针,由宏WDF_DECLARE_CONTEXT_TYPE_WITH_NAME定义。
	// 参看pulibc.h中的说明。
	pContext = GetDeviceContext(device);
	RtlZeroMemory(pContext, sizeof(DEVICE_CONTEXT));
	pContext->par1 = this; // 通过this指针可以得到一切

	// PNP属性。允许设备异常拔除,系统不会弹出错误框。
	WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
	InitPnpCap(&pnpCapabilities);
	WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);

	status = CreateWDFQueues();
	if(!NT_SUCCESS(status))
		return status;

	return status;
}
NTSTATUS
VIOSerialDeviceListCreatePdo(
    IN WDFCHILDLIST DeviceList,
    IN PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
    IN PWDFDEVICE_INIT ChildInit
    )
{
    PVIOSERIAL_PORT                 pport = NULL;
    NTSTATUS                        status = STATUS_SUCCESS;

    WDFDEVICE                       hChild = NULL;

    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS    PnpPowerCallbacks;
    WDF_DEVICE_PNP_CAPABILITIES     pnpCaps;
    WDF_DEVICE_STATE                deviceState;
    WDF_IO_QUEUE_CONFIG             queueConfig;
    PRAWPDO_VIOSERIAL_PORT          rawPdo = NULL;
    WDF_FILEOBJECT_CONFIG           fileConfig;

    DECLARE_CONST_UNICODE_STRING(deviceId, PORT_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation, L"RedHat VIOSerial Port" );

    DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);

    UNREFERENCED_PARAMETER(DeviceList);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    pport = CONTAINING_RECORD(IdentificationDescription,
                                 VIOSERIAL_PORT,
                                 Header
                                 );

    WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_SERIAL_PORT);
    WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);

    do
    {
        WdfDeviceInitSetExclusive(ChildInit, TRUE);
        status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_PORT_DEVICE);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignRawDevice failed - 0x%x\n", status);
           break;
        }

        status = WdfDeviceInitAssignSDDLString(ChildInit, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceInitAssignSDDLString failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignDeviceID failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddHardwareID(ChildInit, &deviceId);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAddHardwareID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"%02u",
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed - 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfPdoInitAssignInstanceID failed - 0x%x\n", status);
           break;
        }

        status = RtlUnicodeStringPrintf(
                                 &buffer,
                                 L"vport%up%u",
                                 pport->DeviceId,
                                 pport->PortId
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "RtlUnicodeStringPrintf failed 0x%x\n", status);
           break;
        }

        status = WdfPdoInitAddDeviceText(
                                 ChildInit,
                                 &buffer,
                                 &deviceLocation,
                                 0x409
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfPdoInitAddDeviceText failed 0x%x\n", status);
           break;
        }

        WdfPdoInitSetDefaultLocale(ChildInit, 0x409);

        WDF_FILEOBJECT_CONFIG_INIT(
                                 &fileConfig,
                                 VIOSerialPortCreate,
                                 VIOSerialPortClose,
                                 WDF_NO_EVENT_CALLBACK
                                 );

        WdfDeviceInitSetFileObjectConfig(
                                 ChildInit,
                                 &fileConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES
                                 );

        WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
        PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry;
        PnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = VIOSerialPortEvtDeviceD0ExitPreInterruptsDisabled;
        PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit;
        WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks);

        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
        attributes.SynchronizationScope = WdfSynchronizationScopeDevice;
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfDeviceCreate(
                                 &ChildInit,
                                 &attributes,
                                 &hChild
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreate failed 0x%x\n", status);
           break;
        }

        rawPdo = RawPdoSerialPortGetData(hChild);
        rawPdo->port = pport;
        pport->Device = hChild;

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential
                                 );

        queueConfig.EvtIoDeviceControl = VIOSerialPortDeviceControl;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->IoctlQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->IoctlQueue,
                                 WdfRequestTypeDeviceControl
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (IoCtrl Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
                                 WdfIoQueueDispatchSequential);

        queueConfig.EvtIoRead   =  VIOSerialPortRead;
        queueConfig.EvtIoStop   =  VIOSerialPortIoStop;
        status = WdfIoQueueCreate(hChild,
                                 &queueConfig,
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &pport->ReadQueue
                                 );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate (Read Queue) failed 0x%x\n", status);
           break;
        }

        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->ReadQueue,
                                 WdfRequestTypeRead
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Read Queue): 0x%x\n", status);
           break;
        }

        WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential);
        queueConfig.AllowZeroLengthRequests = WdfFalse;
        queueConfig.EvtIoWrite = VIOSerialPortWrite;

        status = WdfIoQueueCreate(hChild, &queueConfig,
            WDF_NO_OBJECT_ATTRIBUTES, &pport->WriteQueue);

        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "WdfIoQueueCreate failed (Write Queue): 0x%x\n", status);
           break;
        }
        status = WdfDeviceConfigureRequestDispatching(
                                 hChild,
                                 pport->WriteQueue,
                                 WdfRequestTypeWrite
                                 );

        if(!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "DeviceConfigureRequestDispatching failed (Write Queue): 0x%x\n", status);
           break;
        }

        WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);

        pnpCaps.NoDisplayInUI    =  WdfTrue;
        pnpCaps.Removable        =  WdfTrue;
        pnpCaps.EjectSupported   =  WdfTrue;
        pnpCaps.SurpriseRemovalOK=  WdfTrue;
        pnpCaps.Address          =  pport->DeviceId;
        pnpCaps.UINumber         =  pport->PortId;

        WdfDeviceSetPnpCapabilities(hChild, &pnpCaps);

        WDF_DEVICE_STATE_INIT(&deviceState);
        deviceState.DontDisplayInUI = WdfTrue;
        WdfDeviceSetDeviceState(hChild, &deviceState);

        status = WdfDeviceCreateDeviceInterface(
                                 hChild,
                                 &GUID_VIOSERIAL_PORT,
                                 NULL
                                 );

        if (!NT_SUCCESS (status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfDeviceCreateDeviceInterface failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->InBufLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = hChild;
        status = WdfSpinLockCreate(
                                &attributes,
                                &pport->OutVqLock
                                );
        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfSpinLockCreate failed 0x%x\n", status);
           break;
        }

    } while (0);

    if (!NT_SUCCESS(status))
    {
        // We can send this before PDO is PRESENT since the device won't send any response.
        VIOSerialSendCtrlMsg(pport->BusDevice, pport->PortId, VIRTIO_CONSOLE_PORT_READY, 0);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s status 0x%x\n", __FUNCTION__, status);
    return status;
}
NTSTATUS
XenPci_EvtChildListCreateDevice(WDFCHILDLIST child_list,
  PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER identification_header,
  PWDFDEVICE_INIT child_init) {
  NTSTATUS status = STATUS_SUCCESS;
  WDF_OBJECT_ATTRIBUTES child_attributes;
  WDFDEVICE child_device;
  PXENPCI_PDO_IDENTIFICATION_DESCRIPTION identification = (PXENPCI_PDO_IDENTIFICATION_DESCRIPTION)identification_header;
  WDF_DEVICE_PNP_CAPABILITIES child_pnp_capabilities;
  DECLARE_UNICODE_STRING_SIZE(buffer, 512);
  DECLARE_CONST_UNICODE_STRING(location, L"Xen Bus");
  PXENPCI_PDO_DEVICE_DATA xppdd;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfChildListGetDevice(child_list));
  //WDF_PDO_EVENT_CALLBACKS pdo_callbacks;
  WDF_PNPPOWER_EVENT_CALLBACKS child_pnp_power_callbacks;
  //UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
  WDF_DEVICE_POWER_CAPABILITIES child_power_capabilities;
  
  FUNCTION_ENTER();

  WdfDeviceInitSetDeviceType(child_init, FILE_DEVICE_UNKNOWN);
  
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&child_pnp_power_callbacks);
  child_pnp_power_callbacks.EvtDeviceD0Entry = XenPciPdo_EvtDeviceD0Entry;
  child_pnp_power_callbacks.EvtDeviceD0Exit = XenPciPdo_EvtDeviceD0Exit;
  child_pnp_power_callbacks.EvtDeviceUsageNotification = XenPciPdo_EvtDeviceUsageNotification;
  WdfDeviceInitSetPnpPowerEventCallbacks(child_init, &child_pnp_power_callbacks);

  FUNCTION_MSG("device = '%s', index = '%d', path = '%s'\n",
    identification->device, identification->index, identification->path);
  
  //status = WdfDeviceInitAssignWdmIrpPreprocessCallback(child_init, XenPciPdo_EvtDeviceWdmIrpPreprocess_START_DEVICE,
  //  IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  //if (!NT_SUCCESS(status)) {
  //  return status;
  //}
  
  //WDF_PDO_EVENT_CALLBACKS_INIT(&pdo_callbacks);
  //pdo_callbacks.EvtDeviceResourcesQuery = XenPciPdo_EvtDeviceResourcesQuery;
  //pdo_callbacks.EvtDeviceResourceRequirementsQuery = XenPciPdo_EvtDeviceResourceRequirementsQuery;
  //pdo_callbacks.EvtDeviceEject = XenPciPdo_EvtDeviceEject;
  //pdo_callbacks.EvtDeviceSetLock  = XenPciPdo_EvtDeviceSetLock;
  //WdfPdoInitSetEventCallbacks(child_init, &pdo_callbacks);

  RtlUnicodeStringPrintf(&buffer, L"xen\\%S", identification->device);
  status = WdfPdoInitAssignDeviceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddHardwareID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  status = WdfPdoInitAddCompatibleID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"%02d", identification->index);
  status = WdfPdoInitAssignInstanceID(child_init, &buffer);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  
  RtlUnicodeStringPrintf(&buffer, L"Xen %S device #%d", identification->device, identification->index);
  status = WdfPdoInitAddDeviceText(child_init, &buffer, &location, 0x0409);
  if (!NT_SUCCESS(status))
  {
    return status;
  }
  WdfPdoInitSetDefaultLocale(child_init, 0x0409);

  WdfDeviceInitSetPowerNotPageable(child_init);

  WdfDeviceInitRegisterPnpStateChangeCallback(child_init, WdfDevStatePnpQueryCanceled, XenPci_EvtDevicePnpStateChange, StateNotificationEnterState);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&child_attributes, XENPCI_PDO_DEVICE_DATA);
  status = WdfDeviceCreate(&child_init, &child_attributes, &child_device);
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  xppdd = GetXppdd(child_device);
  
  xppdd->wdf_device = child_device;
  xppdd->wdf_device_bus_fdo = WdfChildListGetDevice(child_list);
  xppdd->xpdd = xpdd;

  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(child_device, WdfSpecialFileDump, TRUE);

  WDF_DEVICE_PNP_CAPABILITIES_INIT(&child_pnp_capabilities);
  child_pnp_capabilities.LockSupported = WdfFalse;
  child_pnp_capabilities.EjectSupported  = WdfTrue;
  child_pnp_capabilities.Removable  = WdfTrue;
  child_pnp_capabilities.DockDevice  = WdfFalse;
  child_pnp_capabilities.UniqueID  = WdfFalse;
  child_pnp_capabilities.SilentInstall  = WdfTrue;
  child_pnp_capabilities.SurpriseRemovalOK  = WdfTrue;
  child_pnp_capabilities.HardwareDisabled = WdfFalse;
  WdfDeviceSetPnpCapabilities(child_device, &child_pnp_capabilities);

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&child_power_capabilities);
  child_power_capabilities.DeviceD1 = WdfTrue;
  child_power_capabilities.WakeFromD1 = WdfTrue;
  child_power_capabilities.DeviceWake = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  child_power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  child_power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  child_power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  child_power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(child_device, &child_power_capabilities);  

  RtlStringCbCopyA(xppdd->path, ARRAY_SIZE(xppdd->path), identification->path);
  RtlStringCbCopyA(xppdd->device, ARRAY_SIZE(xppdd->device), identification->device);
  xppdd->index = identification->index;
  KeInitializeEvent(&xppdd->backend_state_event, SynchronizationEvent, FALSE);
  ExInitializeFastMutex(&xppdd->backend_state_mutex);
  xppdd->backend_state = XenbusStateUnknown;
  xppdd->frontend_state = XenbusStateUnknown;
  xppdd->backend_path[0] = '\0';
  xppdd->backend_id = 0;
    
  FUNCTION_EXIT();
  
  return status;
}
Exemple #6
0
NTSTATUS
kmdf1394_EvtDeviceAdd (
                       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 ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    WDF_PNPPOWER_EVENT_CALLBACKS  pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES fdoAttributes,lockAttributes;
    WDFDEVICE device;
    WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
    WDF_IO_QUEUE_CONFIG ioQueueConfig;

    UNREFERENCED_PARAMETER (Driver);

    PAGED_CODE();

    Enter();

    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.

    //
    // These two callbacks set up and tear down hardware state,
    // specifically that which only has to be done once.
    //

    pnpPowerCallbacks.EvtDevicePrepareHardware = kmdf1394_EvtPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = kmdf1394_EvtReleaseHardware;

    pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup = \
        kmdf1394_EvtDeviceSelfManagedIoCleanup;

    pnpPowerCallbacks.EvtDeviceD0Entry = kmdf1394_EvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = kmdf1394_EvtDeviceD0Exit;

    //
    // Register the PnP and power callbacks. Power policy related callbacks
    // will be registered// later in SotwareInit.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks (DeviceInit, &pnpPowerCallbacks);
    if (!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n",
                            ntStatus);
        return ntStatus;
    }

    //
    // We'll allow multiple handles to be opened to this device driver
    // so we'll set exclusivity to FALSE.
    //
    WdfDeviceInitSetExclusive (DeviceInit, FALSE);

    //
    // Specify the size and type of device context.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&fdoAttributes, DEVICE_EXTENSION);

    ntStatus = WdfDeviceCreate (&DeviceInit, &fdoAttributes, &device);

    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceInitialize failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }


    deviceExtension = GetDeviceContext (device);
    deviceExtension->WdfDevice = device;

    DoTraceLevelMessage(TRACE_LEVEL_INFORMATION, 
                        TRACE_FLAG_PNP,
                        "PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n",
                        WdfDeviceWdmGetPhysicalDevice (device),
                        WdfDeviceWdmGetDeviceObject (device),
                        WdfDeviceWdmGetAttachedDevice(device),
                        deviceExtension);

    //
    // Tell the Framework that this device will need an interface so that
    // application can interact with it.
    //

    ntStatus = WdfDeviceCreateDeviceInterface (
        device,
        (LPGUID) &GUID_KMDF_VDEV,
        NULL);
    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    //
    // 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);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities (device, &pnpCaps);

    //
    // save the device object we created as our physical device object
    //
    deviceExtension->PhysicalDeviceObject = \
        WdfDeviceWdmGetPhysicalDevice (device);

    if (NULL == deviceExtension->PhysicalDeviceObject) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n");
        return STATUS_UNSUCCESSFUL;
    }

    //
    // This is our default IoTarget representing the deviceobject
    // we are attached to.
    //
    deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device);
    deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device);

    if (NULL == deviceExtension->StackDeviceObject) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n");
        return STATUS_UNSUCCESSFUL;
    }


    //
    // Create a automanaged queue for dispatching ioctl requests.
    // All other requests are automatically failed by the framework.
    // By creating an automanaged queue we don't have to worry about
    // PNP/Power synchronization.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (
        &ioQueueConfig,
        WdfIoQueueDispatchParallel);

    ioQueueConfig.EvtIoDeviceControl = kmdf1394_EvtIoDeviceControl;
    
    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    ntStatus = WdfIoQueueCreate (
        deviceExtension->WdfDevice,
        &ioQueueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceExtension->IoctlQueue);
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS (ntStatus)) 
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfIoQueueCreate failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    //
    // Create an additional queue to hold bus reset requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT (&ioQueueConfig, WdfIoQueueDispatchManual);

    __analysis_assume(ioQueueConfig.EvtIoStop != 0);
    ntStatus = WdfIoQueueCreate (
        deviceExtension->WdfDevice,
        &ioQueueConfig,
        WDF_NO_OBJECT_ATTRIBUTES,
        &deviceExtension->BusResetRequestsQueue);
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "Error Creating Reset Request Queue %!STATUS!\n",
                            ntStatus);
        return ntStatus;
    }
    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (&lockAttributes,&deviceExtension->CromSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate CromSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }


    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->AsyncSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate AsyncSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->IsochSpinLock );
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate IsochSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    WDF_OBJECT_ATTRIBUTES_INIT (&lockAttributes);
    lockAttributes.ParentObject = device;

    ntStatus = WdfSpinLockCreate (
        &lockAttributes,
        &deviceExtension->IsochResourceSpinLock);
    if(!NT_SUCCESS (ntStatus))
    {
        DoTraceLevelMessage(TRACE_LEVEL_ERROR, 
                            TRACE_FLAG_PNP, 
                            "WdfSpinLockCreate IsochResourceSpinLock failed %!STATUS!\n", 
                            ntStatus);
        return ntStatus;
    }

    InitializeListHead (&deviceExtension->CromData);
    InitializeListHead (&deviceExtension->AsyncAddressData);
    InitializeListHead (&deviceExtension->IsochDetachData);
    InitializeListHead (&deviceExtension->IsochResourceData);

    ExitS(ntStatus);
    return(ntStatus);
} // kmdf1394_PnpAddDevice
Exemple #7
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;
}
Exemple #8
0
NTSTATUS
KbFiltr_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,KBFILTR_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID );
    DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" );
    DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN);

    DebugPrint(("Entered KbFiltr_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;
        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_DEVCLASS_KEYBOARD);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Since keyboard is secure device, we must protect ourselves from random
    // users sending ioctls and creating trouble.
    //
    status = WdfDeviceInitAssignSDDLString(pDeviceInit,
                                           &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

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

    //
    // For RAW PDO, there is no need to provide BusQueryHardwareIDs
    // and BusQueryCompatibleIDs IDs unless we are running on
    // Windows 2000.
    //
    if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) {
        //
        // On Win2K, we must provide a HWID for the device to get enumerated.
        // Since we are providing a HWID, we will have to provide a NULL inf
        // to avoid the "found new device" popup and get the device installed
        // silently.
        //
        status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId);
        if (!NT_SUCCESS(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, L"%02d", InstanceNo);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Provide a description about the device. This text is usually read from
    // the device. In the case of USB device, this text comes from the string
    // descriptor. 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,L"Keyboard_Filter_%02d", InstanceNo );
    if (!NT_SUCCESS(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
                                        );
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409);
    
    //
    // 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);

    //
    // Set up our queue to allow forwarding of requests to the parent
    // This is done so that the cached Keyboard Attributes can be retrieved
    //
    WdfPdoInitAllowForwardingRequestToParent(pDeviceInit);

    status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild);
    if (!NT_SUCCESS(status)) {
        goto Cleanup;
    }

    //
    // Get the device context.
    //
    pdoData = PdoGetData(hChild);

    pdoData->InstanceNo = InstanceNo;

    //
    // Get the parent queue we will be forwarding to
    //
    devExt = FilterGetData(Device);
    pdoData->ParentQueue = devExt->rawPdoQueue;

    //
    // 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 = KbFilter_EvtIoDeviceControlForRawPdo;

    status = WdfIoQueueCreate(hChild,
                                        &ioQueueConfig,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &queue // pointer to default queue
                                        );
    if (!NT_SUCCESS(status)) {
        DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status));
        goto Cleanup;
    }

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

    pnpCaps.Removable         = WdfTrue;
    pnpCaps.SurpriseRemovalOK = WdfTrue;
    pnpCaps.NoDisplayInUI     = WdfTrue;

    pnpCaps.Address  = InstanceNo;
    pnpCaps.UINumber = InstanceNo;

    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;
    WdfDeviceSetDeviceState(hChild, &deviceState);

    //
    // Tell the Framework that this device will need an interface so that
    // application can find our device and talk to it.
    //
    status = WdfDeviceCreateDeviceInterface(
                 hChild,
                 &GUID_DEVINTERFACE_KBFILTER,
                 NULL
             );

    if (!NT_SUCCESS (status)) {
        DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));
        goto Cleanup;
    }

    //
    // 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)) {
        goto Cleanup;
    }

    //
    // pDeviceInit will be freed by WDF.
    //
    return STATUS_SUCCESS;

Cleanup:

    DebugPrint(("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;
}
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;
}
Exemple #10
0
NTSTATUS
t1394_EvtDeviceAdd(
   /*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;
    PDEVICE_EXTENSION               deviceExtension;
    PNODE_DEVICE_EXTENSION          pNodeExt;
    WDF_PNPPOWER_EVENT_CALLBACKS    pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES           fdoAttributes,lockAttributes;
    WDFDEVICE                       device;
    WDF_DEVICE_PNP_CAPABILITIES     pnpCaps;
    WDF_IO_QUEUE_CONFIG             ioQueueConfig;
    WDF_IO_TARGET_OPEN_PARAMS       openParams;

    //UNREFERENCED_PARAMETER(Driver);

    //ENTER("t1394_PnpAddDevice");

    //
    // Zero out the PnpPowerCallbacks structure.
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    //
    // Set Callbacks for any of the functions we are interested in.
    // If no callback is set, Framework will take the default action
    // by itself.

    //
    // These two callbacks set up and tear down hardware state,
    // specifically that which only has to be done once.
    //

    pnpPowerCallbacks.EvtDevicePrepareHardware = t1394_EvtPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware = t1394_EvtReleaseHardware;

    pnpPowerCallbacks.EvtDeviceSelfManagedIoCleanup =
        t1394_EvtDeviceSelfManagedIoCleanup;

    pnpPowerCallbacks.EvtDeviceD0Entry = t1394_EvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit  = t1394_EvtDeviceD0Exit;

    //
    // Register the PnP and power callbacks. Power policy related callbacks
    // will be registered// later in SotwareInit.
    //
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
    if ( !NT_SUCCESS(status)) {
        //TRACE(TL_ERROR, ("WdfDeviceInitSetPnpPowerEventCallbacks failed %x\n",
        //                 status));
        return status;
    }

    WdfDeviceInitSetExclusive(DeviceInit, FALSE);

    //
    // Specify the size and type of device context.
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, DEVICE_EXTENSION);

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

    if ( !NT_SUCCESS(status)) {
        //TRACE(TL_ERROR, ("WdfDeviceInitialize failed %x\n", status));
        return status;
    }


    deviceExtension = GetDeviceContext (device);
    deviceExtension->WdfDevice = device;

    //TRACE(TL_TRACE, ("PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n",
    //                 WdfDeviceWdmGetPhysicalDevice (device),
    //                 WdfDeviceWdmGetDeviceObject (device),
    //                 WdfDeviceWdmGetAttachedDevice(device),
    //                 deviceExtension));

    //
    // Tell the Framework that this device will need an interface so that
    // application can interact with it.
    //

    status = WdfDeviceCreateDeviceInterface(
                 device,
#if defined(_1394VDEV_DRIVER_)
                 (LPGUID) &GUID_1394VDEV,
#else
                 (LPGUID) &GUID_1394DIAG,
#endif
                 NULL
             );

    if (!NT_SUCCESS (status)) {
        //TRACE(TL_ERROR, ("WdfDeviceCreateDeviceInterface failed %x\n", status));
        return status;
    }

    //
    // 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);
    pnpCaps.SurpriseRemovalOK = WdfTrue;

    WdfDeviceSetPnpCapabilities(device, &pnpCaps);

    // save the device object we created as our physical device object
    deviceExtension->PhysicalDeviceObject =
        WdfDeviceWdmGetPhysicalDevice (device);

    if (deviceExtension->PhysicalDeviceObject == NULL) {
        //TRACE(TL_ERROR, ("WdfDeviceWdmGetPhysicalDevice: NULL DeviceObject\n"));
        return STATUS_UNSUCCESSFUL;
    }

    //
    // This is our default IoTarget representing the deviceobject
    // we are attached to.
    //
    deviceExtension->StackIoTarget = WdfDeviceGetIoTarget(device);
    deviceExtension->StackDeviceObject = WdfDeviceWdmGetAttachedDevice(device);

    if (deviceExtension->StackDeviceObject == NULL) {
        //TRACE(TL_ERROR, ("WdfDeviceWdmGetAttachedDevice: NULL DeviceObject\n"));
        return STATUS_UNSUCCESSFUL;
    }

    // Patch: this code is not in DDK 7600.16385.1  {
    //
    // Get the port device object from the passed in PhysicalDeviceObject
    // created by the 1394 stack for us.
    // Note: we can't use the top of the stack and get its device extension
    // in case there is a filter driver between us and our PDO.
    //
    //pNodeExt = WdfDeviceWdmGetPhysicalDevice(device)->DeviceExtension;
    //deviceExtension->PortDeviceObject = pNodeExt->PortDeviceObject;
    // Patch: this code is not in DDK 7600.16385.1 }

    //TRACE(TL_TRACE, ("PortDeviceObject = 0x%x\n",
    //                 deviceExtension->PortDeviceObject));

    //
    // Create a automanaged queue for dispatching ioctl requests.
    // All other requests are automatically failed by the framework.
    // By creating an automanaged queue we don't have to worry about
    // PNP/Power synchronization.
    // A default queue gets all the requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
        &ioQueueConfig,
        WdfIoQueueDispatchParallel
    );

    ioQueueConfig.EvtIoDeviceControl = t1394_EvtIoDeviceControl;

    status = WdfIoQueueCreate(
                 deviceExtension->WdfDevice,
                 &ioQueueConfig,
                 WDF_NO_OBJECT_ATTRIBUTES,
                 &deviceExtension->IoctlQueue // queue handle
             );

    if (!NT_SUCCESS (status)) {
         //TRACE(TL_ERROR, ("WdfIoQueueCreate failed 0x%x\n", status));
        return status;
    }

    //
    // Create an additional queue to hold bus reset requests.
    //
    WDF_IO_QUEUE_CONFIG_INIT(
        &ioQueueConfig,
        WdfIoQueueDispatchManual
        );

    status = WdfIoQueueCreate (
                   deviceExtension->WdfDevice,
                   &ioQueueConfig,
                   WDF_NO_OBJECT_ATTRIBUTES,
                   &deviceExtension->BusResetRequestsQueue
                   );

    if(!NT_SUCCESS (status)){
        //TRACE(TL_ERROR, ("Error Creating Reset Request Queue 0x%x\n",
        //                 status));
        return status;
    }

    //
    // Create another IoTarget representing PortDeviceObject so that
    // we can send async requests in rawmode directly to the port device.
    //
    WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(&openParams,
                                                pNodeExt->PortDeviceObject);
    status = WdfIoTargetCreate(device,
                                WDF_NO_OBJECT_ATTRIBUTES,
                                &deviceExtension->PortDeviceIoTarget);
    if (!NT_SUCCESS (status)) {
        //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status));
        return status;
    }

    status = WdfIoTargetOpen(deviceExtension->PortDeviceIoTarget, &openParams);
    if (!NT_SUCCESS (status)) {
        //TRACE(TL_ERROR, ("WdfIoTargetCreate failed 0x%x\n", status));
        return status;
    }


    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;
    // initialize the spinlock/list to store the bus reset irps...

    status = WdfSpinLockCreate(&lockAttributes,&deviceExtension->CromSpinLock );
    if(!NT_SUCCESS(status)){
         //TRACE(TL_ERROR, ("WdfSpinLockCreate CromSpinLock "
         //                 "failed 0x%x\n", status));
        return status;
    }


    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;

    status = WdfSpinLockCreate(&lockAttributes,
                               &deviceExtension->AsyncSpinLock );
    if(!NT_SUCCESS(status)){
         //TRACE(TL_ERROR, ("WdfSpinLockCreate AsyncSpinLock "
         //                 "failed 0x%x\n", status));
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;

    status = WdfSpinLockCreate(&lockAttributes,
                               &deviceExtension->IsochSpinLock );
    if(!NT_SUCCESS(status)){
         //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochSpinLock "
         //                 "failed 0x%x\n", status));
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&lockAttributes);
    lockAttributes.ParentObject = device;

    status = WdfSpinLockCreate(&lockAttributes,
                               &deviceExtension->IsochResourceSpinLock );
    if(!NT_SUCCESS(status)){
         //TRACE(TL_ERROR, ("WdfSpinLockCreate IsochResourceSpinLock "
         //                 "failed 0x%x\n", status));
        return status;
    }
    InitializeListHead(&deviceExtension->CromData);
    InitializeListHead(&deviceExtension->AsyncAddressData);
    InitializeListHead(&deviceExtension->IsochDetachData);
    InitializeListHead(&deviceExtension->IsochResourceData);

    //EXIT("t1394_PnpAddDevice", status);

    return(status);
} // t1394_PnpAddDevice
Exemple #11
0
NTSTATUS EvtDeviceAdd(
                      IN WDFDRIVER  Driver,
                      IN PWDFDEVICE_INIT  DeviceInit
                      )
{
  NTSTATUS status;
  WDFDEVICE device;									// Device object
  PDEVICE_CONTEXT devCtx = NULL;					// Pointer to a device context
  WDF_OBJECT_ATTRIBUTES attributes;					// Object attribute
  WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;	// PNP Power event callback
  WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;		//

  UNREFERENCED_PARAMETER(Driver);

  /*Set the callback functions that will be executed on PNP and Power events*/
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);	// Init pnpPowerCallbacks
  pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
  pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
  pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
  WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);	// Setup pnpPowerCallbacks

  WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);	// Buffered IO type

  /*Initialize storage for the device context*/
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

  /*Create a device instance.*/
  status = WdfDeviceCreate(&DeviceInit, &attributes, &device);  
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfDeviceCreate failed with status 0x%08x\n", status));
    return status;
  }

  /*Set the PNP capabilities of our device. we don't want an annoying
    popup if the device is pulled out of the USB slot.*/
  WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
  pnpCapabilities.Removable = WdfTrue;				// Can hot-unplug
  pnpCapabilities.SurpriseRemovalOK = WdfTrue;		//
  WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);
  
  devCtx = GetDeviceContext(device);

  /*Create a WDF memory object for the memory that is occupied by the
    WdfMemLEDArrayState variable in the device context.
    this way we have the value itself handy for debugging purposes, and
    we have a WDF memory handle that can be used for passing to the low
    level USB functions.
    this alleviates the need to getting the buffer at run time.*/
  status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES,
                           &devCtx->D0LEDArrayState,
                           sizeof(devCtx->D0LEDArrayState),
                           &devCtx->WdfMemLEDArrayState);	// for Debbug 
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfMemoryCreatePreallocated failed with status 0x%08x\n", status));
    return status;
  }

  // Create Queues for handling IO request
  status = CreateQueues(device, devCtx);
  if(!NT_SUCCESS(status))
    return status;

  // Create Device Interface
  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEV_IF_LEDSCTRL, NULL);
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status));
    return status;
  }

  return status;
  
}
Exemple #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;
}
Exemple #13
0
NTSTATUS
FireShockCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
)
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    DeviceInit - Pointer to an opaque init structure. Memory for this
                    structure will be freed by the framework when the WdfDeviceCreate
                    succeeds. So don't access the structure after that point.

Return Value:

    NTSTATUS

--*/
{
    WDF_PNPPOWER_EVENT_CALLBACKS    pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES           deviceAttributes;
    WDFDEVICE                       device;
    NTSTATUS                        status;
    WDF_DEVICE_PNP_CAPABILITIES     pnpCapabilities;

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = FireShockEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry = FireShockEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit = FireShockEvtDeviceD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

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

    if (NT_SUCCESS(status)) 
    {
        WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
        pnpCapabilities.Removable = WdfTrue;
        pnpCapabilities.SurpriseRemovalOK = WdfTrue;
        WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        status = WdfDeviceCreateDeviceInterface(
            device,
            &GUID_DEVINTERFACE_FIRESHOCK,
            NULL // ReferenceString
        );

        if (NT_SUCCESS(status)) {
            //
            // Initialize the I/O Package and any Queues
            //
            status = FireShockQueueInitialize(device);

            if (NT_SUCCESS(status))
            {
                status = FireShockIoReadQueueInitialize(device);
            }
        }
    }

    return status;
}