Exemple #1
0
NTSTATUS
Bus_EjectDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )

/*++

Routine Description:

    The user application has told us to eject the device from the bus.
    In a real situation the driver gets notified by an interrupt when the
    user presses the Eject button on the device.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/

{
    PPDO_DEVICE_DATA pdoData;
    BOOLEAN          ejectAll;
    WDFDEVICE        hChild;
    NTSTATUS         status = STATUS_INVALID_PARAMETER;

    PAGED_CODE ();

    //
    // Scan the list to find matching PDOs
    //
    ejectAll = (0 == SerialNo) ? TRUE : FALSE;
    hChild = NULL;

    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                                       hChild,
                                       WdfRetrieveAddedChildren)) != NULL) {

        pdoData = PdoGetData(hChild);

        if (ejectAll || SerialNo == pdoData->SerialNo) {

            status = STATUS_SUCCESS;
            WdfPdoRequestEject(hChild);
            if (!ejectAll) {
                break;
            }
        }
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);

    return status;
}
Exemple #2
0
VOID
KbFilter_EvtIoDeviceControlForRawPdo(
    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 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

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    WDFDEVICE parent = WdfIoQueueGetDevice(Queue);
    PRPDO_DEVICE_DATA pdoData;
    WDF_REQUEST_FORWARD_OPTIONS forwardOptions;
        
    pdoData = PdoGetData(parent);

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

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

    //
    // Process the ioctl and complete it when you are done.
    // Since the queue is configured for serial dispatch, you will
    // not receive another ioctl request until you complete this one.
    //

    switch (IoControlCode) {
    case IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES:
        WDF_REQUEST_FORWARD_OPTIONS_INIT(&forwardOptions);
        status = WdfRequestForwardToParentDeviceIoQueue(Request, pdoData->ParentQueue, &forwardOptions);
        if (!NT_SUCCESS(status)) {
            WdfRequestComplete(Request, status);
        }
        break;    
	case IOCTL_KBFILTR_ON:
    case IOCTL_KBFILTR_OFF:
    case IOCTL_KBFILTR_GET_STATE:
	case IOCTL_KBFILTR_GET_CHAR:
        WDF_REQUEST_FORWARD_OPTIONS_INIT(&forwardOptions);
        status = WdfRequestForwardToParentDeviceIoQueue(Request, pdoData->ParentQueue, &forwardOptions);
        if (!NT_SUCCESS(status)) {
            WdfRequestComplete(Request, status);
        }
        break;

    default:
        WdfRequestComplete(Request, status);
        break;
    }

    return;
}
Exemple #3
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;
}
Exemple #4
0
// handles operations that must be performed when an application requests access to a device.
VOID vJoy_EvtDeviceFileCreate(
  __in  WDFDEVICE Device,
  __in  WDFREQUEST Request,
  __in  WDFFILEOBJECT FileObject
)
{
		WDFFILEOBJECT FileObj;
		PCUNICODE_STRING pName;
		UNICODE_STRING TmpUstr;
		NTSTATUS status = STATUS_SUCCESS;
		int  id=0;
		WCHAR RefStr[100];
		PFILEOBJECT_EXTENSION pExtension=NULL;
		PDEVICE_EXTENSION    pDevContext = NULL;
		PRPDO_DEVICE_DATA	pPdoData=NULL;
		size_t len;
		DWORD_PTR ProcessId;

	    PAGED_CODE ();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_EvtDeviceFileCreate\n");


		// Get file object then get its filename
		FileObj = WdfRequestGetFileObject(Request);
		if (!FileObj)
			goto going_out;
		pName = WdfFileObjectGetFileName(FileObj);
		if (!pName)
			goto going_out;

		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: File name=%wZ\n", pName);

		// Extract id from interface number
		status = RtlStringCchLengthW(VJOY_INTERFACE, 100, &len);
		if (!NT_SUCCESS(status))
			goto going_out;
		status = RtlStringCchCopyNW(RefStr, 100, pName->Buffer+len+1,4);	// Copy the numeric part of the string (000)
		if (!NT_SUCCESS(status))
			goto going_out;
		RtlInitUnicodeString(&TmpUstr, RefStr);								// Convert "000" to UNICODE_STRING
		status = RtlUnicodeStringToInteger(&TmpUstr, 10, &id);				// Convert "000" to integer (0)
		if (!NT_SUCCESS(status))
			goto going_out;

		if (id>0)
		{
			// Verify that this interface has a corresponding device
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: ID=%d\n", id);
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;
			if (!pDevContext->positions[id - 1])
				goto going_out;

			// Get the file object context space
			// Test that this interface is not in use
			// and store there the parent (Raw PDO) context
			pExtension = GetFileObjectContext(FileObject);
			if (!pExtension)
				goto going_out;
			pExtension->pParentRawDeviceContext = pPdoData;
			if (pPdoData->UsedInterfacesMask & (1 << (id - 1)))
			{
				WdfRequestComplete(Request, STATUS_ACCESS_DENIED);
				ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
				TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Access Denied)\n", ProcessId);
				return;
			}

			///// This is a successful file creation - Now record the file details

			// vJoy Device ID
			else
				pPdoData->UsedInterfacesMask |= 1 << (id - 1);

			// Put id in file object context space 
			pExtension->id = id; // Update

			// Get the id of the calling process
			ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
			pExtension->CallingProcessId = (DWORD)(ProcessId & 0xFFFFFFFF);
			TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d\n", pExtension->CallingProcessId);

			// Put the file object in the FDO extension
			pDevContext->DeviceFileObject[id - 1] = FileObject;

			// Activate FFB Queues
			FfbActiveSet(TRUE, id, pDevContext);


			WdfRequestComplete(Request, status);
			return;

		} // if (id>0)

		// Case of General purpose and non device-specific Interface
		else // if (id<1)
		{
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): ID=%d\n", id);
#if 0
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;

			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): Completing Request\n");

#endif // 0
			WdfRequestComplete(Request, status);
			return;
		}; // if (id<1)

	going_out:
		ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Invalid Handle)\n", ProcessId);
		WdfRequestComplete(Request, STATUS_INVALID_HANDLE);
}
Exemple #5
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 #6
0
VOID
vJoy_EvtIoDeviceControlForRawPdo(
    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 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

--*/
{
    NTSTATUS status = STATUS_SUCCESS;
    WDFDEVICE parent;
    WDF_REQUEST_FORWARD_OPTIONS forwardOptions;
    PDEVICE_EXTENSION    pDevContext = NULL;
	WDFMEMORY  inMemory, outMemory;
    PVOID  buffer;
    size_t  bufSize;
    WDFDEVICE            hRawDevice = WdfIoQueueGetDevice(Queue);
	PRPDO_DEVICE_DATA pdoData = PdoGetData(hRawDevice);
	WDF_REQUEST_SEND_OPTIONS RequestOptions;
	WDFIOTARGET TargetOnParent;

	JOYSTICK_POSITION_V2 * iReport;
	WDFFILEOBJECT FileObj;
	USHORT id=0;
	PFILEOBJECT_EXTENSION pExtension=NULL;

    WDFREQUEST				requestForceFeedback;
	PHID_XFER_PACKET		transferPacket = NULL;
	PVOID					ForceFeedbackBuffer = NULL;
	PVOID					GenBuffer = NULL;
	size_t					bytesReturned = 0;
	WDF_REQUEST_PARAMETERS	Params;
	BOOLEAN					FfbStat = FALSE;
	ULONG					bytesToCopy = 0;
	BYTE					Byte_tmp;




    
    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

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

    //
    // Process the ioctl and complete it when you are done.
    // Since the queue is configured for serial dispatch, you will
    // not receive another ioctl request until you complete this one.
    //

	  switch (IoControlCode) {
 	case 1234: // TODO: Remove for production
		//RequestOptions.Flags =	WDF_REQUEST_SEND_OPTION_TIMEOUT;
		//RequestOptions.Size =	sizeof(WDF_REQUEST_SEND_OPTIONS);
		//WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&RequestOptions,  WDF_REL_TIMEOUT_IN_SEC(1));
		//status = WdfIoTargetSendInternalIoctlSynchronously(pdoData->IoTargetToParent, Request, IoControlCode , NULL, NULL, &RequestOptions, NULL);
		break; // Testing 

	case GET_DEV_STAT:
		// Get information for a device by device ID
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DEV_STAT\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy<5)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesToCopy=%d\n", bytesToCopy);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the buffer
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<5)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesReturned=%d\n", bytesReturned);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the id number from input buffer
		status = WdfRequestRetrieveInputBuffer(Request, sizeof(BYTE), &buffer, &bufSize);
		if (!NT_SUCCESS(status) || (bufSize!=1))
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed to retrieve input buffer\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get target ID
		id = *(BYTE *)buffer;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: id=%d\n", id);

		// Put data into output buffer
		// Byte 1:
		// Bit 0: Implemented?
		// Bit 1: FFB Device Enabled?
		// Bit 2: File Object associated with this device?
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		Byte_tmp = 0;

		// Implemented mask
		if (pDevContext->DeviceImplemented[id - 1])
			Byte_tmp |= 1;
		else
			Byte_tmp &= 0xFE;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Implemented=%x\n", pDevContext->DeviceImplemented[id - 1]);

		// FFB mask
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Enabled=%x\n", pDevContext->FfbEnable[id - 1]);
		if (pDevContext->FfbEnable[id - 1])
			Byte_tmp |= 2;
		else
			Byte_tmp &= 0xFD;

		// File Object
		if (pDevContext->DeviceFileObject[id - 1])
			Byte_tmp |= 4;
		else
			Byte_tmp &= 0xFB;

		((BYTE *)GenBuffer)[0] = Byte_tmp;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Buffer[0]=%x\n", ((BYTE *)GenBuffer)[0]);

		// Byte2-5: Process ID
		// Get the context
		FileObj = pDevContext->DeviceFileObject[id - 1];
		if (FileObj)
			*(DWORD *)(&((BYTE *)GenBuffer)[1]) = GetFileObjectContext(FileObj)->CallingProcessId;
		else
			*(DWORD *)(&((BYTE *)GenBuffer)[1]) = 0;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: ProcessID=%x\n", *(DWORD *)(&((BYTE *)GenBuffer)[1]));

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;



	case GET_DRV_INFO:
		// Get information for this driver
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO]\n");
		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);

		// Number of bytes to copy must be at least one byte
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy <1 )
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesToCopy <1\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};


		// Output buffer must be at least one byte
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesReturned <1\n");
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		pDevContext = GetDeviceContext(pdoData->hParentDevice);

		// Return the data in the output buffer
		// BYTE 0 //////////////////////////////
		// Bit 0	: Supports FFB?
		// Bit 1	: Reserved
		// Bit 2	: Mode: Multi-device 
		// Bit 3	: Mode: FFB 
		// BYTE 1 //////////////////////////////
		// Bits 0-7	: Maximum number of possible devices (16 ==> 255)  not regarding to mode
		// BYTE 2 //////////////////////////////
		// Bits 0-7	: Number of existing devices
		// BYTE 3 //////////////////////////////
		// Bits 0-7	: Number of devices that can still be implemented (This is the number of possible devices for the current mode minus the number of already existing devices).

		//////////////////////////////////
		// Byte 0
		Byte_tmp = 0;
		Byte_tmp |= 0x01; // FFB Supported
		Byte_tmp |= 0x00; // Default Mode (TODO: Change to real mode when Implemented) Multi-Device=0x04; FFB=0x80
		((BYTE *)GenBuffer)[0] = Byte_tmp;

		// Byte 1
		if (bytesToCopy >= 2 && bytesReturned >= 2)
		{
			((BYTE *)GenBuffer)[1] = MAX_N_DEVICES;
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[1]=%02x\n", ((BYTE *)GenBuffer)[1]);
		}

		// Byte 2
		if (bytesToCopy >= 3 && bytesReturned >= 3)
		{
			((BYTE *)GenBuffer)[2] = (BYTE)(pDevContext->nDevices);
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[2]=%02x\n", ((BYTE *)GenBuffer)[2]);
		}

		// Byte 3 - TODO: Change according to mode
		if (bytesToCopy >= 4 && bytesReturned >= 4)
		{
			((BYTE *)GenBuffer)[3] = MAX_N_DEVICES - (BYTE)(pDevContext->nDevices);
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[3]=%02x\n", ((BYTE *)GenBuffer)[3]);
		}
		//////////////////////////////////

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;


	case GET_DEV_INFO:
		// Get information for this device (and for the driver)

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		if (bytesToCopy<6)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (bytesReturned<6)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);

		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Copy the state to the buffer
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		((BYTE *)GenBuffer)[0] = (BYTE)id;
		((BYTE *)GenBuffer)[1] = (BYTE)(pDevContext->nDevices);
		((BYTE *)GenBuffer)[2] = pDevContext->DeviceImplemented ? 1:0;
		((BYTE *)GenBuffer)[3] = MAX_N_DEVICES; 
 		((BYTE *)GenBuffer)[4] = 1; // Driver does support FFB
		((BYTE *)GenBuffer)[5] = pDevContext->FfbEnable[id - 1]; // Device support FFB

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;

	case 0x910: // Backward compatibility value of 	LOAD_POSITIONS
	case LOAD_POSITIONS:
		// KdBreakPoint(); Break When loading position
		status = WdfRequestRetrieveInputBuffer( Request, sizeof(JOYSTICK_POSITION), &buffer, &bufSize);
		if(!NT_SUCCESS(status))
			break;

		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// Illegal ID
		if (id==0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the incoming report and compare the id in the report
		// to the implicated id of the top-level collection
		// They should match
		iReport = buffer;
		if (iReport->bDevice != id)
		{
			WdfRequestComplete(Request, STATUS_CANCELLED);
			return;
		};

		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		LoadPositions(iReport, pDevContext, bufSize);
		status = vJoyCompleteReadReport(pdoData->hParentDevice, (BYTE)id);
		break;   

	case GET_FFB_STAT:
		/* Get the status of the FFB mechanism */

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		if (!bytesReturned)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Copy the state to the buffer
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		((BYTE *)GenBuffer)[0] =  pDevContext->FfbEnable[id-1];

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		return;

	case SET_FFB_STAT:
		/*Set the status of the FFB mechanism - Obsolete*/

		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);

		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		// Get the context, id and the status
		id = GetIdFromRawPdoRequest(Request, pExtension);
		// Illegal ID
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};


		// Get the data, process the data and complete the transaction
		//pDevContext = GetDeviceContext(pdoData->hParentDevice);	   - Obsolete
		//FfbActiveSet(*(BOOLEAN *)Params.Parameters.DeviceIoControl.Type3InputBuffer, id, pDevContext);   - Obsolete
		WdfRequestComplete(Request, status);
		return;

	case GET_FFB_DATA:
		// Get interface that this IRP came from,
		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);


		// If FFB is not active then just reject this request
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		if (id == 0xFFFF || !pDevContext->FfbEnable[id - 1])
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// If FFB is active then forward this request to the ReadQ and return
		status = WdfRequestForwardToIoQueue(Request, pDevContext->FfbReadQ[id - 1]);
        if(!NT_SUCCESS(status)){
            TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
				"WdfRequestForwardToIoQueue (FfbWriteQ[%d]) failed with status: 0x%x\n", id - 1, status);
            WdfRequestComplete(Request, status);
        }
        return;

	case GET_DRV_DEV_EN:
		// Get the number of devices that are currently enabled
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_EN\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		if (!pdoData) break;
		pDevContext = GetDeviceContext(pdoData->hParentDevice);
		if (!pDevContext) break;
		// The number of the max supported devices
		((BYTE *)GenBuffer)[0] = (BYTE)(pDevContext->nDevices);

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;

	case GET_DRV_DEV_MAX:
		// Get the max possible number of devices that this driver supports
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_MAX\n");

		// Get the buffer from the request
		// Get the data from the request
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// The number of the max supported devices
		((BYTE *)GenBuffer)[0] = MAX_N_DEVICES;

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;


	case IS_DRV_FFB_CAP:
		// Test is this version of vJoy driver supports FFB
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case IS_DRV_FFB_CAP\n");

		// Get the data from the request (Bytes to copy)
		WDF_REQUEST_PARAMETERS_INIT(&Params);
		WdfRequestGetParameters(Request, &Params);
		bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength;
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy);
		if (bytesToCopy<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d (Failed)\n", bytesToCopy);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the buffer from the request
		status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned);
		if (bytesReturned<1)
		{
			TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d (Failed)\n", bytesReturned);
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Yes, this driver supports FFB
		((BYTE *)GenBuffer)[0] = 1;

		// Complete the transaction
		WdfRequestCompleteWithInformation(Request, status, bytesReturned);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]);
		return;
	case RESET_DEV:
		/* Resets device(s) to predefined values */
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case RESET_DEV\n");

		// then get the implicated id of the top-level collection
		id = GetIdFromRawPdoRequest(Request, pExtension);
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: ID=%d\n", id);

		// Sanity check
		if (id == 0xFFFF)
		{
			WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE);
			return;
		};

		// Get the context of vJoy device
		pDevContext = GetDeviceContext(pdoData->hParentDevice);		
		
		// Reset device(s)
		status = ResetDevice(id, pDevContext);
		WdfRequestCompleteWithInformation(Request, status, 0);
		return;

	default:
        break;
    }
	  WdfRequestComplete(Request, status);

    return;
}
Exemple #7
0
NTSTATUS
Bus_UnPlugDevice(
    WDFDEVICE   Device,
    ULONG       SerialNo
    )
/*++

Routine Description:

    The application has told us a device has departed from the bus.

    We therefore need to flag the PDO as no longer present
    and then tell Plug and Play about it.

Arguments:


Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/

{
    PPDO_DEVICE_DATA pdoData;
    BOOLEAN          found = FALSE;
    BOOLEAN          plugOutAll;
    WDFDEVICE        hChild;
    NTSTATUS         status = STATUS_INVALID_PARAMETER;

    PAGED_CODE ();

    plugOutAll = (0 == SerialNo) ? TRUE : FALSE;

    hChild = NULL;

    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                            hChild, WdfRetrieveAddedChildren)) != NULL) {

        if (plugOutAll) {

            status = WdfPdoMarkMissing(hChild);
            if(!NT_SUCCESS(status)) {
                KdPrint(("WdfPdoMarkMissing failed 0x%x\n", status));
                break;
            }

            found = TRUE;
        }
        else {
            pdoData = PdoGetData(hChild);

            if (SerialNo == pdoData->SerialNo) {

                status = WdfPdoMarkMissing(hChild);
                if(!NT_SUCCESS(status)) {
                    KdPrint(("WdfPdoMarkMissing failed 0x%x\n", status));
                    break;
                }

                found = TRUE;
                break;
            }
        }
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);

    if (found) {
        status = STATUS_SUCCESS;
    }

    return status;
}
Exemple #8
0
NTSTATUS
Bus_PlugInDevice(
    _In_ WDFDEVICE  Device,
    _In_ PWCHAR     HardwareIds,
    _In_ ULONG      SerialNo
    )

/*++

Routine Description:

    The user application has told us that a new device on the bus has arrived.

    We therefore need to create a new PDO, initialize it, add it to the list
    of PDOs for this FDO bus, and then tell Plug and Play that all of this
    happened so that it will start sending prodding IRPs.

--*/

{
    NTSTATUS         status = STATUS_SUCCESS;
    BOOLEAN          unique = TRUE;
    WDFDEVICE        hChild;
    PPDO_DEVICE_DATA pdoData;
    PFDO_DEVICE_DATA deviceData;

    PAGED_CODE ();

    //
    // First make sure that we don't already have another device with the
    // same serial number.
    // Framework creates a collection of all the child devices we have
    // created so far. So acquire the handle to the collection and lock
    // it before walking the item.
    //
    deviceData = FdoGetData(Device);
    hChild = NULL;

    //
    // We need an additional lock to synchronize addition because
    // WdfFdoLockStaticChildListForIteration locks against anyone immediately
    // updating the static child list (the changes are put on a queue until the
    // list has been unlocked).  This type of lock does not enforce our concept
    // of unique IDs on the bus (ie SerialNo).
    //
    // Without our additional lock, 2 threads could execute this function, both
    // find that the requested SerialNo is not in the list and attempt to add
    // it.  If that were to occur, 2 PDOs would have the same unique SerialNo,
    // which is incorrect.
    //
    // We must use a passive level lock because you can only call WdfDeviceCreate
    // at PASSIVE_LEVEL.
    //
    WdfWaitLockAcquire(deviceData->ChildLock, NULL);
    WdfFdoLockStaticChildListForIteration(Device);

    while ((hChild = WdfFdoRetrieveNextStaticChild(Device,
                            hChild, WdfRetrieveAddedChildren)) != NULL) {
        //
        // WdfFdoRetrieveNextStaticChild returns reported and to be reported
        // children (ie children who have been added but not yet reported to PNP).
        //
        // A surprise removed child will not be returned in this list.
        //
        pdoData = PdoGetData(hChild);

        //
        // It's okay to plug in another device with the same serial number
        // as long as the previous one is in a surprise-removed state. The
        // previous one would be in that state after the device has been
        // physically removed, if somebody has an handle open to it.
        //
        if (SerialNo == pdoData->SerialNo) {
            unique = FALSE;
            status = STATUS_INVALID_PARAMETER;
            break;
        }
    }

    if (unique) {
        //
        // Create a new child device.  It is OK to create and add a child while
        // the list locked for enumeration.  The enumeration lock applies only
        // to enumeration, not addition or removal.
        //
        status = Bus_CreatePdo(Device, HardwareIds, SerialNo);
    }

    WdfFdoUnlockStaticChildListFromIteration(Device);
    WdfWaitLockRelease(deviceData->ChildLock);

    return status;
}