Example #1
0
// Add device
NTSTATUS GFilterAddDevice( 	IN	WDFDRIVER			Driver,
							IN	PWDFDEVICE_INIT		DeviceInit)
{
	NTSTATUS				status;
	WDF_OBJECT_ATTRIBUTES 	deviceAttributes;
	WDFDEVICE 				device;
	PFILTER_EXTENSION 		filtExt;
	WDF_IO_QUEUE_CONFIG		ioQueueConfig;
	WDFQUEUE				ioDefaultQueue;

	DEBUG("Adding Device");

	// Indicate we are a filter driver, This forwards all IRPs on to the lower filters
	WdfFdoInitSetFilter(DeviceInit);

	// Setup the actual filter for the IRPs
#ifdef USE_SETIOINCALLERCONTEXTCALLBACK
	// Use built in KMDF filter
	WdfDeviceInitSetIoInCallerContextCallback(	DeviceInit, 
												GFilterIOCallback);
#endif

	// Create a new device
	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(	&deviceAttributes, 
												FILTER_EXTENSION);
	// no cleanup callback needed -- deviceAttributes.EvtCleanupCallback = GFilterDeviceCleanUp; 	// Set device unload callback
	status = WdfDeviceCreate(	&DeviceInit, 				// Create the device
				 				&deviceAttributes, 
				 				&device);
	CHECKSTATUS(status, return(status));

	// Create the filter extension -- We don't really care about this really
	filtExt = FilterGetData(device);
	filtExt->Instance = 0x00;

#ifndef USE_SETIOINCALLERCONTEXTCALLBACK
	// Create IO queue and set callbacks to be filtered.
	//!todo, we created a parrallel que here but some drivers may need multiple parallel queues which is not done
	WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(	&ioQueueConfig,					// Create parallel IO queue in case the device we filter does not like sequential
											WdfIoQueueDispatchParallel );
	ioQueueConfig.EvtIoRead 	= GFilterRead;	// Read
	ioQueueConfig.EvtIoWrite 	= GFilterWrite;	// Write
	status = WdfIoQueueCreate(	device,
								&ioQueueConfig,
								WDF_NO_OBJECT_ATTRIBUTES,
								&ioDefaultQueue);
	CHECKSTATUS(status, ERROR("Failed to create queues. status=0x%0.4x",status); goto GFilterAddDeviceCleanup);		
#endif

	// Create sideband communications to userspace
#ifdef USE_CONTROL_DEVICE
	GFilterCreateControlDevice(	device,
								++DeviceInstances); //!todo, should we lock instance ??
#else
	GFilterCreateRawPDO(	device,
							++DeviceInstances); //!todo, should we lock instance ??
#endif
GFilterAddDeviceCleanup:
	return(status);
}
Example #2
0
File: device.c Project: MHesham/bsp
VCHIQ_PAGED_SEGMENT_BEGIN

/*++

Routine Description:

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

Arguments:

     DeviceInitPtr - 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

--*/
_Use_decl_annotations_
NTSTATUS VchiqCreateDevice (
    WDFDRIVER Driver,
    PWDFDEVICE_INIT DeviceInitPtr
    )
{
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    WDF_OBJECT_ATTRIBUTES deviceAttributes;
    DEVICE_CONTEXT* deviceContextPtr;
    WDFDEVICE device;
    NTSTATUS status;
    WDF_IO_TYPE_CONFIG ioConfig;
    DECLARE_CONST_UNICODE_STRING(vchiqSymbolicLink, VCHIQ_SYMBOLIC_NAME);

    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();

    {
        WDF_FILEOBJECT_CONFIG fileobjectConfig;
        WDF_FILEOBJECT_CONFIG_INIT(
            &fileobjectConfig,
            WDF_NO_EVENT_CALLBACK,
            VchiqFileClose,
            WDF_NO_EVENT_CALLBACK);

        fileobjectConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext;

        WdfDeviceInitSetFileObjectConfig(
            DeviceInitPtr,
            &fileobjectConfig,
            WDF_NO_OBJECT_ATTRIBUTES);
    }

    WDF_IO_TYPE_CONFIG_INIT(&ioConfig);
    ioConfig.ReadWriteIoType = WdfDeviceIoDirect;
    ioConfig.DeviceControlIoType = WdfDeviceIoDirect;
    ioConfig.DirectTransferThreshold = 0;

    WdfDeviceInitSetIoTypeEx(DeviceInitPtr, &ioConfig);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
    pnpPowerCallbacks.EvtDevicePrepareHardware = 
        VchiqPrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware =
        VchiqReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = 
        VchiqInitOperation;
    WdfDeviceInitSetPnpPowerEventCallbacks(
        DeviceInitPtr, 
        &pnpPowerCallbacks);

    WdfDeviceInitSetIoInCallerContextCallback(
        DeviceInitPtr,
        VchiqInCallerContext);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
        &deviceAttributes, 
        DEVICE_CONTEXT);

    status = WdfDeviceCreate(
        &DeviceInitPtr,
        &deviceAttributes,
        &device);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "WdfDeviceCreate fail %!STATUS!", status);
        goto End;
    }

    {
        WDF_OBJECT_ATTRIBUTES attributes;
        WDF_IO_QUEUE_CONFIG queueConfig;
        WDFQUEUE queue;

        deviceContextPtr = VchiqGetDeviceContext(device);
        deviceContextPtr->Device = device;
        deviceContextPtr->VersionMajor = VCHIQ_VERSION_MAJOR;
        deviceContextPtr->VersionMinor = VCHIQ_VERSION_MINOR;

        deviceContextPtr->PhyDeviceObjectPtr =
            WdfDeviceWdmGetPhysicalDevice(device);

        WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
            &queueConfig,
            WdfIoQueueDispatchParallel);
        queueConfig.EvtIoDeviceControl = VchiqIoDeviceControl;
        queueConfig.EvtIoStop = VchiqIoStop;

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ExecutionLevel = WdfExecutionLevelPassive;

        status = WdfIoQueueCreate(
            device,
            &queueConfig,
            &attributes,
            &queue);
        if (!NT_SUCCESS(status)) {
            VCHIQ_LOG_ERROR(
                "WdfIoQueueCreate fail %!STATUS!", status);
            goto End;
        }
    }

    // Create symbolic and device interface
    status = WdfDeviceCreateSymbolicLink(
        device,
        &vchiqSymbolicLink);
    if (!NT_SUCCESS(status)) {
        VCHIQ_LOG_ERROR(
            "Fail to register symbolic link %!STATUS!",
            status);
        goto End;
    }

End:
    VCHIQ_LOG_INFORMATION("Exit Status %!STATUS!", status);

    return status;
}
Example #3
0
NTSTATUS
NonPnpDeviceAdd(
    IN WDFDRIVER Driver,
    IN PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Called by the DriverEntry to create a control-device. This call is
    responsible for freeing the memory for DeviceInit.

Arguments:

    DriverObject - a pointer to the object that represents this device
    driver.

    DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure.

Return Value:

    STATUS_SUCCESS if initialized; an error otherwise.

--*/
{
    NTSTATUS                       status;
    WDF_OBJECT_ATTRIBUTES           attributes;
    WDF_IO_QUEUE_CONFIG      ioQueueConfig;
    WDF_FILEOBJECT_CONFIG fileConfig;
    WDFQUEUE                            queue;
    WDFDEVICE   controlDevice;
    DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ;
    DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ;

    UNREFERENCED_PARAMETER( Driver );

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
                   "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit);
    //
    // Set exclusive to TRUE so that no more than one app can talk to the
    // control device at any time.
    //
    WdfDeviceInitSetExclusive(DeviceInit, TRUE);

    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);


    status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName);

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status);
        goto End;
    }

    WdfControlDeviceInitSetShutdownNotification(DeviceInit,
                                                NonPnpShutdown,
                                                WdfDeviceShutdown);

    //
    // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
    // framework whether you are interested in handling Create, Close and
    // Cleanup requests that gets generated when an application or another
    // kernel component opens an handle to the device. If you don't register
    // the framework default behaviour would be to 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,
                        NonPnpEvtDeviceFileCreate,
                        NonPnpEvtFileClose,
                        WDF_NO_EVENT_CALLBACK // not interested in Cleanup
                        );

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                                       &fileConfig,
                                       WDF_NO_OBJECT_ATTRIBUTES);

    //
    // In order to support METHOD_NEITHER Device controls, or
    // NEITHER device I/O type, we need to register for the
    // EvtDeviceIoInProcessContext callback so that we can handle the request
    // in the calling threads context.
    //
    WdfDeviceInitSetIoInCallerContextCallback(DeviceInit,
                                    NonPnpEvtDeviceIoInCallerContext);

    //
    // Specify the size of device context
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
                                    CONTROL_DEVICE_EXTENSION);

    status = WdfDeviceCreate(&DeviceInit,
                             &attributes,
                             &controlDevice);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status);
        goto End;
    }

    //
    // Create a symbolic link for the control object so that usermode can open
    // the device.
    //


    status = WdfDeviceCreateSymbolicLink(controlDevice,
                                &symbolicLinkName);

    if (!NT_SUCCESS(status)) {
        //
        // Control device will be deleted automatically by the framework.
        //
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status);
        goto End;
    }

    //
    // Configure a default queue so that requests that are not
    // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
    // other queues get dispatched here.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                    WdfIoQueueDispatchSequential);

    ioQueueConfig.EvtIoRead = FileEvtIoRead;
    ioQueueConfig.EvtIoWrite = FileEvtIoWrite;
    ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl;

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    //
    // Since we are using Zw function set execution level to passive so that
    // framework ensures that our Io callbacks called at only passive-level
    // even if the request came in at DISPATCH_LEVEL from another driver.
    //
    //attributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // 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 or 
    // forward them to other drivers. This driver completes the requests 
    // directly in the queue's handlers. 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(controlDevice,
                              &ioQueueConfig,
                              &attributes,
                              &queue // pointer to default queue
                              );
    __analysis_assume(ioQueueConfig.EvtIoStop == 0);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status);
        goto End;
    }

    //
    // Control devices must notify WDF when they are done initializing.   I/O is
    // rejected until this call is made.
    //
    WdfControlFinishInitializing(controlDevice);

End:
    //
    // If the device is created successfully, framework would clear the
    // DeviceInit value. Otherwise device create must have failed so we
    // should free the memory ourself.
    //
    if (DeviceInit != NULL) {
        WdfDeviceInitFree(DeviceInit);
    }

    return status;

}