diff options
| author | Adonais Romero González <[email protected]> | 2024-05-06 16:21:31 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-05-06 16:21:31 -0700 |
| commit | a74a241c664c4e1d7c0838287b34076c19d9858a (patch) | |
| tree | 6ff7562612967b122acf8acf8a69c4dcfd5905db /biometrics/driver/Device.cpp | |
| parent | def8e8e34ed2b7b1deb2fc9112ac4255f1a0f2ba (diff) | |
| parent | 15477ce52bbb6b42ca591ecdfb484cac089f89ab (diff) | |
Merge develop changes prior to upcoming WDK release (May 2024)
Diffstat (limited to 'biometrics/driver/Device.cpp')
| -rw-r--r-- | biometrics/driver/Device.cpp | 1834 |
1 files changed, 0 insertions, 1834 deletions
diff --git a/biometrics/driver/Device.cpp b/biometrics/driver/Device.cpp deleted file mode 100644 index 8f8dd6b4..00000000 --- a/biometrics/driver/Device.cpp +++ /dev/null @@ -1,1834 +0,0 @@ -/*++ - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF - ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A - PARTICULAR PURPOSE. - - Copyright (c) Microsoft Corporation. All rights reserved - -Module Name: - - Device.cpp - -Abstract: - - This module contains the implementation of the Biometric - device driver. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ -#include "internal.h" -#include "device.tmh" - -#pragma warning(disable : 4189) - -DWORD WINAPI -CaptureSleepThread( - LPVOID lpParam - ) -{ - CBiometricDevice *device = (CBiometricDevice *) lpParam; - PCAPTURE_SLEEP_PARAMS sleepParams = device->GetCaptureSleepParams(); - - // - // Make sure it is less than or equal to 1 minute. - // - if (sleepParams->SleepValue > 60) - { - sleepParams->SleepValue = 60; - } - - Sleep(sleepParams->SleepValue * 1000); - - device->CompletePendingRequest(sleepParams->Hr, sleepParams->Information); - - return 0; -} - - -HRESULT -CBiometricDevice::CreateInstanceAndInitialize( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit, - _Out_ CBiometricDevice **Device - ) -/*++ - - Routine Description: - - This method creates and initializs an instance of the skeleton driver's - device callback object. - - Arguments: - - FxDeviceInit - the settings for the device. - - Device - a location to store the referenced pointer to the device object. - - Return Value: - - Status - ---*/ -{ - // - // Create a new instance of the device class - // - CComObject<CBiometricDevice> *pMyDevice = NULL; - HRESULT hr = CComObject<CBiometricDevice>::CreateInstance( &pMyDevice ); - - if (SUCCEEDED(hr)) - { - - // - // Initialize the instance. This calls the WUDF framework, - // which keeps a reference to the device interface for the lifespan - // of the device. - // - if (NULL != pMyDevice) - { - hr = pMyDevice->Initialize(FxDriver, FxDeviceInit); - - if (FAILED(hr)) - { - BiometricSafeRelease(pMyDevice); - } - - } - - *Device = pMyDevice; - - } - - return hr; -} - -HRESULT -CBiometricDevice::Initialize( - _In_ IWDFDriver * FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit - ) -/*++ - - Routine Description: - - This method initializes the device callback object and creates the - partner device object. - - The method should perform any device-specific configuration that: - * could fail (these can't be done in the constructor) - * must be done before the partner object is created -or- - * can be done after the partner object is created and which aren't - influenced by any device-level parameters the parent (the driver - in this case) might set. - - Arguments: - - FxDeviceInit - the settings for this device. - - Return Value: - - status. - ---*/ -{ - IWDFDevice *fxDevice = NULL; - HRESULT hr = S_OK; - IUnknown *unknown = NULL; - - // - // Configure things like the locking model before we go to create our - // partner device. - // - - // - // Set the locking model. - // - - FxDeviceInit->SetLockingConstraint(WdfDeviceLevel); - - // - // Any per-device initialization which must be done before - // creating the partner object. - // - - // - // Create a new FX device object and assign the new callback object to - // handle any device level events that occur. - // - - // - // We pass an IUnknown reference to CreateDevice, which takes its own - // reference if everything works. - // - - if (SUCCEEDED(hr)) - { - hr = this->QueryInterface(__uuidof(IUnknown), (void **)&unknown); - - } - - if (SUCCEEDED(hr)) - { - - hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &fxDevice); - BiometricSafeRelease(unknown); - } - - // - // If that succeeded then set our FxDevice member variable. - // - - if (SUCCEEDED(hr)) - { - m_FxDevice = fxDevice; - - // - // Drop the reference we got from CreateDevice. Since this object - // is partnered with the framework object they have the same - // lifespan - there is no need for an additional reference. - // - - BiometricSafeRelease(fxDevice); - } - - return hr; -} - -HRESULT -CBiometricDevice::Configure( - VOID - ) -/*++ - - Routine Description: - - This method is called after the device callback object has been initialized - and returned to the driver. It would setup the device's queues and their - corresponding callback objects. - - Arguments: - - FxDevice - the framework device object for which we're handling events. - - Return Value: - - status - ---*/ -{ - - HRESULT hr = S_OK; - - // - // Create the I/O queue - // - - if (SUCCEEDED(hr)) - { - hr = CBiometricIoQueue::CreateInstanceAndInitialize(m_FxDevice, this, &m_IoQueue); - - if (SUCCEEDED(hr)) - { - hr = m_IoQueue->Configure(); - } - } - - // - // Create Device Interface - // - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->CreateDeviceInterface(&GUID_DEVINTERFACE_BIOMETRIC_READER, - NULL); - } - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->AssignDeviceInterfaceState(&GUID_DEVINTERFACE_BIOMETRIC_READER, - NULL, - TRUE); - } - - // - // TODO - this is where additional interfaces can be exposed. - // - - return hr; -} - -HRESULT -CBiometricDevice::OnPrepareHardware( - _In_ IWDFDevice * /* FxDevice */ - ) -/*++ - -Routine Description: - - This routine is invoked to ready the driver - to talk to hardware. It opens the handle to the - device and talks to it using the WINUSB interface. - It invokes WINUSB to discver the interfaces and stores - the information related to bulk endpoints. - -Arguments: - - FxDevice : Pointer to the WDF device interface - -Return Value: - - HRESULT - ---*/ -{ - PWSTR deviceName = NULL; - DWORD deviceNameCch = 0; - - HRESULT hr; - - // - // Get the device name. - // Get the length to allocate first - // - - hr = m_FxDevice->RetrieveDeviceName(NULL, &deviceNameCch); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get device name %!hresult!", - hr - ); - } - - // - // Allocate the buffer - // - - if (SUCCEEDED(hr)) - { - deviceName = (PWSTR) malloc(deviceNameCch * sizeof (WCHAR)); - - if (deviceName == NULL) - { - hr = E_OUTOFMEMORY; - } - } - - // - // Get the actual name - // - - if (SUCCEEDED(hr)) - { - hr = m_FxDevice->RetrieveDeviceName(deviceName, &deviceNameCch); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get device name %!hresult!", - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Device name %S", - deviceName - ); - } - - // - // Create USB I/O Targets and configure them - // - - if (SUCCEEDED(hr)) - { - hr = CreateUsbIoTargets(); - } - - if (SUCCEEDED(hr)) - { - ULONG length = sizeof(m_Speed); - - hr = m_pIUsbTargetDevice->RetrieveDeviceInformation(DEVICE_SPEED, - &length, - &m_Speed); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get usb device speed information %!HRESULT!", - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Speed - %x\n", - m_Speed - ); - } - - // - // Setup power-management settings on the device. - // - - if (SUCCEEDED(hr)) - { - hr = SetPowerManagement(); - } - - // - // We have non-power managed queues so we Stop them in OnReleaseHardware - // and start them in OnPrepareHardware - // - - if (SUCCEEDED(hr)) - { - m_IoQueue->Start(); - } - - if (SUCCEEDED(hr)) - { - // - // If the device stack allows read to remain pending across power-down - // and up, it can be initiated during OnPrepareHardware - // - // If the device stack doesn't allow the read to remain pending (i.e. it - // cancels the pending read during power transition) driver will have to - // stop sending pending read during D0Exit and re-initiate it during - // D0Entry - // - // USB core actually doesn't allow read to remain pending across power - // transition but WinUSB does. Since we are layered above WinUSB we don't - // need to manage pending read across power transitions. - // - - hr = InitiatePendingRead(); - } - - if (deviceName) - { - free(deviceName); - deviceName = NULL; - } - - return hr; -} - -HRESULT -CBiometricDevice::OnReleaseHardware( - _In_ IWDFDevice * /* FxDevice */ - ) -/*++ - -Routine Description: - - This routine is invoked when the device is being removed or stopped - It releases all resources allocated for this device. - -Arguments: - - FxDevice - Pointer to the Device object. - -Return Value: - - HRESULT - Always succeeds. - ---*/ -{ - // - // Cancel the pending data collection I/O, if one exists. - // - CompletePendingRequest(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0); - - // - // Since we have non-power managed queues, we need to Stop them - // explicitly - // - // We need to stop them before deleting I/O targets otherwise we - // will continue to get I/O and our I/O processing will try to access - // freed I/O targets - // - // We initialize queues in CMyDevice::Initialize so we can't get - // here with queues being NULL and don't need to guard against that - // - - m_IoQueue->StopSynchronously(); - - // - // Delete USB Target Device WDF Object, this will in turn - // delete all the children - interface and the pipe objects - // - // This makes sure that - // 1. We drain the I/O before releasing the targets - // a. We always need to do that for the pending read which does - // not come from an I/O queue - // b. We need to do this even for I/O coming from I/O queues because - // we set them to non-power managed queues (to leverage wait/wake - // from WinUsb.sys) - // 2. We remove USB target objects from object tree (and thereby free them) - // before any potential subsequent OnPrepareHardware creates new ones - // - // m_pIUsbTargetDevice could be NULL if OnPrepareHardware failed so we need - // to guard against that - // - - if (m_pIUsbTargetDevice) - { - m_pIUsbTargetDevice->DeleteWdfObject(); - } - - // - // This sample has a thread that will sleep for 5 seconds before - // completing a capture request. - // - if (m_SleepThread != INVALID_HANDLE_VALUE) - { - WaitForSingleObject(m_SleepThread, INFINITE); - CloseHandle(m_SleepThread); - m_SleepThread = INVALID_HANDLE_VALUE; - } - - return S_OK; -} - -HRESULT -CBiometricDevice::CreateUsbIoTargets( - ) -/*++ - -Routine Description: - - This routine creates Usb device, interface and pipe objects - -Arguments: - - None - -Return Value: - - HRESULT ---*/ -{ - HRESULT hr; - UCHAR NumEndPoints = 0; - IWDFUsbTargetFactory * pIUsbTargetFactory = NULL; - IWDFUsbTargetDevice * pIUsbTargetDevice = NULL; - IWDFUsbInterface * pIUsbInterface = NULL; - IWDFUsbTargetPipe * pIUsbPipe = NULL; - - hr = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pIUsbTargetFactory)); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot get usb target factory %!HRESULT!", - hr - ); - } - - if (SUCCEEDED(hr)) - { - hr = pIUsbTargetFactory->CreateUsbTargetDevice( - &pIUsbTargetDevice); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to create USB Device I/O Target %!HRESULT!", - hr - ); - } - else - { - m_pIUsbTargetDevice = pIUsbTargetDevice; - - // - // Release the creation reference as object tree will maintain a reference - // - - BiometricSafeRelease(pIUsbTargetDevice); - } - } - - if (SUCCEEDED(hr)) - { - UCHAR NumInterfaces = pIUsbTargetDevice->GetNumInterfaces(); - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Found %u interfaces", - NumInterfaces - ); - - hr = pIUsbTargetDevice->RetrieveUsbInterface(0, &pIUsbInterface); - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to retrieve USB interface from USB Device I/O Target %!HRESULT!", - hr - ); - } - else - { - m_pIUsbInterface = pIUsbInterface; - - BiometricSafeRelease(pIUsbInterface); // release creation reference - } - } - - if (SUCCEEDED(hr)) - { - NumEndPoints = pIUsbInterface->GetNumEndPoints(); - - if (NumEndPoints != NUM_WBDI_ENDPOINTS) - { - hr = E_UNEXPECTED; - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Has %d endpoints, expected %d, returning %!HRESULT! ", - NumEndPoints, - NUM_WBDI_ENDPOINTS, - hr - ); - } - } - - if (SUCCEEDED(hr)) - { - for (UCHAR PipeIndex = 0; PipeIndex < NumEndPoints; PipeIndex++) - { - hr = pIUsbInterface->RetrieveUsbPipeObject(PipeIndex, - &pIUsbPipe); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to retrieve USB Pipe for PipeIndex %d, %!HRESULT!", - PipeIndex, - hr - ); - } - else - { - if ( pIUsbPipe->IsInEndPoint() ) - { - if ( UsbdPipeTypeInterrupt == pIUsbPipe->GetType() ) - { - m_pIUsbInterruptPipe = pIUsbPipe; - } - else if ( UsbdPipeTypeBulk == pIUsbPipe->GetType() ) - { - m_pIUsbInputPipe = pIUsbPipe; - } - else - { - pIUsbPipe->DeleteWdfObject(); - } - } - else if ( pIUsbPipe->IsOutEndPoint() && (UsbdPipeTypeBulk == pIUsbPipe->GetType()) ) - { - m_pIUsbOutputPipe = pIUsbPipe; - } - else - { - pIUsbPipe->DeleteWdfObject(); - } - - BiometricSafeRelease(pIUsbPipe); //release creation reference - } - } - - if (NULL == m_pIUsbInputPipe || NULL == m_pIUsbOutputPipe) - { - hr = E_UNEXPECTED; - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Input or output pipe not found, returning %!HRESULT!", - hr - ); - } - } - - BiometricSafeRelease(pIUsbTargetFactory); - - return hr; -} - -HRESULT -CBiometricDevice::SetPowerManagement( - VOID - ) -/*++ - - Routine Description: - - This method enables the WinUSB driver to power the device down when it is - idle. - - Arguments: - - None - - Return Value: - - Status - ---*/ -{ - - HRESULT hr = S_OK; - ULONG value = WBDI_SUSPEND_DELAY; - - hr = m_pIUsbTargetDevice->SetPowerPolicy( SUSPEND_DELAY, - sizeof(ULONG), - (PVOID) &value ); - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to set power policy (SUSPEND_DELAY) for the device %!HRESULT!", - hr - ); - } - - - // - // Finally enable auto-suspend. - // - - if (SUCCEEDED(hr)) - { - BOOL AutoSuspsend = TRUE; - - hr = m_pIUsbTargetDevice->SetPowerPolicy( AUTO_SUSPEND, - sizeof(BOOL), - (PVOID) &AutoSuspsend ); - } - - if (FAILED(hr)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Unable to set power policy (AUTO_SUSPEND) for the device %!HRESULT!", - hr - ); - } - - return hr; -} - -HRESULT -CBiometricDevice::SendControlTransferSynchronously( - _In_ PWINUSB_SETUP_PACKET SetupPacket, - _Inout_updates_(BufferLength) PBYTE Buffer, - _In_ ULONG BufferLength, - _Out_ PULONG LengthTransferred - ) -/*++ - - Routine Description: - - This method synchronously sends a control transfer request to - the USB I/O target. - - Arguments: - - SetupPacket - The command parameter structure - - Buffer - The data to transfer - - BufferLength - The size of the data buffer to transfer - - LengthTransferred - Contains the actual number of bytes transferred. - - Return Value: - - HRESULT - ---*/ -{ - HRESULT hr = S_OK; - IWDFIoRequest *pWdfRequest = NULL; - IWDFDriver * FxDriver = NULL; - IWDFMemory * FxMemory = NULL; - IWDFRequestCompletionParams * FxComplParams = NULL; - IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL; - - *LengthTransferred = 0; - - hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface - NULL, //pParentObject - &pWdfRequest); - - if (SUCCEEDED(hr)) - { - m_FxDevice->GetDriver(&FxDriver); - - hr = FxDriver->CreatePreallocatedWdfMemory( Buffer, - BufferLength, - NULL, //pCallbackInterface - pWdfRequest, //pParetObject - &FxMemory ); - } - - if (SUCCEEDED(hr)) - { - hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest, - SetupPacket, - FxMemory, - NULL); //TransferOffset - } - - if (SUCCEEDED(hr)) - { - hr = pWdfRequest->Send( m_pIUsbTargetDevice, - WDF_REQUEST_SEND_OPTION_SYNCHRONOUS, - 0); //Timeout - } - - if (SUCCEEDED(hr)) - { - pWdfRequest->GetCompletionParams(&FxComplParams); - - hr = FxComplParams->GetCompletionStatus(); - } - - if (SUCCEEDED(hr)) - { - HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams)); - if (SUCCEEDED(hrQI)) - { - FxUsbComplParams->GetDeviceControlTransferParameters( NULL, - LengthTransferred, - NULL, - NULL ); - } - } - - BiometricSafeRelease(FxUsbComplParams); - BiometricSafeRelease(FxComplParams); - BiometricSafeRelease(FxMemory); - - pWdfRequest->DeleteWdfObject(); - BiometricSafeRelease(pWdfRequest); - - BiometricSafeRelease(FxDriver); - - return hr; -} - -WDF_IO_TARGET_STATE -CBiometricDevice::GetTargetState( - IWDFIoTarget * pTarget - ) -/*++ - - Routine Description: - - This method gets the state of the I/O target - - Arguments: - - pTarget - A pointer to the I/O target - - Return Value: - - WDF_IO_TARGET_STATE - ---*/ -{ - IWDFIoTargetStateManagement * pStateMgmt = NULL; - WDF_IO_TARGET_STATE state = WdfIoTargetStateUndefined; - - HRESULT hrQI = pTarget->QueryInterface(IID_PPV_ARGS(&pStateMgmt)); - if (FAILED(hrQI)) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cannot query interface %!HRESULT!", - hrQI - ); - - return state; - } - - state = pStateMgmt->GetState(); - - BiometricSafeRelease(pStateMgmt); - - return state; -} - -HRESULT -CBiometricDevice::InitiatePendingRead( - VOID - ) -/*++ - - Routine Description: - - This routine starts up a cycling read on the interrupt pipe. As each - read completes it will start up the next one. - - Arguments: - - None - - Return Value: - - Status - ---*/ -{ - HRESULT hr = S_OK; - IWDFIoRequest * FxRequest = NULL; - IWDFMemory * FxMemory = NULL; - IWDFDriver * FxDriver = NULL; - IRequestCallbackRequestCompletion * FxComplCallback = NULL; - - hr = m_FxDevice->CreateRequest(NULL, NULL, &FxRequest); - - if (SUCCEEDED(hr)) - { - m_FxDevice->GetDriver(&FxDriver); - - hr = FxDriver->CreatePreallocatedWdfMemory( (PBYTE) &m_InterruptMessage, - sizeof(m_InterruptMessage), - NULL, //pCallbackInterface - FxRequest, //pParetObject - &FxMemory ); - } - - if (SUCCEEDED(hr)) - { - hr = m_pIUsbInterruptPipe->FormatRequestForRead(FxRequest, - NULL, //pFile - IoTarget would apply its file - FxMemory, - NULL, //Memory offset - NULL); //Device offset - } - - if (SUCCEEDED(hr)) - { - hr = this->QueryInterface(IID_PPV_ARGS(&FxComplCallback)); - if (SUCCEEDED(hr)) - { - FxRequest->SetCompletionCallback(FxComplCallback, NULL); - - hr = FxRequest->Send(m_pIUsbInterruptPipe, 0, 0); - } - } - - if (FAILED(hr)) - { - m_InterruptReadProblem = hr; - - if (FxRequest) - { - FxRequest->DeleteWdfObject(); - } - } - - BiometricSafeRelease(FxRequest); - BiometricSafeRelease(FxMemory); - BiometricSafeRelease(FxDriver); - BiometricSafeRelease(FxComplCallback); - - return hr; -} - -VOID -CBiometricDevice::OnCompletion( - _In_ IWDFIoRequest* FxRequest, - _In_ IWDFIoTarget* pIoTarget, - _In_ IWDFRequestCompletionParams* pParams, - _In_ PVOID pContext - ) -/*++ - - Routine Description: - - This method is called when the asynchronous pending - read on the interrupt pipe completes. - - Arguments: - - FxRequest - The request object - - pIoTarget - The I/O target for the request - - pParams - The completion parameters - - pContext - Optional context - - Return Value: - - None - ---*/ -{ - UNREFERENCED_PARAMETER(pIoTarget); - UNREFERENCED_PARAMETER(pContext); - - IWDFUsbRequestCompletionParams * pUsbComplParams = NULL; - IWDFMemory * FxMemory = NULL; - SIZE_T bytesRead = 0; - HRESULT hrCompletion = pParams->GetCompletionStatus(); - - TraceEvents(TRACE_LEVEL_INFORMATION, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Pending read completed with %!hresult!", - hrCompletion - ); - - if (FAILED(hrCompletion)) - { - m_InterruptReadProblem = hrCompletion; - } - else - { - // - // Get the interrupt message - // - - HRESULT hrQI = pParams->QueryInterface(IID_PPV_ARGS(&pUsbComplParams)); - if (SUCCEEDED(hrQI)) - { - pUsbComplParams->GetPipeReadParameters(&FxMemory, &bytesRead, NULL); - if (bytesRead == sizeof(INTERRUPT_MESSAGE)) - { - - PVOID pBuff = FxMemory->GetDataBuffer(NULL); - CopyMemory(&m_InterruptMessage, pBuff, sizeof(m_InterruptMessage)); - - // - // TODO: Parse m_InterruptMessage - // - } - } - } - - // - // Don't complete the request since we created it, just delete it. - // - - FxRequest->DeleteWdfObject(); - - // - // Re-initiate pending read if I/O Target is not stopped/removed - // - - if (WdfIoTargetStarted == GetTargetState(m_pIUsbInterruptPipe)) - { - int numRetries = 0; - HRESULT hr = InitiatePendingRead(); - - // - // If we fail here, the device will become unresponsive. - // Re-issue the request until it succeeds. - // - for (numRetries = 0; FAILED(hr) && numRetries < 3; ++numRetries) - { - hr = InitiatePendingRead(); - } - } - - BiometricSafeRelease(pUsbComplParams); - BiometricSafeRelease(FxMemory); -} - - -// -// I/O handlers -// - -void -CBiometricDevice::GetIoRequestParams( - _In_ IWDFIoRequest *FxRequest, - _Out_ ULONG *MajorControlCode, - _Outptr_result_bytebuffer_(*InputBufferSizeInBytes) PUCHAR *InputBuffer, - _Out_ SIZE_T *InputBufferSizeInBytes, - _Outptr_result_bytebuffer_(*OutputBufferSizeInBytes) PUCHAR *OutputBuffer, - _Out_ SIZE_T *OutputBufferSizeInBytes - ) -/*++ - - Routine Description: - - This method retrieves the input and output buffers associated with the request. - - Arguments: - - FxRequest - The WDF request oject - - MajorControlCode - Contains the control code for the I/O request - - InputBuffer - Contains the input buffer pointer - - InputBufferSizeInBytes - Contains the size of the input buffer - - OutputBuffer - Contains the output buffer pointer - - OutputBufferSizeInBytes - Contains the size of the output buffer - - Return Value: - - None - ---*/ -{ - // - // Get main parameters - // - FxRequest->GetDeviceIoControlParameters(MajorControlCode, - InputBufferSizeInBytes, - OutputBufferSizeInBytes); - - // Get pointer to input buffer - IWDFMemory *fxMemory = NULL; - FxRequest->GetInputMemory(&fxMemory); - if (fxMemory) - { - *InputBuffer = (PUCHAR) fxMemory->GetDataBuffer(InputBufferSizeInBytes); - BiometricSafeRelease(fxMemory); - } - - // Save pointer to reply buffer - fxMemory = NULL; - FxRequest->GetOutputMemory(&fxMemory); - if (fxMemory) - { - *OutputBuffer = (PUCHAR) fxMemory->GetDataBuffer(OutputBufferSizeInBytes); - BiometricSafeRelease(fxMemory); - } -} - -void -CBiometricDevice::OnGetAttributes( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_ATTRIBUTES command is called. - - Arguments: - - FxRequest - The output for this request is a PWINBIO_SENSOR_ATTRIBUTES. - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_SENSOR_ATTRIBUTES sensorAttributes = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&sensorAttributes, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (sensorAttributes == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - // We only have one supported format, so sizeof (WINBIO_SENSOR_ATTRIBUTES) is sufficient. - if (outputBufferSize < sizeof(WINBIO_SENSOR_ATTRIBUTES)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_SENSOR_ATTRIBUTES)); - sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // Fill in the attribute payload structure - // - RtlZeroMemory(sensorAttributes, outputBufferSize); - sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES); - sensorAttributes->WinBioHresult = S_OK; - sensorAttributes->WinBioVersion.MajorVersion = WINBIO_WBDI_MAJOR_VERSION; - sensorAttributes->WinBioVersion.MinorVersion = WINBIO_WBDI_MINOR_VERSION; - sensorAttributes->SensorType = WINBIO_TYPE_FINGERPRINT; - sensorAttributes->SensorSubType = WINBIO_FP_SENSOR_SUBTYPE_SWIPE; - sensorAttributes->Capabilities = WINBIO_CAPABILITY_SENSOR; - sensorAttributes->SupportedFormatEntries = 1; - sensorAttributes->SupportedFormat[0].Owner = WINBIO_ANSI_381_FORMAT_OWNER; - sensorAttributes->SupportedFormat[0].Type= WINBIO_ANSI_381_FORMAT_TYPE; - RtlCopyMemory(sensorAttributes->ManufacturerName, SAMPLE_MANUFACTURER_NAME, (wcslen(SAMPLE_MANUFACTURER_NAME)+1)*sizeof(WCHAR)); - RtlCopyMemory(sensorAttributes->ModelName, SAMPLE_MODEL_NAME, (wcslen(SAMPLE_MODEL_NAME)+1)*sizeof(WCHAR)); - RtlCopyMemory(sensorAttributes->SerialNumber, SAMPLE_SERIAL_NUMBER, (wcslen(SAMPLE_SERIAL_NUMBER)+1)*sizeof(WCHAR)); - sensorAttributes->FirmwareVersion.MajorVersion = 1; - sensorAttributes->FirmwareVersion.MinorVersion = 0; - - MyRequest.SetInformation(sensorAttributes->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnReset( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_RESET command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_BLANK_PAYLOAD blankPayload = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&blankPayload, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (blankPayload== NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_BLANK_PAYLOAD)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // This is a simulated device. Nothing to do here except cancel the pending data - // collection I/O, if one exists. - // - CompletePendingRequest(HRESULT_FROM_WIN32(ERROR_CANCELLED), 0); - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(blankPayload, outputBufferSize); - blankPayload->PayloadSize = (DWORD) sizeof(WINBIO_BLANK_PAYLOAD); - blankPayload->WinBioHresult = S_OK; - - FxRequest->SetInformation(blankPayload->PayloadSize); - MyRequest.SetCompletionHr(S_OK); - -} - -void -CBiometricDevice::OnCalibrate( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CALIBRATE command is called. - - Arguments: - - FxRequest - - IN - blank payload - OUT - PWINBIO_CALIBRATION_INFO - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_CALIBRATION_INFO calibrationInfo = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&calibrationInfo, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (calibrationInfo == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_CALIBRATION_INFO)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - calibrationInfo->PayloadSize = (DWORD) sizeof(WINBIO_CALIBRATION_INFO); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // This is where code to calibrate the device goes. - // - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(calibrationInfo, outputBufferSize); - calibrationInfo->PayloadSize = (DWORD) sizeof(WINBIO_CALIBRATION_INFO); - calibrationInfo->WinBioHresult = S_OK; - - MyRequest.SetInformation(calibrationInfo->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnGetSensorStatus( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_SENSOR_STATUS command is called. - - Arguments: - - FxRequest - - IN payload: none - OUT payload: PWINBIO_DIAGNOSTICS - - Return Value: - - None - ---*/ -{ - CRequestHelper MyRequest(FxRequest); // RAII helper class - ULONG controlCode = 0; - PUCHAR inputBuffer= NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_DIAGNOSTICS diagnostics = NULL; - SIZE_T outputBufferSize; - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - &inputBuffer, - &inputBufferSize, - (PUCHAR *)&diagnostics, - &outputBufferSize); - - // - // Make sure we have an output buffer big enough - // - if (diagnostics == NULL || outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - MyRequest.SetCompletionHr(E_INVALIDARG); - return; - } - - if (outputBufferSize < sizeof(WINBIO_DIAGNOSTICS)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS)); - diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS); - MyRequest.SetInformation(sizeof(DWORD)); - MyRequest.SetCompletionHr(S_OK); - return; - } - - // - // Fill in the OUT payload structure - // - RtlZeroMemory(diagnostics, outputBufferSize); - diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS); - diagnostics->WinBioHresult = S_OK; - diagnostics->SensorStatus = WINBIO_SENSOR_READY; - - MyRequest.SetInformation(diagnostics->PayloadSize); - MyRequest.SetCompletionHr(S_OK); -} - - -void -CBiometricDevice::OnCaptureData( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CAPTURE_DATA command is called. - - Arguments: - - FxRequest - - IN payload: PWINBIO_CAPTURE_PARAMETERS - OUT payload: PWINBIO_CAPTURE_DATA - - Return Value: - - None - ---*/ -{ - ULONG controlCode = 0; - PWINBIO_CAPTURE_PARAMETERS captureParams = NULL; - SIZE_T inputBufferSize = 0; - PWINBIO_CAPTURE_DATA captureData = NULL; - SIZE_T outputBufferSize = 0; - - // - // We can only have one outstanding data capture request at a time. - // Check to see if we have a request pending. - // - bool requestPending = false; - - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest == NULL) - { - // - // See if we have an active sleep thread. - // If so, tell it to exit. - // Wait for it to exit. - // - if (m_SleepThread != INVALID_HANDLE_VALUE) - { - LeaveCriticalSection(&m_RequestLock); - - // TODO: Add code to signal thread to exit. - - // NOTE: Sleeping for INFINITE time is dangerous. A real driver - // should be able to handle the case where the thread does - // not exit. - WaitForSingleObject(m_SleepThread, INFINITE); - CloseHandle(m_SleepThread); - m_SleepThread = INVALID_HANDLE_VALUE; - - EnterCriticalSection(&m_RequestLock); - } - - // - // We might have had to leave the CS to wait for the sleep thread. - // Double check that the pending request is still NULL. - // - if (m_PendingRequest == NULL) - { - // Save the request. - m_PendingRequest = FxRequest; - - // Mark the request as cancellable. - m_PendingRequest->MarkCancelable(this); - } - else - { - requestPending = true; - } - - } - else - { - requestPending = true; - } - - LeaveCriticalSection(&m_RequestLock); - - if (requestPending) - { - // Complete the request to tell the app that there is already - // a pending data collection request. - FxRequest->Complete(WINBIO_E_DATA_COLLECTION_IN_PROGRESS); - return; - } - - // - // Get the request parameters - // - GetIoRequestParams(FxRequest, - &controlCode, - (PUCHAR *)&captureParams, - &inputBufferSize, - (PUCHAR *)&captureData, - &outputBufferSize); - - // - // Check input parameters. - // - if (inputBufferSize < sizeof (WINBIO_CAPTURE_PARAMETERS)) - { - // Invalid arguments - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Invalid argument(s)."); - CompletePendingRequest(E_INVALIDARG, 0); - return; - } - - // - // Make sure we have an output buffer big enough - // - if (outputBufferSize < sizeof(DWORD)) - { - // We cannot return size information. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Output buffer NULL or too small to return size information."); - CompletePendingRequest(E_INVALIDARG, 0); - return; - } - - // - // Check output buffer size. - // - if (outputBufferSize < sizeof (WINBIO_CAPTURE_DATA)) - { - // Buffer too small. - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC!Buffer too small - must be at least 0x%x.", sizeof (WINBIO_CAPTURE_DATA)); - // - // NOTE: The output buffer size necessary for this sample is sizeof(WINBIO_CAPTURE_DATA). - // Real devices will need additional space to handle a typical capture. - // The value that should be returned here is sizeof(WINBIO_CAPTURE_DATA) + CaptureBufferSize. - // - captureData->PayloadSize = (DWORD) sizeof(WINBIO_CAPTURE_DATA); - CompletePendingRequest(S_OK, sizeof(DWORD)); - return; - } - - // - // NOTE: This call always fails in this sample since it is not - // written for a real device. - // - - // - // Set default values in output buffer. - // - captureData->PayloadSize = (DWORD) sizeof (WINBIO_CAPTURE_DATA); - captureData->WinBioHresult = WINBIO_E_NO_CAPTURE_DATA; - captureData->SensorStatus = WINBIO_SENSOR_FAILURE; - captureData->RejectDetail= 0; - captureData->CaptureData.Size = 0; - - // - // Check purpose, format and type. - // - if (captureParams->Purpose == WINBIO_NO_PURPOSE_AVAILABLE) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_PURPOSE; - } - else if ((captureParams->Format.Type != WINBIO_ANSI_381_FORMAT_TYPE) || - (captureParams->Format.Owner != WINBIO_ANSI_381_FORMAT_OWNER)) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_FORMAT; - } - else if (captureParams->Flags != WINBIO_DATA_FLAG_RAW) - { - captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_TYPE; - } - - // - // NOTE: This sample completes the request after - // sleeping for 5 seconds. A real driver would - // program the device for capture mode, and then - // return from this callback. The request would - // remain pending until cancelled, or until the - // driver detects a capture is complete. - // - // The construct of m_PendingRequest will allow - // a driver to have only one pending request at any - // time, which can be cancelled in a Reset IOCTL, or - // by calling CancelIoEx. - // - - // - // Create thread to sleep 5 seconds before completing the request. - // - m_SleepParams.SleepValue = 5; - m_SleepParams.Hr = S_OK; - m_SleepParams.Information = captureData->PayloadSize; - m_SleepThread = CreateThread(NULL, // default security attributes - 0, // use default stack size - CaptureSleepThread, // thread function name - this, // argument to thread function - 0, // use default creation flags - NULL); // returns the thread identifier -} - - -void -CBiometricDevice::OnUpdateFirmware( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_UPDATE_FIRMWARE command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnGetSupportedAlgorithms( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_SUPPORTED_ALGORITHMS command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnGetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_GET_INDICATOR command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - - -void -CBiometricDevice::OnSetIndicator( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_SET_INDICATOR command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - -void -CBiometricDevice::OnControlUnit( - _Inout_ IWDFIoRequest *FxRequest - ) -/*++ - - Routine Description: - - This method is invoked when the IOCTL_BIOMETRIC_CONTROL_UNIT command is called. - - Arguments: - - FxRequest - - - Return Value: - - None - ---*/ -{ - FxRequest->Complete(E_NOTIMPL); -} - - -VOID -CBiometricDevice::CompletePendingRequest( - HRESULT hr, - DWORD information - ) -{ - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest) - { - // - // Only complete the request if we weren't cancelled. Otherwise, the - // OnCancel callback will complete the request. - // - HRESULT hrUnmark = m_PendingRequest->UnmarkCancelable(); - if (HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) != hrUnmark) - { - m_PendingRequest->SetInformation(information); - m_PendingRequest->Complete(hr); - m_PendingRequest = NULL; - } - } - - LeaveCriticalSection(&m_RequestLock); -} - -VOID -STDMETHODCALLTYPE -CBiometricDevice::OnCancel( - _In_ IWDFIoRequest *pWdfRequest - ) -{ - EnterCriticalSection(&m_RequestLock); - - if (m_PendingRequest != pWdfRequest) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Cancelled request does not match pending request."); - } - - // - // TODO: In a real driver, the device would be reset so that it is no longer in capture mode. - // Add your code to do so here. - // - - if (m_PendingRequest == NULL) - { - TraceEvents(TRACE_LEVEL_ERROR, - BIOMETRIC_TRACE_DEVICE, - "%!FUNC! Pending request is NULL."); - } - else - { - m_PendingRequest->Complete(HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)); - m_PendingRequest = NULL; - } - - LeaveCriticalSection(&m_RequestLock); -} |
