PIBIO_SENSOR_START_CAPTURE_FN コールバック関数 (winbio_adapter.h)

非同期生体認証キャプチャを開始するために、Windows 生体認証フレームワークによって呼び出されます。

構文

PIBIO_SENSOR_START_CAPTURE_FN PibioSensorStartCaptureFn;

HRESULT PibioSensorStartCaptureFn(
  [in, out] PWINBIO_PIPELINE Pipeline,
  [in]      WINBIO_BIR_PURPOSE Purpose,
  [out]     LPOVERLAPPED *Overlapped
)
{...}

パラメーター

[in, out] Pipeline

操作を実行する生体認証ユニットに関連付けられている WINBIO_PIPELINE 構造体へのポインター。

[in] Purpose

サンプル 使用目的を指定するWINBIO_BIR_PURPOSEビットマスク。 これは、次の値のビットごとの OR にすることができます。

  • WINBIO_PURPOSE_VERIFY
  • WINBIO_PURPOSE_IDENTIFY
  • WINBIO_PURPOSE_ENROLL
  • WINBIO_PURPOSE_ENROLL_FOR_VERIFICATION
  • WINBIO_PURPOSE_ENROLL_FOR_IDENTIFICATION

一部のセンサーでは、生体情報を複数の解像度でキャプチャできます。 Purpose パラメーターで複数のフラグが指定されている場合、アダプターは、キャプチャ操作の解像度を決定するために、最高の解像度を表すフラグを使用する必要があります。

[out] Overlapped

非同期キャプチャ操作の状態を追跡する OVERLAPPED 構造体へのポインターを受け取る変数のアドレス。 この構造は、センサー アダプターによって作成および管理されますが、同期のために Windows 生体認証フレームワークによって使用されます。 詳細については、「解説」を参照してください。

戻り値

関数が成功した場合は、S_OK を返します。 関数が失敗した場合は、エラーを示す HRESULT 値を返します。 次の値は、Windows 生体認証フレームワークによって認識されます。

リターン コード 説明
E_POINTER
必須のポインター引数は NULL です
E_INVALIDARG
Purpose パラメーターが無効です。
E_OUTOFMEMORY
操作を実行するのに十分なメモリが不足していました。
WINBIO_E_DEVICE_BUSY
デバイスでデータをキャプチャする準備ができていない。
WINBIO_E_DEVICE_FAILURE
デバイスエラーが発生しました。
WINBIO_E_INVALID_DEVICE_STATE
Pipeline 引数が指すWINBIO_PIPELINE構造体の SensorContext メンバーが NULL であるか、SensorHandle メンバーが INVALID_HANDLE_VALUE に設定されています。

注釈

この関数はブロックしません。 アダプターがセンサーに複数のコマンドを発行してキャプチャ操作の準備を行う場合、最後のコマンド以外はすべて同期可能です。 SensorAdapterStartCapture が Windows 生体認証フレームワークに制御を返す直前に発行される最後のコマンドは非同期であり、重複する I/O を使用する必要があります。

重複した I/O を使用するには、まず、プライベート センサー アダプター コンテキスト構造の定義に OVERLAPPED オブジェクトを追加します。 この構造体は、WINBIO_PIPELINE オブジェクトの SensorContext フィールドを介してアダプターで使用できます。

SensorAdapterAttach を実装する場合は、次のアクションを実行して OVERLAPPED 構造体を初期化する必要があります。

  • ZeroMemory 関数を呼び出して、OVERLAPPED 構造体をクリアします。
  • CreateEvent 関数を使用して、手動リセット イベント オブジェクトを作成します。 イベント オブジェクトは、自動リセットではなく手動で行う必要があります。 重複した I/O で自動リセット イベントを使用すると、I/O 処理操作で回復不可能な応答が不足する可能性があります。
  • このイベントのハンドルを、OVERLAPPED 構造体の hEvent メンバーに保存します。
SensorAdapterDetach を実装する場合は、CloseHandle 関数を呼び出してイベント オブジェクトを解放する必要があります。 キャプチャに関連するすべての入出力操作が完了または取り消されるまで、このハンドルを解放しないことが重要です。

Windows 生体認証フレームワークは、GetOverlappedResultWaitForMultipleObjects などのオペレーティング システム関数を呼び出すときに OVERLAPPED オブジェクトを使用して、キャプチャ操作がいつ完了したかを判断します。

SensorAdapterStartCapture が返された場合、OVERLAPPED 構造体のイベント ハンドルは非シグナル状態である必要があります。 DeviceIoControl を呼び出して重複する I/O 操作を開始すると、イベントが自動的にリセットされます。 アダプターで他のメカニズムを使用して I/O 操作を開始する場合は、イベントを自分でリセットする必要があります。

Windows 生体認証フレームワークでは、生体認証ユニットごとに、いつでも 1 つの非同期 I/O 操作のみが未処理であることが保証されます。 そのため、センサー アダプターは、処理パイプラインごとに 1 つの OVERLAPPED 構造のみを必要とします。

Windows 生体認証フレームワークは、センサー アダプター ハンドルを開いて閉じ、ハンドルが重複する I/O 用に構成されていることを確認する役割を担います。

次の擬似コードは、この関数の 1 つの可能な実装を示しています。 この例はコンパイルされません。 目的に合わせて調整する必要があります。

//////////////////////////////////////////////////////////////////////////////////////////
//
// SensorAdapterStartCapture
//
// Purpose:
//      Begins an asynchronous biometric capture.
//      
// Parameters:
//      Pipeline   -  Pointer to a WINBIO_PIPELINE structure associated with 
//                    the biometric unit.
//      Purpose    -  A WINBIO_BIR_PURPOSE bitmask that specifies the intended
//                    use of the sample.
//      Overlapped -  Receives a pointer to an OVERLAPPED structure.
//
static HRESULT 
WINAPI
SensorAdapterStartCapture(
    __inout PWINBIO_PIPELINE Pipeline,
    __in WINBIO_BIR_PURPOSE Purpose,
    __out LPOVERLAPPED *Overlapped
    )
{
    HRESULT hr = S_OK;
    WINBIO_SENSOR_STATUS sensorStatus = WINBIO_SENSOR_FAILURE;
    WINBIO_CAPTURE_PARAMETERS captureParameters = {0};
    BOOL result = TRUE;
    DWORD bytesReturned = 0;

    // Verify that pointer arguments are not NULL.
    if (!ARGUMENT_PRESENT(Pipeline) ||
        !ARGUMENT_PRESENT(Purpose)  ||
        !ARGUMENT_PRESENT(Overlapped))
    {
        hr = E_POINTER;
        goto cleanup;
    }

    // Retrieve the context from the pipeline.
    PWINBIO_SENSOR_CONTEXT sensorContext = 
                       (PWINBIO_SENSOR_CONTEXT)Pipeline->SensorContext;

    // Verify the state of the pipeline.
    if (sensorContext == NULL || 
        Pipeline->SensorHandle == INVALID_HANDLE_VALUE)
    {
        return WINBIO_E_INVALID_DEVICE_STATE;
    }

    *Overlapped = NULL;

    //  Synchronously retrieve the status.
    hr = SensorAdapterQueryStatus(Pipeline, &sensorStatus);
    if (FAILED(hr))
    {
        return hr;
    }

    // Determine whether the sensor requires calibration.
    if (sensorStatus == WINBIO_SENSOR_NOT_CALIBRATED)
    {
        // Call a custom function that sends IOCTLs to
        // the sensor to calibrate it. This operation is
        // synchronous.
        hr = _SensorAdapterCalibrate(Pipeline);

        // Retrieve the status again to determine whether the 
        // sensor is ready.
        if (SUCCEEDED(hr))
        {
            hr = SensorAdapterQueryStatus(Pipeline, &sensorStatus);
        }

        if (FAILED(hr))
        {
            return hr;
        }
    }
    if (sensorStatus == WINBIO_SENSOR_BUSY)
    {
        return WINBIO_E_DEVICE_BUSY;
    }

    if (sensorStatus != WINBIO_SENSOR_READY)
    {
        return WINBIO_E_INVALID_DEVICE_STATE;
    }

    // Determine whether the data format has been previously determined.
    // If it has not, find a format supported by both the engine and 
    // the sensor.
    if ((sensorContext->Format.Owner == 0) &&
        (sensorContext->Format.Type == 0))
    {

        // Retrieve the format preferred by the engine.
        hr = Pipeline->EngineInterface->QueryPreferredFormat(
                                            Pipeline,
                                            &sensorContext->Format,
                                            &sensorContext->VendorFormat
                                            );
        if (SUCCEEDED(hr))
        {
            // Call a private function that queries the sensor driver
            // and attaches an attribute array to the sensor context.
            // This operation is synchronous.
            hr = _SensorAdapterGetAttributes(Pipeline);
        }

        if (SUCCEEDED(hr))
        {
            // Search the sensor attributes array for the format
            // preferred by the engine adapter.
            DWORD i = 0;
            for (i = 0; i < sensorContext->AttributesBuffer->SupportedFormatEntries; i++)
            {
                if ((sensorContext->AttributesBuffer->SupportedFormat[i].Owner == sensorContext->Format.Owner) &&
                    (sensorContext->AttributesBuffer->SupportedFormat[i].Type == sensorContext->Format.Type))
                {
                    break;
                }
            }

            if (i == sensorContext->AttributesBuffer->SupportedFormatEntries)
            {
                // No match was found. Use the default.
                sensorContext->Format.Owner = WINBIO_ANSI_381_FORMAT_OWNER;
                sensorContext->Format.Type = WINBIO_ANSI_381_FORMAT_TYPE;
            }
        }
        else
        {
            return hr;
        }
    }

    // Set up the parameter-input block needed for the IOCTL.
    captureParameters.PayloadSize = sizeof(WINBIO_CAPTURE_PARAMETERS);
    captureParameters.Purpose = Purpose;
    captureParameters.Format.Owner = sensorContext->Format.Owner;
    captureParameters.Format.Type = sensorContext->Format.Type;
    CopyMemory(&captureParameters.VendorFormat, &sensorContext->VendorFormat, sizeof (WINBIO_UUID));
    captureParameters.Flags = WINBIO_DATA_FLAG_RAW;

    // Determine whether a buffer has already been allocated for this sensor.
    if (sensorContext->CaptureBuffer == NULL)
    {
        DWORD allocationSize = 0;

        sensorContext->CaptureBufferSize = 0;

        // This sample assumes that the sensor driver returns
        // a fixed-size DWORD buffer containing the required
        // size of the capture buffer if it receives a buffer
        // that is smaller than sizeof(WINBIO_CAPTURE_DATA).
        //
        // Call the driver with a small buffer to get the 
        // allocation size required for this sensor.
        //
        // Because this operation is asynchronous, you must block 
        // and wait for it to complete.
        result = DeviceIoControl(
                    Pipeline->SensorHandle,
                    IOCTL_VENDOR_PRIVATE_CMD_CAPTURE_DATA,
                    &captureParameters,
                    sizeof(WINBIO_CAPTURE_PARAMETERS),
                    &allocationSize,
                    sizeof(DWORD),
                    &bytesReturned,
                    &sensorContext->Overlapped
                    );
        if (!result && GetLastError() == ERROR_IO_PENDING)
        {
            SetLastError(ERROR_SUCCESS);

            result = GetOverlappedResult(
                        Pipeline->SensorHandle,
                        &sensorContext->Overlapped,
                        &bytesReturned,
                        TRUE
                        );
        }

        if (!result || bytesReturned != sizeof (DWORD))
        {
            // An error occurred.
            hr = _AdapterGetHresultFromWin32(GetLastError());
            return hr;
        }

        // Make sure that you allocate at least the minimum buffer 
        // size needed to get the payload structure.
        if (allocationSize < sizeof(WINBIO_CAPTURE_DATA))
        {
            allocationSize = sizeof(WINBIO_CAPTURE_DATA);
        }

        // Allocate the buffer.
        sensorContext->CaptureBuffer = (PWINBIO_CAPTURE_DATA)_AdapterAlloc(allocationSize);
        if (!sensorContext->CaptureBuffer)
        {
            sensorContext->CaptureBufferSize = 0;
            return E_OUTOFMEMORY;
        }
        sensorContext->CaptureBufferSize = allocationSize;
    }
    else
    {
        // The buffer has already been allocated. Clear the buffer contents. 
        SensorAdapterClearContext(Pipeline);
    }

    // Send the capture request. Because this is an asynchronous operation,
    // the IOCTL call will return immediately regardless of 
    // whether the I/O has completed.
    result = DeviceIoControl(
                Pipeline->SensorHandle,
                IOCTL_VENDOR_PRIVATE_CMD_CAPTURE_DATA,
                &captureParameters,
                sizeof (WINBIO_CAPTURE_PARAMETERS),
                sensorContext->CaptureBuffer,
                sensorContext->CaptureBufferSize,
                &bytesReturned,
                &sensorContext->Overlapped
                );

    if (result ||
        (!result && GetLastError() == ERROR_IO_PENDING))
    {
        *Overlapped = &sensorContext->Overlapped;
        return S_OK;
    }
    else
    {
        hr = _AdapterGetHresultFromWin32(GetLastError());
        return hr;
    }
}

要件

要件
サポートされている最小のクライアント Windows 7 [デスクトップ アプリのみ]
サポートされている最小のサーバー Windows Server 2008 R2 [デスクトップ アプリのみ]
対象プラットフォーム Windows
ヘッダー winbio_adapter.h (Winbio_adapter.h を含む)

こちらもご覧ください

プラグイン関数

SensorAdapterFinishCapture