PIBIO_SENSOR_START_CAPTURE_FN
コールバックシグネチャ
HRESULT PIBIO_SENSOR_START_CAPTURE_FN(
WINBIO_PIPELINE* Pipeline,
BYTE Purpose,
OVERLAPPED** Overlapped
);パラメーター
| フィールド | 型 | 説明 |
|---|---|---|
| Pipeline | WINBIO_PIPELINE* | 操作を実行する生体認証ユニットに関連付けられた WINBIO_PIPELINE 構造体へのポインター。 |
| Purpose | BYTE | サンプルの用途を指定する WINBIO_BIR_PURPOSE ビットマスク。次の値のビットごとの OR を指定できます。
センサーによっては、複数の解像度で生体認証情報をキャプチャできるものがあります。Purpose パラメーターに複数のフラグが指定されている場合、アダプターは最も高い解像度を表すフラグを使用して、キャプチャ操作の解像度を決定してください。 |
| Overlapped | OVERLAPPED** | 非同期キャプチャ操作の状態を追跡する OVERLAPPED 構造体へのポインターを受け取る変数のアドレス。この構造体はセンサーアダプターが作成および管理しますが、同期のために Windows Biometric Framework が使用します。詳細については、「解説」セクションを参照してください。 |
公式ドキュメント
非同期の生体認証キャプチャを開始するために、Windows Biometric Framework から呼び出されます。
戻り値
関数が成功した場合は S_OK を返します。関数が失敗した場合は、エラーを示す HRESULT 値を返します。次の値は Windows Biometric Framework によって認識されます。
| 戻り値 | 説明 |
|---|---|
| 必須のポインター引数が NULL です。 | |
| Purpose パラメーターが無効です。 | |
| 操作を実行するためのメモリが不足していました。 | |
| デバイスがデータをキャプチャする準備ができていません。 | |
| デバイスの障害が発生しました。 | |
| Pipeline 引数が指す WINBIO_PIPELINE 構造体の SensorContext メンバーが NULL であるか、SensorHandle メンバーが INVALID_HANDLE_VALUE に設定されています。 |
解説(Remarks)
この関数はブロックしません。アダプターがキャプチャ操作の準備のためにセンサーへ複数のコマンドを発行する場合、最後のコマンド以外は同期的でもかまいません。SensorAdapterStartCapture が Windows Biometric Framework に制御を返す直前に発行される最後のコマンドは、非同期でなければならず、オーバーラップ I/O を使用する必要があります。
オーバーラップ I/O を使用するには、まずプライベートなセンサーアダプターコンテキスト構造体の定義に OVERLAPPED オブジェクトを追加します。この構造体は、WINBIO_PIPELINE オブジェクトの SensorContext フィールドを通じてアダプターから利用できます。
SensorAdapterAttach を実装する際は、OVERLAPPED 構造体を初期化するために次の操作を行う必要があります。
- ZeroMemory 関数を呼び出して OVERLAPPED 構造体をクリアします。
- CreateEvent 関数を使用して手動リセットのイベントオブジェクトを作成します。イベントオブジェクトが自動リセットではなく手動リセットであることが極めて重要です。オーバーラップ I/O で自動リセットイベントを使用すると、I/O 処理が回復不能な無応答状態に陥るおそれがあります。
- このイベントのハンドルを OVERLAPPED 構造体の hEvent メンバーに保存します。
Windows Biometric Framework は、キャプチャ操作が完了した時点を判断するために GetOverlappedResult や WaitForMultipleObjects などのオペレーティングシステム関数を呼び出す際に、この OVERLAPPED オブジェクトを使用します。
SensorAdapterStartCapture が制御を返す時点で、OVERLAPPED 構造体内のイベントハンドルは非シグナル状態でなければなりません。DeviceIoControl を呼び出してオーバーラップ I/O 操作を開始すると、イベントは自動的にリセットされます。アダプターが別の仕組みで I/O 操作を開始する場合は、イベントを自分でリセットする必要があります。
Windows Biometric Framework は、生体認証ユニットごとに、同時に未完了となる非同期 I/O 操作が 1 つだけであることを保証します。そのため、センサーアダプターが必要とする OVERLAPPED 構造体は、処理パイプラインごとに 1 つだけです。
Windows Biometric Framework はセンサーアダプターのハンドルの開閉を行い、そのハンドルがオーバーラップ 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;
}
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)