A driver-created I/O request object describes a read, write, or device I/O control request. A driver can create its own I/O request objects to send a new I/O request to its own device stack, to request I/O from another device, or to split an existing I/O request into multiple, smaller requests before completing it.
When a driver calls the framework to create an I/O request, the framework creates and initializes a WDF I/O request object. The request object does not contain a memory object or any other information; the driver supplies that later by formatting the request.
KMDF In addition to sending read, write, and device I/O control requests, KMDF drivers can send internal device I/O control requests, which are device defined and sometimes have nonstandard parameters. Instead of supplying input and output buffers for such requests, a driver supplies as many as three memory objects and offset structures that describe the buffer space for the request.
To create an I/O request object, a UMDF driver calls IWDFDevice::CreateRequest, passing a pointer to the IUnknown interface on the driver's request callback object, a pointer to the IWDFObject interface on the parent object, and a location to receive a pointer to the IWDFIoRequest interface on the created request object.
Listing 9-3 shows an example from the Fx2_Driver sample's Device.cpp file.
Listing 9-3: Creating a WDF I/O request in a UMDF driver
HRESULT hr = S_OK; IWDFIoRequest *pWdfRequest = NULL; IWDFDriver * FxDriver = NULL; hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface, NULL, //pParentObject &pWdfRequest );
Creating an I/O request object is quite straightforward, as the listing shows. The driver calls the CreateRequest method on the device object, with three pointers:
A pointer to a callback interface that the framework uses to query for a cleanup callback on the request object. The sample driver passes NULL because it does not perform any cleanup associated with the request.
A pointer for the parent object. The sample passes NULL to accept the device object as the default parent.
A pointer to a variable in which the framework returns a pointer to the IWDFIoRequest interface on the created request object.
A KMDF driver calls WdfRequestCreate to create a WDF I/O request object. This method takes a pointer to an object attributes structure, an optional handle to an I/O target object, and a location to receive a handle to the created WDFREQUEST object.
Listing 9-4 shows how the Toastmon sample creates an I/O request object in the Toastmon.c file.
Listing 9-4: Creating a WDF I/O request object in a KMDF driver
WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = ioTarget; status = WdfRequestCreate(&attributes, ioTarget, &targetDeviceInfo->ReadRequest);
As Listing 9-4 shows, the driver initializes an attributes structure and then sets the parent object to the previously created I/O target object. By setting the I/O target object as the parent, the driver ensures that the framework deletes the I/O request object when it deletes the I/O target object. In this case, the driver reuses the request with the same I/O target as long as the I/O target is available.
The driver then calls WdfRequestCreate to create the request. It passes a pointer to the attributes structure, a handle to the I/O target object, and a location in which the framework returns a handle to the new I/O request object. The sample driver stores the handle in the context area of the I/O target object.