NTSTATUS
Acpi_EnumChildren (
    _In_ PACPI_CONTEXT AcpiCtx,
    _Out_ WDFMEMORY* EnumChildrenOutput
    )
{
    NTSTATUS status;
    WDFDEVICE device;
    WDFMEMORY inputMem;
    PACPI_ENUM_CHILDREN_INPUT_BUFFER inputBuf;
    size_t inputBufSize;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    WDFMEMORY outputMem;
    PACPI_ENUM_CHILDREN_OUTPUT_BUFFER outputBuf;
    size_t outputBufSize;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    WDF_OBJECT_ATTRIBUTES attributes;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    inputMem = WDF_NO_HANDLE;
    outputMem = WDF_NO_HANDLE;

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

    inputBufSize = sizeof(*inputBuf);
    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             inputBufSize,
                             &inputMem,
                             (PVOID*) &inputBuf);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate for %Iu bytes failed", device, inputBufSize);
        goto Exit;
    }

    RtlZeroMemory(inputBuf, inputBufSize);
    inputBuf->Signature = ACPI_ENUM_CHILDREN_INPUT_BUFFER_SIGNATURE;
    inputBuf->Flags = ENUM_CHILDREN_IMMEDIATE_ONLY;

    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMem, nullptr);

    outputBufSize = sizeof(*outputBuf);

    do
    {
        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        attributes.ParentObject = device;

        status = WdfMemoryCreate(&attributes,
                                 NonPagedPoolNx,
                                 0,
                                 outputBufSize,
                                 &outputMem,
                                 (PVOID*) &outputBuf);
        if (!NT_SUCCESS(status))
        {
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate for %Iu bytes failed", device, outputBufSize);
            goto Exit;
        }

        WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMem, nullptr);

        status = WdfIoTargetSendIoctlSynchronously(WdfDeviceGetIoTarget(device),
                                                   NULL,
                                                   IOCTL_ACPI_ENUM_CHILDREN,
                                                   &inputMemDesc,
                                                   &outputMemDesc,
                                                   nullptr,
                                                   nullptr);

        if (NT_SUCCESS(status))
        {
            if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE)
            {
                status = STATUS_ACPI_INVALID_DATA;
                TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
                goto Exit;
            }

            //
            // There must be atleast one, because this device is included in the list.
            //

            if (outputBuf->NumberOfChildren < 1)
            {
                status = STATUS_ACPI_INVALID_DATA;
                TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] No child devices in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
                goto Exit;
            }

            break;
        }

        if (status != STATUS_BUFFER_OVERFLOW)
        {
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] IOCTL_ACPI_ENUM_CHILDREN failed - %!STATUS!", device, status);
            goto Exit;
        }

        if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE)
        {
            status = STATUS_ACPI_INVALID_DATA;
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
            goto Exit;
        }

        outputBufSize = outputBuf->NumberOfChildren;
        WdfObjectDelete(outputMem);
        outputMem = WDF_NO_HANDLE;

#pragma warning(suppress:4127)
    } while (true);

    *EnumChildrenOutput = outputMem;

Exit:

    if (inputMem != WDF_NO_HANDLE)
    {
        WdfObjectDelete(inputMem);
    }

    if (!NT_SUCCESS(status) && (outputMem != WDF_NO_HANDLE))
    {
        WdfObjectDelete(outputMem);
    }

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
// Pass down Idle notification request to lower driver
//
NTSTATUS HidFx2SendIdleNotification(_In_ WDFREQUEST hRequest)
{
    NTSTATUS                   status = STATUS_SUCCESS;
    WDF_REQUEST_SEND_OPTIONS   options;
    WDFIOTARGET                hNextLowerDriver;
    WDFDEVICE                  hDevice;
    PIO_STACK_LOCATION         pCurrentIrpStack = NULL;
    IO_STACK_LOCATION          nextIrpStack;

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n");

    hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest));
    pCurrentIrpStack = IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(hRequest));

    // Convert the request to corresponding USB Idle notification request
    if (pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO))
    {
        ASSERT(sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO));
        #pragma warning(suppress :4127)  // conditional expression is constant warning
        if (sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO))
        {
            // prepare next stack location
            RtlZeroMemory(&nextIrpStack, sizeof(IO_STACK_LOCATION));
            nextIrpStack.MajorFunction = pCurrentIrpStack->MajorFunction;
            nextIrpStack.Parameters.DeviceIoControl.InputBufferLength = pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength;
            nextIrpStack.Parameters.DeviceIoControl.Type3InputBuffer = pCurrentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
            nextIrpStack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
            nextIrpStack.DeviceObject = WdfIoTargetWdmGetTargetDeviceObject(WdfDeviceGetIoTarget(hDevice));

            // Format the I/O request for the driver's local I/O target by using the contents of the specified WDM I/O stack location structure.
            WdfRequestWdmFormatUsingStackLocation(hRequest, &nextIrpStack);

            // Send the request down using Fire and forget option.
            WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);
            hNextLowerDriver = WdfDeviceGetIoTarget(hDevice);
            if (WdfRequestSend(hRequest, hNextLowerDriver, &options) == FALSE)
            {
                status = STATUS_UNSUCCESSFUL;
            }
        }
        else // Incorrect DeviceIoControl.InputBufferLength
        {
            status = STATUS_INFO_LENGTH_MISMATCH;
            TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect DeviceIoControl.InputBufferLength, %!STATUS!\n", status);
            return status;
        }
    }
    else // DeviceIoControl.InputBufferLength too small
    {
        status = STATUS_BUFFER_TOO_SMALL;
        TraceErr(DBG_IOCTL, "(%!FUNC!) DeviceIoControl.InputBufferLength too small, %!STATUS!\n", status);
        return status;
    }

    TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status);
    return status;
}
NDIS_STATUS
VenetGetInterface(NDIS_HANDLE handle, PADAPTER a)
{
    WDF_OBJECT_ATTRIBUTES	attr;
    int			rc;
    NTSTATUS		nrc;

    /* Get my interface from Vbus... */
    NdisMGetDeviceProperty(handle, &a->pdo, &a->fdo, &a->next, NULL, NULL);
    WDF_OBJECT_ATTRIBUTES_INIT(&attr);
    nrc = WdfDeviceMiniportCreate(WdfGetDriver(), &attr, a->fdo,
                                  a->next, a->pdo, &a->wdf_device);
    if (!NT_SUCCESS(nrc))
        return NDIS_STATUS_FAILURE;


    nrc = WdfIoTargetQueryForInterface(WdfDeviceGetIoTarget(a->wdf_device),
                                       &VBUS_INTERFACE_GUID, (PINTERFACE) &a->vif,
                                       VBUS_IF_SIZE, VBUS_IF_VERSION, NULL);
    if (!NT_SUCCESS(nrc))
        return NDIS_STATUS_FAILURE;

    rc = a->vif.open(a->pdo, VENET_VERSION, &a->bus_handle,
                     VenetEventHandler);
    if (rc)
        return NDIS_STATUS_FAILURE;

    return NDIS_STATUS_SUCCESS;
}
Beispiel #4
0
void MouseTrapEvtIoInternalDeviceControl(WDFQUEUE queue, WDFREQUEST request, size_t outputBufferLength, size_t inputBufferLength, ULONG ioControlCode) {
	UNREFERENCED_PARAMETER(outputBufferLength);
	UNREFERENCED_PARAMETER(inputBufferLength);

	NTSTATUS status = STATUS_SUCCESS;

	PAGED_CODE(); // Ensure paging is allowed in current IRQL

	// Get extension data
	WDFDEVICE hDevice = WdfIoQueueGetDevice(queue);
	PDEVICE_CONTEXT context = DeviceGetContext(hDevice);

	if(ioControlCode == IOCTL_INTERNAL_MOUSE_CONNECT) {
		// Only allow one connection.
		if(context->UpperConnectData.ClassService == NULL) {
			// Copy the connection parameters to the device extension.
			PCONNECT_DATA connectData;
			size_t length;
			status = WdfRequestRetrieveInputBuffer(request, sizeof(CONNECT_DATA), &connectData, &length);
			if(NT_SUCCESS(status)) {
				// Hook into the report chain (I am not sure this is correct)
				context->UpperConnectData = *connectData;
				connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice);

				#pragma warning(push)
				#pragma warning(disable:4152)
				connectData->ClassService = MouseTrapServiceCallback;
				#pragma warning(pop)
			}
			else {
				DebugPrint(("[MouseTrap] WdfRequestRetrieveInputBuffer failed %x\n", status));
			}
		}
		else {
			status = STATUS_SHARING_VIOLATION;
		}
	}
	else if(ioControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT) {
		status = STATUS_NOT_IMPLEMENTED;
	}

	// Complete on error
	if(!NT_SUCCESS(status)) {
		WdfRequestComplete(request, status);
		return;
	}

	// Dispatch to higher level driver
	WDF_REQUEST_SEND_OPTIONS options;
	WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

	if(WdfRequestSend(request, WdfDeviceGetIoTarget(hDevice), &options) == FALSE) {
		NTSTATUS status = WdfRequestGetStatus(request);
		DebugPrint(("[MouseTrap] WdfRequestSend failed: 0x%x\n", status));
		WdfRequestComplete(request, status);
	}
}
Beispiel #5
0
NTSTATUS
BthEchoSharedDeviceContextHeaderInit(
    PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER Header,
    WDFDEVICE Device
)
/*++

Description:

    Initializes the common context header between server and client

Arguments:

    Header - Contex header
    Device - Framework device object

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;

    Header->Device = Device;

    Header->IoTarget = WdfDeviceGetIoTarget(Device);

    //
    // Initialize request object
    //

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = Device;

    status = WdfRequestCreate(
                 &attributes,
                 Header->IoTarget,
                 &Header->Request
             );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "Failed to pre-allocate request in device context, Status code %!STATUS!\n", status);

        goto exit;
    }

exit:
    return status;
}
VOID
SimSensorIoInternalDeviceControl (
    WDFQUEUE Queue,
    WDFREQUEST Request,
    size_t OutputBufferLength,
    size_t InputBufferLength,
    ULONG IoControlCode)

/*++

Description:

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

--*/

{
    WDF_REQUEST_SEND_OPTIONS RequestSendOptions;
    BOOLEAN Return;
    NTSTATUS Status;

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);
    UNREFERENCED_PARAMETER(IoControlCode);

    DebugEnter();

    WdfRequestFormatRequestUsingCurrentType(Request);

    WDF_REQUEST_SEND_OPTIONS_INIT(
        &RequestSendOptions,
        WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

    Return = WdfRequestSend(
                Request,
                WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)),
                &RequestSendOptions);

    if (Return == FALSE) {
        Status = WdfRequestGetStatus(Request);
        DebugPrint(SIMSENSOR_WARN,
                   "WdfRequestSend() Failed. Request Status=0x%x\n",
                   Status);

        WdfRequestComplete(Request, Status);
    }

    DebugExit();
}
Beispiel #7
0
///////////////////////////////////////////////////////////////////////////////
// SmplFilterEvtIoDefault
///////////////////////////////////////////////////////////////////////////////
VOID SmplFilterEvtIoDefault(
  __in  WDFQUEUE Queue,
  __in  WDFREQUEST Request
)
{
    WDF_REQUEST_PARAMETERS RequestParameters;
    BOOLEAN bResult;

    WDF_REQUEST_PARAMETERS_INIT(&RequestParameters);
    WdfRequestGetParameters(Request, &RequestParameters);
    if(WdfRequestTypeRead == RequestParameters.Type)
    {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault WdfRequestTypeRead\n");
        WdfRequestFormatRequestUsingCurrentType(Request);
        WdfRequestSetCompletionRoutine(Request, SmplFilterCompletionRoutineRead, NULL);
        bResult = WdfRequestSend(Request,
                                WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)),
                                NULL);
    }
    else
    {
        WDF_REQUEST_SEND_OPTIONS Options;
        WDF_REQUEST_SEND_OPTIONS_INIT(&Options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault other Request type\n");

        bResult = WdfRequestSend(Request,
                                WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)),
                                &Options);
    }

    if(FALSE == bResult)
    {
        DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestSend failed!\n");
        WdfRequestComplete(Request, WdfRequestGetStatus(Request));
    }
} // end SmplFilterEvtIoDefault
VOID
ForwardRequestToIoTarget(
    _In_ WDFQUEUE   queue,
    _In_ WDFREQUEST request,
    _In_ size_t     length)
{
    TraceEntry();
    Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! - Queue 0x%p, Request 0x%p Length %Iu", queue, request, length);

    auto device = WdfIoQueueGetDevice(queue);
    auto context = GetDeviceContext(device);

    if (length > context->MaxLengthInBytesForRWTransfers) {
        TraceError("%!FUNC! - Buffer Length to big %Iu, Max is %Iu. Status - %!STATUS!",
            length, context->MaxLengthInBytesForRWTransfers, STATUS_BUFFER_OVERFLOW);

        WdfRequestCompleteWithInformation(request, STATUS_BUFFER_OVERFLOW, NULL);
        return;
    }

    auto targetDevice = WdfDeviceGetIoTarget(device);

    WdfRequestFormatRequestUsingCurrentType(request);

    WDF_REQUEST_SEND_OPTIONS options;

    WDF_REQUEST_SEND_OPTIONS_INIT(
        &options,
        WDF_REQUEST_SEND_OPTION_SYNCHRONOUS | WDF_REQUEST_SEND_OPTION_TIMEOUT);

    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_ABS_TIMEOUT_IN_SEC(10));

    auto sendSuccess = WdfRequestSend(request, targetDevice, &options);
    auto status = WdfRequestGetStatus(request);
    if (!sendSuccess || !NT_SUCCESS(status))
    {
        TraceError("%!FUNC! - WdfRequestSend returned %d with status: %!STATUS!", sendSuccess, status);
        WdfRequestCompleteWithInformation(request, status, NULL);
        return;
    }

    WdfRequestComplete(request, status);
}
Beispiel #9
0
VOID
FilterEvtIoDeviceControl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
/*++

Routine Description:

    This routine is the dispatch routine for internal device control requests.
    
Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.

Return Value:

   VOID

--*/
{
    PFILTER_EXTENSION               filterExt;
    NTSTATUS                        status = STATUS_SUCCESS;
    WDFDEVICE                       device;

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    KdPrint(("Entered FilterEvtIoDeviceControl\n"));

    device = WdfIoQueueGetDevice(Queue);

    filterExt = FilterGetData(device);

    switch (IoControlCode) {

    //
    // Put your cases for handling IOCTLs here
    //
    
    default:
        status = STATUS_SUCCESS;
    }
    
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Forward the request down. WdfDeviceGetIoTarget returns
    // the default target, which represents the device attached to us below in
    // the stack.
    //
#if FORWARD_REQUEST_WITH_COMPLETION
    //
    // Use this routine to forward a request if you are interested in post
    // processing the IRP.
    //
        FilterForwardRequestWithCompletionRoutine(Request, 
                                               WdfDeviceGetIoTarget(device));
#else   
        FilterForwardRequest(Request, WdfDeviceGetIoTarget(device));
#endif

    return;
}
Beispiel #10
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
Beispiel #11
0
///////////////////////////////////////////////////////////////////////////////
//
//  CDFilterEvtDeviceAdd
//
//    This routine is called by the framework when a device of
//    the type we filter is found in the system.
//
//  INPUTS:
//
//      DriverObject - Our WDFDRIVER object
//
//      DeviceInit   - The device iniitalization structure we'll
//                     be using to create our WDFDEVICE
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      STATUS_SUCCESS, otherwise an error indicating why the driver could not
//                      load.
//
//  IRQL:
//
//      This routine is called at IRQL == PASSIVE_LEVEL.
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
CDFilterEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{

    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES wdfObjectAttr;
    WDFDEVICE wdfDevice;
    PFILTER_DEVICE_CONTEXT devContext;
    WDF_IO_QUEUE_CONFIG ioQueueConfig;

#if DBG
    DbgPrint("CDFilterEvtDeviceAdd: Adding device...\n");
#endif

   UNREFERENCED_PARAMETER(Driver);

    //
    // Indicate that we're creating a FILTER device.  This will cause
    // KMDF to attach us correctly to the device stack and auto-forward
    // any requests we don't explicitly handle.
    //
    WdfFdoInitSetFilter(DeviceInit);


    //
    // Setup our device attributes to have our context type
    //
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&wdfObjectAttr, 
                                            FILTER_DEVICE_CONTEXT);


    //
    // And create our WDF device. This does a multitude of things,
    //  including:
    //
    //  1) Creating a WDM device object
    //  2) Attaching the device object to the filtered device object
    //  3) Propogates all of the flags and characteristics of the 
    //     target device to our filter device. So, for example, if 
    //     the target device is setup for direct I/O our filter 
    //     device will also be setup for direct I/O
    //
    status = WdfDeviceCreate(&DeviceInit, 
                             &wdfObjectAttr, 
                             &wdfDevice);

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

    //
    // Get our filter context
    //
    devContext = CDFilterGetDeviceContext(wdfDevice);

   //
    // Get our local (aka "in-stack") I/O Target. This is the device
    // to which we'll be forwarding requests that we intercept (and
    // hence aren't automagically forwarded).
    //
    devContext->TargetToSendRequestsTo = WdfDeviceGetIoTarget(wdfDevice);

    //
    // Now that that's over with, we can create our default queue.
    //  This queue will allow us to pick off any I/O requests
    //  that we may be interested in before they are forwarded
    //  to the target device.
    //
    WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
                                           WdfIoQueueDispatchParallel);

    //
    // For this exercise we'll intercept READ requests
    //
    ioQueueConfig.EvtIoRead = CDFilterEvtRead;

    //
    // Create the queue...
    //
    status = WdfIoQueueCreate(wdfDevice,
                              &ioQueueConfig,
                              WDF_NO_OBJECT_ATTRIBUTES,
                              NULL);

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

   //
    // Success!
    //
    return STATUS_SUCCESS;
}
Beispiel #12
0
VOID
Rio500_EvtIoDeviceControl(
  _In_ WDFQUEUE   Queue,
  _In_ WDFREQUEST Request,
  _In_ size_t     OutputBufferLength,
  _In_ size_t     InputBufferLength,
  _In_ ULONG      IoControlCode
)
/*++

Routine Description:

    This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
    requests from the system.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.
Return Value:

    VOID

--*/
{
  WDFDEVICE             device;
  PVOID                 ioBuffer;
  PRIO_IOCTL_BLOCK      ioBufferRio;
  size_t                bufLength;
  NTSTATUS              status;
  PDEVICE_CONTEXT       pDevContext;
  ULONG                 length = 0;
  URB                   urb;
  PMDL                  pMdl = NULL;
  WDF_MEMORY_DESCRIPTOR memoryDesc;
#ifdef _WIN64
  BOOLEAN               isWowRequest = FALSE;
#endif // _WIN64

  UNREFERENCED_PARAMETER(OutputBufferLength);
  UNREFERENCED_PARAMETER(InputBufferLength);

  Rio500_DbgPrint(3, ("Entered Rio500_DispatchDevCtrl\n"));

  PAGED_CODE();

  //
  // initialize variables
  //
  device = WdfIoQueueGetDevice(Queue);
  pDevContext = GetDeviceContext(device);

  switch(IoControlCode) {
    case IOCTL_RIO500_RESET_PIPE:
      status = ResetPipe(pDevContext->ReadPipe);
      if (NT_SUCCESS(status)) {
        status = ResetPipe(pDevContext->WritePipe);
      }
      break;

    case IOCTL_RIO500_GET_CONFIG_DESCRIPTOR:
      if (pDevContext->UsbConfigurationDescriptor) {
        length = pDevContext->UsbConfigurationDescriptor->wTotalLength;

        status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength);
        if (!NT_SUCCESS(status)) {
          Rio500_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
          break;
        }

        RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length);
        status = STATUS_SUCCESS;
      } else {
        status = STATUS_INVALID_DEVICE_STATE;
      }
      break;

    case IOCTL_RIO500_RESET_DEVICE:
      status = ResetDevice(device);
      break;

    case IOCTL_RIO500_RIO_COMMAND:
#ifdef _WIN64
      if (IoIs32bitProcess(NULL)) {
        bufLength = sizeof(RIO_IOCTL_BLOCK) - sizeof(DWORD32);
        isWowRequest = TRUE;
      } else
#endif // _WIN64
      {
        bufLength = sizeof(RIO_IOCTL_BLOCK);
      }
      status = WdfRequestRetrieveInputBuffer(
        Request,
        bufLength,
        &ioBufferRio,
        NULL
      );

      if (NT_SUCCESS(status)) {
#ifdef _WIN64
        if (isWowRequest) {
          ioBuffer = (PVOID)ioBufferRio->MsgData.DataWow;
        } else
#endif // _WIN64
        {
          ioBuffer = ioBufferRio->MsgData.Data;
        }
        if (ioBufferRio->MsgLength != 0 && ioBuffer != NULL) {
          pMdl = IoAllocateMdl(
            ioBuffer,
            ioBufferRio->MsgLength,
            FALSE,
            FALSE,
            NULL
          );
          MmProbeAndLockPages(pMdl, (KPROCESSOR_MODE)KernelMode, IoModifyAccess);
        }

        memset(&urb, 0, sizeof(urb));
        urb.UrbControlVendorClassRequest.Hdr.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
        urb.UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;
        urb.UrbControlVendorClassRequest.TransferBuffer = NULL;
        urb.UrbControlVendorClassRequest.RequestTypeReservedBits = 0x00;
        urb.UrbControlVendorClassRequest.TransferBufferLength = ioBufferRio->MsgLength;
        urb.UrbControlVendorClassRequest.TransferBufferMDL = pMdl;
        urb.UrbControlVendorClassRequest.Request = ioBufferRio->RequestCode;
        urb.UrbControlVendorClassRequest.Value = ioBufferRio->MsgValue;
        urb.UrbControlVendorClassRequest.Index = ioBufferRio->MsgIndex;
        urb.UrbControlVendorClassRequest.TransferFlags = USBD_SHORT_TRANSFER_OK;
        if (ioBufferRio->RequestType & 0x80) {
          urb.UrbControlVendorClassRequest.TransferFlags |= USBD_TRANSFER_DIRECTION_IN;
        }
        urb.UrbControlVendorClassRequest.UrbLink = NULL;
      
        WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDesc, &urb, sizeof(urb));
        status = WdfIoTargetSendInternalIoctlOthersSynchronously(
          WdfDeviceGetIoTarget(device),
          Request,
          IOCTL_INTERNAL_USB_SUBMIT_URB,
          &memoryDesc,
          NULL,
          NULL,
          NULL,
          NULL
        );

        if (pMdl != NULL) {
          MmUnlockPages(pMdl);
          IoFreeMdl(pMdl);
        }
      }
      break;

    default:
      status = STATUS_INVALID_DEVICE_REQUEST;
      break;
  }

  WdfRequestCompleteWithInformation(Request, status, length);

  Rio500_DbgPrint(3, ("Exit Rio500_DispatchDevCtrl\n"));
}
static NTSTATUS
XenVbd_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init) {
  PXENVBD_FILTER_DATA xvfd;
  NTSTATUS status;
  WDFDEVICE device;
  WDF_OBJECT_ATTRIBUTES device_attributes;
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_DPC_CONFIG dpc_config;
  WDF_OBJECT_ATTRIBUTES oa;
  UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
  UCHAR power_minor_functions[] = { IRP_MN_SET_POWER };
  
  UNREFERENCED_PARAMETER(driver);

  FUNCTION_ENTER();

  WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);

  WdfFdoInitSetFilter(device_init);

  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDeviceD0Entry = XenVbd_EvtDeviceD0Entry;
  pnp_power_callbacks.EvtDeviceD0Exit = XenVbd_EvtDeviceD0Exit;
  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE,
    IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  if (!NT_SUCCESS(status)) {
    return status;
  }

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER,
    IRP_MJ_POWER, power_minor_functions, ARRAY_SIZE(power_minor_functions));
  if (!NT_SUCCESS(status)) {
    return status;
  }

  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENVBD_FILTER_DATA);
  status = WdfDeviceCreate(&device_init, &device_attributes, &device);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("Error creating device 0x%x\n", status);
    return status;
  }

  xvfd = GetXvfd(device);
  xvfd->wdf_device = device;
  xvfd->wdf_target = WdfDeviceGetIoTarget(device);
  xvfd->xvdd.xvfd = xvfd;
  xvfd->xvdd.pdo = WdfDeviceWdmGetPhysicalDevice(device);
  xvfd->xvdd.grant_tag = XENVBD_POOL_TAG;

  KeInitializeEvent(&xvfd->xvdd.backend_event, SynchronizationEvent, FALSE);

  WDF_DPC_CONFIG_INIT(&dpc_config, XenVbd_EvtDpcEvent);
  WDF_OBJECT_ATTRIBUTES_INIT(&oa);
  oa.ParentObject = device;
  status = WdfDpcCreate(&dpc_config, &oa, &xvfd->dpc);

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

  FUNCTION_EXIT();
  return status;
}
VOID
SimSensorIoDeviceControl(
    WDFQUEUE   Queue,
    WDFREQUEST Request,
    size_t     OutputBufferLength,
    size_t     InputBufferLength,
    ULONG      IoControlCode
    )

/*++

Routine Description:

    Handles requests to read or write the simulated device state.

Arguments:

    Queue - Supplies a handle to the framework queue object that is associated
        with the I/O request.

    Request - Supplies a handle to a framework request object. This one
        represents the IRP_MJ_DEVICE_CONTROL IRP received by the framework.

    OutputBufferLength - Supplies the length, in bytes, of the request's output
        buffer, if an output buffer is available.

    InputBufferLength - Supplies the length, in bytes, of the request's input
        buffer, if an input buffer is available.

    IoControlCode - Supplies the Driver-defined or system-defined I/O control
        code (IOCtl) that is associated with the request.

Return Value:

   VOID

--*/

{
    ULONG BytesReturned;
    WDFDEVICE Device;
    BOOLEAN Result;
    WDF_REQUEST_SEND_OPTIONS RequestSendOptions;
    NTSTATUS Status;

    UNREFERENCED_PARAMETER(InputBufferLength);
    UNREFERENCED_PARAMETER(OutputBufferLength);

    PAGED_CODE();

    Device = WdfIoQueueGetDevice(Queue);
    DebugPrint(SIMSENSOR_NOTE, "SimSensorIoDeviceControl: 0x%p\n", Device);
    BytesReturned = 0;
    switch(IoControlCode) {
    case IOCTL_THERMAL_READ_TEMPERATURE:

        //
        // This call will either complete the request or put it in the pending
        // queue.
        //

        SimSensorAddReadRequest(Device, Request);
        break;
    default:

        //
        // Unrecognized IOCtls must be forwarded down the stack.
        //

        WDF_REQUEST_SEND_OPTIONS_INIT(
            &RequestSendOptions,
            WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

        WdfRequestFormatRequestUsingCurrentType(Request);

        Result = WdfRequestSend(
                    Request,
                    WdfDeviceGetIoTarget(Device),
                    &RequestSendOptions);

        if (Result == FALSE) {
            Status = WdfRequestGetStatus(Request);
            DebugPrint(SIMSENSOR_WARN,
                       "WdfRequestSend() Failed. Request Status = 0x%x\n",
                       Status);

            WdfRequestComplete(Request, Status);
        }
        break;
    }
}
Beispiel #15
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
NTSTATUS
Acpi_EvaluateUcsiDsm (
    _In_ PACPI_CONTEXT AcpiCtx,
    _In_ ULONG FunctionIndex,
    _Outptr_opt_ PACPI_EVAL_OUTPUT_BUFFER* Output
    )
/*++

    N.B. Caller is expected to free the Output buffer.

--*/
{
    NTSTATUS status;
    WDFDEVICE device;
    WDFMEMORY inputMemory;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
    size_t inputBufferSize;
    size_t inputArgumentBufferSize;
    PACPI_METHOD_ARGUMENT argument;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    size_t outputBufferSize;
    size_t outputArgumentBufferSize;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_REQUEST_SEND_OPTIONS sendOptions;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    inputMemory = WDF_NO_HANDLE;
    outputBuffer = nullptr;

    inputArgumentBufferSize =
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(GUID)) +
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) +
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) +
        ACPI_METHOD_ARGUMENT_LENGTH(0);

    inputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX, Argument) +
        inputArgumentBufferSize;

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

    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             inputBufferSize,
                             &inputMemory,
                             (PVOID*) &inputBuffer);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate failed for %Iu bytes - %!STATUS!", device, inputBufferSize, status);
        goto Exit;
    }

    RtlZeroMemory(inputBuffer, inputBufferSize);

    inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
    inputBuffer->Size = (ULONG) inputArgumentBufferSize;
    inputBuffer->ArgumentCount = 4;
    inputBuffer->MethodNameAsUlong = (ULONG) 'MSD_';

    argument = &(inputBuffer->Argument[0]);
    ACPI_METHOD_SET_ARGUMENT_BUFFER(argument,
                                    &GUID_UCSI_DSM,
                                    sizeof(GUID_UCSI_DSM));

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    ACPI_METHOD_SET_ARGUMENT_INTEGER(argument, UCSI_DSM_REVISION);

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    ACPI_METHOD_SET_ARGUMENT_INTEGER(argument, FunctionIndex);

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    argument->Type = ACPI_METHOD_ARGUMENT_PACKAGE_EX;
    argument->DataLength = 0;

    outputArgumentBufferSize = ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG));
    outputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
        outputArgumentBufferSize;

    outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER) ExAllocatePoolWithTag(NonPagedPoolNx,
                                                                    outputBufferSize,
                                                                    TAG_UCSI);

    if (outputBuffer == nullptr)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] ExAllocatePoolWithTag failed for %Iu bytes", device, outputBufferSize);
        goto Exit;
    }

    RtlZeroMemory(outputBuffer, outputBufferSize);

    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMemory, NULL);
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputMemDesc, outputBuffer, (ULONG) outputBufferSize);

    WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions,
                                         WDF_REL_TIMEOUT_IN_MS(UCSI_DSM_EXECUTION_TIMEOUT_IN_MS));

    status = WdfIoTargetSendInternalIoctlSynchronously(
                 WdfDeviceGetIoTarget(device),
                 NULL,
                 IOCTL_ACPI_EVAL_METHOD,
                 &inputMemDesc,
                 &outputMemDesc,
                 &sendOptions,
                 NULL);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] IOCTL_ACPI_EVAL_METHOD for _DSM failed - %!STATUS!", device, status);
        goto Exit;
    }

    if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE)
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] ACPI_EVAL_OUTPUT_BUFFER signature is incorrect", device);
        status = STATUS_ACPI_INVALID_DATA;
        goto Exit;
    }

Exit:

    if (inputMemory != WDF_NO_HANDLE)
    {
        WdfObjectDelete(inputMemory);
    }

    if (!NT_SUCCESS(status) || (Output == nullptr))
    {
        if (outputBuffer)
        {
            ExFreePoolWithTag(outputBuffer, TAG_UCSI);
        }
    }
    else
    {
        *Output = outputBuffer;
    }

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
NTSTATUS
Acpi_EvaluatePld (
    _In_ PACPI_CONTEXT AcpiCtx,
    _In_ LPCSTR DeviceName,
    _Out_ PACPI_PLD_BUFFER PldBuffer
    )
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    ACPI_EVAL_INPUT_BUFFER_EX inputBuffer;
    size_t inputBufferSize;
    WDFMEMORY outputMemory;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    size_t outputBufferSize;
    size_t outputArgumentBufferSize;
    WDF_OBJECT_ATTRIBUTES attributes;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    outputMemory = WDF_NO_HANDLE;

    inputBufferSize = sizeof(inputBuffer);
    RtlZeroMemory(&inputBuffer, inputBufferSize);

    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX;

    status = RtlStringCchPrintfA(inputBuffer.MethodName,
                                 sizeof(inputBuffer.MethodName),
                                 "%s._PLD",
                                 DeviceName);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] RtlStringCchPrintfA for creating method name failed - %!STATUS!", device, status);
        goto Exit;
    }

    outputArgumentBufferSize = 1024;
    outputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
        outputArgumentBufferSize;

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

    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             outputBufferSize,
                             &outputMemory,
                             (PVOID*) &outputBuffer);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate failed for %Iu bytes - %!STATUS!", device, outputBufferSize, status);
        goto Exit;
    }

    RtlZeroMemory(outputBuffer, outputBufferSize);

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG) inputBufferSize);
    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL);

    status = WdfIoTargetSendInternalIoctlSynchronously(
                 WdfDeviceGetIoTarget(device),
                 NULL,
                 IOCTL_ACPI_EVAL_METHOD_EX,
                 &inputMemDesc,
                 &outputMemDesc,
                 NULL,
                 NULL);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] IOCTL_ACPI_EVAL_METHOD_EX for %s failed - %!STATUS!", device, inputBuffer.MethodName, status);
        goto Exit;
    }

    if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE)
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] ACPI_EVAL_OUTPUT_BUFFER signature is incorrect", device);
        goto Exit;
    }

    if (outputBuffer->Count < 1)
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] _PLD for %s didn't return anything", device, inputBuffer.MethodName);
        goto Exit;
    }

    if (outputBuffer->Argument[0].Type != ACPI_METHOD_ARGUMENT_BUFFER)
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] _PLD for %s returned an unexpected argument of type %d", device, inputBuffer.MethodName, outputBuffer->Argument[0].Type);
        goto Exit;
    }

    if (outputBuffer->Argument[0].DataLength < sizeof(*PldBuffer))
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Unexpected _PLD buffer size for %s. Expected %Iu bytes, got %Iu bytes", device, inputBuffer.MethodName, sizeof(*PldBuffer), outputBuffer->Argument[0].DataLength);
        goto Exit;
    }

    *PldBuffer = *((PACPI_PLD_BUFFER) outputBuffer->Argument[0].Data);

Exit:

    if (outputMemory != WDF_NO_HANDLE)
    {
        WdfObjectDelete(outputMemory);
    }

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
Beispiel #18
0
VOID
KbFilter_EvtIoInternalDeviceControl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
    )
/*++

Routine Description:

    This routine is the dispatch routine for internal device control requests.
    There are two specific control codes that are of interest:

    IOCTL_INTERNAL_KEYBOARD_CONNECT:
        Store the old context and function pointer and replace it with our own.
        This makes life much simpler than intercepting IRPs sent by the RIT and
        modifying them on the way back up.

    IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
        Add in the necessary function pointers and context values so that we can
        alter how the ps/2 keyboard is initialized.

    NOTE:  Handling IOCTL_INTERNAL_I8042_HOOK_KEYBOARD is *NOT* necessary if
           all you want to do is filter KEYBOARD_INPUT_DATAs.  You can remove
           the handling code and all related device extension fields and
           functions to conserve space.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.
    Request - Handle to a framework request object.

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.

Return Value:

   VOID

--*/
{
    PDEVICE_EXTENSION               devExt;
    PINTERNAL_I8042_HOOK_KEYBOARD   hookKeyboard = NULL;
    PCONNECT_DATA                   connectData = NULL;
    NTSTATUS                        status = STATUS_SUCCESS;
    size_t                          length;
    WDFDEVICE                       hDevice;
    BOOLEAN                         forwardWithCompletionRoutine = FALSE;
    BOOLEAN                         ret = TRUE;
    WDFCONTEXT                      completionContext = WDF_NO_CONTEXT;
    WDF_REQUEST_SEND_OPTIONS        options;
    WDFMEMORY                       outputMemory;
    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);


    PAGED_CODE();

    DebugPrint(("Entered KbFilter_EvtIoInternalDeviceControl\n"));

    hDevice = WdfIoQueueGetDevice(Queue);
    devExt = FilterGetData(hDevice);

    switch (IoControlCode) {

    //
    // Connect a keyboard class device driver to the port driver.
    //
    case IOCTL_INTERNAL_KEYBOARD_CONNECT:
        //
        // Only allow one connection.
        //
        if (devExt->UpperConnectData.ClassService != NULL) {
            status = STATUS_SHARING_VIOLATION;
            break;
        }

        //
        // Get the input buffer from the request
        // (Parameters.DeviceIoControl.Type3InputBuffer).
        //
        status = WdfRequestRetrieveInputBuffer(Request,
                                    sizeof(CONNECT_DATA),
                                    &connectData,
                                    &length);
        if(!NT_SUCCESS(status)){
            DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
            break;
        }

        NT_ASSERT(length == InputBufferLength);

        devExt->UpperConnectData = *connectData;

        //
        // Hook into the report chain.  Everytime a keyboard packet is reported
        // to the system, KbFilter_ServiceCallback will be called
        //

        connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice);

#pragma warning(disable:4152)  //nonstandard extension, function/data pointer conversion

        connectData->ClassService = KbFilter_ServiceCallback;

#pragma warning(default:4152)

        break;

    //
    // Disconnect a keyboard class device driver from the port driver.
    //
    case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:

        //
        // Clear the connection parameters in the device extension.
        //
        // devExt->UpperConnectData.ClassDeviceObject = NULL;
        // devExt->UpperConnectData.ClassService = NULL;

        status = STATUS_NOT_IMPLEMENTED;
        break;

    //
    // Attach this driver to the initialization and byte processing of the
    // i8042 (ie PS/2) keyboard.  This is only necessary if you want to do PS/2
    // specific functions, otherwise hooking the CONNECT_DATA is sufficient
    //
    case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:

        DebugPrint(("hook keyboard received!\n"));

        //
        // Get the input buffer from the request
        // (Parameters.DeviceIoControl.Type3InputBuffer)
        //
        status = WdfRequestRetrieveInputBuffer(Request,
                            sizeof(INTERNAL_I8042_HOOK_KEYBOARD),
                            &hookKeyboard,
                            &length);
        if(!NT_SUCCESS(status)){
            DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
            break;
        }

        NT_ASSERT(length == InputBufferLength);

        //
        // Enter our own initialization routine and record any Init routine
        // that may be above us.  Repeat for the isr hook
        //
        devExt->UpperContext = hookKeyboard->Context;

        //
        // replace old Context with our own
        //
        hookKeyboard->Context = (PVOID) devExt;

        if (hookKeyboard->InitializationRoutine) {
            devExt->UpperInitializationRoutine =
                hookKeyboard->InitializationRoutine;
        }
        hookKeyboard->InitializationRoutine =
            (PI8042_KEYBOARD_INITIALIZATION_ROUTINE)
            KbFilter_InitializationRoutine;

        if (hookKeyboard->IsrRoutine) {
            devExt->UpperIsrHook = hookKeyboard->IsrRoutine;
        }
        hookKeyboard->IsrRoutine = (PI8042_KEYBOARD_ISR) KbFilter_IsrHook;

        //
        // Store all of the other important stuff
        //
        devExt->IsrWritePort = hookKeyboard->IsrWritePort;
        devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket;
        devExt->CallContext = hookKeyboard->CallContext;

        status = STATUS_SUCCESS;
        break;


    case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
        forwardWithCompletionRoutine = TRUE;
        completionContext = devExt;
        break;
        
    //
    // Might want to capture these in the future.  For now, then pass them down
    // the stack.  These queries must be successful for the RIT to communicate
    // with the keyboard.
    //
    case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
    case IOCTL_KEYBOARD_QUERY_INDICATORS:
    case IOCTL_KEYBOARD_SET_INDICATORS:
    case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
    case IOCTL_KEYBOARD_SET_TYPEMATIC:
        break;
    }

    if (!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Forward the request down. WdfDeviceGetIoTarget returns
    // the default target, which represents the device attached to us below in
    // the stack.
    //

    if (forwardWithCompletionRoutine) {

        //
        // Format the request with the output memory so the completion routine
        // can access the return data in order to cache it into the context area
        //
        
        status = WdfRequestRetrieveOutputMemory(Request, &outputMemory); 

        if (!NT_SUCCESS(status)) {
            DebugPrint(("WdfRequestRetrieveOutputMemory failed: 0x%x\n", status));
            WdfRequestComplete(Request, status);
            return;
        }

        status = WdfIoTargetFormatRequestForInternalIoctl(WdfDeviceGetIoTarget(hDevice),
                                                         Request,
                                                         IoControlCode,
                                                         NULL,
                                                         NULL,
                                                         outputMemory,
                                                         NULL);

        if (!NT_SUCCESS(status)) {
            DebugPrint(("WdfIoTargetFormatRequestForInternalIoctl failed: 0x%x\n", status));
            WdfRequestComplete(Request, status);
            return;
        }
    
        // 
        // Set our completion routine with a context area that we will save
        // the output data into
        //
        WdfRequestSetCompletionRoutine(Request,
                                    KbFilterRequestCompletionRoutine,
                                    completionContext);

        ret = WdfRequestSend(Request,
                             WdfDeviceGetIoTarget(hDevice),
                             WDF_NO_SEND_OPTIONS);

        if (ret == FALSE) {
            status = WdfRequestGetStatus (Request);
            DebugPrint( ("WdfRequestSend failed: 0x%x\n", status));
            WdfRequestComplete(Request, status);
        }

    }
    else
    {

        //
        // We are not interested in post processing the IRP so 
        // fire and forget.
        //
        WDF_REQUEST_SEND_OPTIONS_INIT(&options,
                                      WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

        ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(hDevice), &options);

        if (ret == FALSE) {
            status = WdfRequestGetStatus (Request);
            DebugPrint(("WdfRequestSend failed: 0x%x\n", status));
            WdfRequestComplete(Request, status);
        }
        
    }

    return;
}
Beispiel #19
0
VOID
MouFilter_EvtIoInternalDeviceControl(
    IN WDFQUEUE      Queue,
    IN WDFREQUEST    Request,
    IN size_t        OutputBufferLength,
    IN size_t        InputBufferLength,
    IN ULONG         IoControlCode
)
/*++

Routine Description:

    This routine is the dispatch routine for internal device control requests.
    There are two specific control codes that are of interest:

    IOCTL_INTERNAL_MOUSE_CONNECT:
        Store the old context and function pointer and replace it with our own.
        This makes life much simpler than intercepting IRPs sent by the RIT and
        modifying them on the way back up.

    IOCTL_INTERNAL_I8042_HOOK_MOUSE:
        Add in the necessary function pointers and context values so that we can
        alter how the ps/2 mouse is initialized.

    NOTE:  Handling IOCTL_INTERNAL_I8042_HOOK_MOUSE is *NOT* necessary if
           all you want to do is filter MOUSE_INPUT_DATAs.  You can remove
           the handling code and all related device extension fields and
           functions to conserve space.


--*/
{

    PDEVICE_EXTENSION           devExt;
    PCONNECT_DATA               connectData;
    PINTERNAL_I8042_HOOK_MOUSE  hookMouse;
    NTSTATUS                   status = STATUS_SUCCESS;
    WDFDEVICE                 hDevice;
    size_t                           length;

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    PAGED_CODE();

    hDevice = WdfIoQueueGetDevice(Queue);
    devExt = FilterGetData(hDevice);

    switch (IoControlCode) {

    //
    // Connect a mouse class device driver to the port driver.
    //
    case IOCTL_INTERNAL_MOUSE_CONNECT:
        //
        // Only allow one connection.
        //
        if (devExt->UpperConnectData.ClassService != NULL) {
            status = STATUS_SHARING_VIOLATION;
            break;
        }

        //
        // Copy the connection parameters to the device extension.
        //
        status = WdfRequestRetrieveInputBuffer(Request,
                                               sizeof(CONNECT_DATA),
                                               &connectData,
                                               &length);
        if(!NT_SUCCESS(status)) {
            DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
            break;
        }


        devExt->UpperConnectData = *connectData;

        //
        // Hook into the report chain.  Everytime a mouse packet is reported to
        // the system, MouFilter_ServiceCallback will be called
        //
        connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice);
        connectData->ClassService = MouFilter_ServiceCallback;

        break;

    //
    // Disconnect a mouse class device driver from the port driver.
    //
    case IOCTL_INTERNAL_MOUSE_DISCONNECT:

        //
        // Clear the connection parameters in the device extension.
        //
        // devExt->UpperConnectData.ClassDeviceObject = NULL;
        // devExt->UpperConnectData.ClassService = NULL;

        status = STATUS_NOT_IMPLEMENTED;
        break;

    //
    // Attach this driver to the initialization and byte processing of the
    // i8042 (ie PS/2) mouse.  This is only necessary if you want to do PS/2
    // specific functions, otherwise hooking the CONNECT_DATA is sufficient
    //
    case IOCTL_INTERNAL_I8042_HOOK_MOUSE:

        DebugPrint(("hook mouse received!\n"));

        // Get the input buffer from the request
        // (Parameters.DeviceIoControl.Type3InputBuffer)
        //
        status = WdfRequestRetrieveInputBuffer(Request,
                                               sizeof(INTERNAL_I8042_HOOK_MOUSE),
                                               &hookMouse,
                                               &length);
        if(!NT_SUCCESS(status)) {
            DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status));
            break;
        }

        //
        // Set isr routine and context and record any values from above this driver
        //
        devExt->UpperContext = hookMouse->Context;
        hookMouse->Context = (PVOID) devExt;

        if (hookMouse->IsrRoutine) {
            devExt->UpperIsrHook = hookMouse->IsrRoutine;
        }
        hookMouse->IsrRoutine = (PI8042_MOUSE_ISR) MouFilter_IsrHook;

        //
        // Store all of the other functions we might need in the future
        //
        devExt->IsrWritePort = hookMouse->IsrWritePort;
        devExt->CallContext = hookMouse->CallContext;
        devExt->QueueMousePacket = hookMouse->QueueMousePacket;

        status = STATUS_SUCCESS;
        break;

    //
    // Might want to capture this in the future.  For now, then pass it down
    // the stack.  These queries must be successful for the RIT to communicate
    // with the mouse.
    //
    case IOCTL_MOUSE_QUERY_ATTRIBUTES:
    default:
        break;
    }

    if (!NT_SUCCESS(status)) {
        WdfRequestComplete(Request, status);
        return ;
    }

    MouFilter_DispatchPassThrough(Request,WdfDeviceGetIoTarget(hDevice));
}