PIBIO_STORAGE_DELETE_RECORD_FN コールバック関数 (winbio_adapter.h)
データベースから 1 つ以上のテンプレートを削除するために、Windows 生体認証フレームワークによって呼び出されます。
構文
PIBIO_STORAGE_DELETE_RECORD_FN PibioStorageDeleteRecordFn;
HRESULT PibioStorageDeleteRecordFn(
[in, out] PWINBIO_PIPELINE Pipeline,
[in] PWINBIO_IDENTITY Identity,
[in] WINBIO_BIOMETRIC_SUBTYPE SubFactor
)
{...}
パラメーター
[in, out] Pipeline
操作を実行する生体認証ユニットに関連付けられている WINBIO_PIPELINE 構造体へのポインター。
[in] Identity
削除するテンプレートの GUID または SID を含む WINBIO_IDENTITY 構造体へのポインター。
[in] SubFactor
削除するテンプレートに関連付けられているサブ要素を指定する WINBIO_BIOMETRIC_SUBTYPE 値。
戻り値
関数が成功した場合は、S_OK を返します。 関数が失敗した場合は、エラーを示すために次のいずれかの HRESULT 値を返す必要があります。
リターン コード | 説明 |
---|---|
|
SubFactor パラメーターで指定された引数が無効であるか、Identity パラメーターで指定された構造体のメンバーが無効です。 |
|
レコード ヘッダーにメモリを割り当てませんでした。 |
|
必須のポインター引数は NULL です。 |
|
データベースに未指定の問題があります。 |
|
データベースに一致するレコードが見つかりませんでした。 |
|
パイプライン オブジェクトの StorageContext メンバーが NULL であるか、 FileHandle メンバーが無効です。 |
注釈
Identity パラメーターが指すWINBIO_IDENTITY構造体の Type フィールドが WINBIO_IDENTITY_TYPE_WILDCARD に設定され、SubFactor パラメーターが WINBIO_SUBTYPE_ANY に等しい場合、ストレージ アダプターはデータベースからすべてのレコードを削除する必要があります。
SubFactor パラメーターに指定された値の検証を試みないでください。 Windows 生体認証サービスは、指定された値を実装に渡す前に検証します。 値が WINBIO_SUBTYPE_NO_INFORMATION または WINBIO_SUBTYPE_ANY場合は、必要に応じて検証します。
例
次の擬似コードは、この関数の 1 つの可能な実装を示しています。 この例はコンパイルされません。 目的に合わせて調整する必要があります。
/////////////////////////////////////////////////////////////////////////////////////////
//
// StorageAdapterDeleteRecord
//
// Purpose:
// Deletes one or more templates from the database.
//
// Parameters:
// Pipeline - Pointer to a WINBIO_PIPELINE structure associated with
// the biometric unit performing the operation.
// Identity - Pointer to a WINBIO_IDENTITY structure that contains the GUID or
// SID of the template to delete.
// SubFactor - A WINBIO_BIOMETRIC_SUBTYPE value that specifies the sub-factor
// associated with the template to delete.
//
static HRESULT
WINAPI
StorageAdapterDeleteRecord(
__inout PWINBIO_PIPELINE Pipeline,
__in PWINBIO_IDENTITY Identity,
__in WINBIO_BIOMETRIC_SUBTYPE SubFactor
)
{
HRESULT hr = S_OK;
BOOL lockAcquired = FALSE;
struct _MY_ADAPTER_FILE_HEADER fileHeader = {0};
SIZE_T remainingRecords = 0;
LARGE_INTEGER currentRecordOffset = {0};
struct _MY_ADAPTER_RECORD_HEADER *recordHeader = NULL;
SIZE_T recordHeaderSize = 0;
struct _MY_ADAPTER_DPAPI_DATA protectedData = {0};
SIZE_T deletedRecordCount = 0;
// Check that pointer arguments are not NULL.
if (!ARGUMENT_PRESENT(Pipeline) ||
!ARGUMENT_PRESENT(Identity))
{
hr = E_POINTER;
goto cleanup;
}
// Retrieve the context from the pipeline.
PWINBIO_STORAGE_CONTEXT storageContext = (PWINBIO_STORAGE_CONTEXT)Pipeline->StorageContext;
// Verify the pipeline state.
if (storageContext == NULL || storageContext->FileHandle == INVALID_HANDLE_VALUE)
{
hr = WINBIO_E_INVALID_DEVICE_STATE;
goto cleanup;
}
// Check the identity type.
if (Identity->Type != WINBIO_ID_TYPE_GUID &&
Identity->Type != WINBIO_ID_TYPE_SID &&
Identity->Type != WINBIO_ID_TYPE_WILDCARD)
{
hr = E_INVALIDARG;
goto cleanup;
}
if (Identity->Type == WINBIO_ID_TYPE_WILDCARD &&
Identity->Value.Wildcard != WINBIO_IDENTITY_WILDCARD)
{
hr = E_INVALIDARG;
goto cleanup;
}
// Some kind of sub-factor information is mandatory, even if it's
// just a wildcard.
if (SubFactor == WINBIO_SUBTYPE_NO_INFORMATION)
{
hr = E_INVALIDARG;
goto cleanup;
}
// Lock the database for writing (EXCLUSIVE ownership).
hr = _LockDatabase( Pipeline->StorageHandle, TRUE);
if (FAILED(hr))
{
goto cleanup;
}
lockAcquired = TRUE;
// Read the database header block into memory.
hr = _ReadFileHeader( Pipeline->StorageHandle, &fileHeader );
if (FAILED(hr))
{
goto cleanup;
}
// For this operation, you need to update only the record header
// area, not the index vector area.
recordHeaderSize = sizeof(struct _MY_ADAPTER_RECORD_HEADER);
recordHeader = (struct _MY_ADAPTER_RECORD_HEADER*)_AdapterAlloc( recordHeaderSize );
if (recordHeader == NULL)
{
hr = E_OUTOFMEMORY;
goto cleanup;
}
currentRecordOffset = _MY_ADAPTER_FIRST_RECORD_OFFSET;
remainingRecords = fileHeader.TotalRecordCount;
// Scan through all records looking for identity matches.
while (remainingRecords > 0)
{
SIZE_T recordSize = 0;
BOOLEAN match = FALSE;
hr = _ReadRecordHeader(
Pipeline->StorageHandle,
currentRecordOffset,
recordHeader,
recordHeaderSize
);
if (FAILED(hr))
{
goto cleanup;
}
recordSize = recordHeader->RecordSize;
// Ignore records already marked for deletion.
if ((recordHeader->Flags & _MY_ADAPTER_FLAG_RECORD_DELETED) == 0)
{
hr = _MatchIdentity(
Identity,
SubFactor,
&recordHeader->Identity,
recordHeader->SubFactor,
&match
);
if (FAILED(hr))
{
goto cleanup;
}
if (match == TRUE)
{
// Mark the record as deleted and call a custom function
// (_WriteRecordHeader) to write the record header to disk. Space
// occupied by deleted records should be reclaimed when the last
// thread that is using the database closes the file. Delaying
// reclamation until the last thread closes is necessary because
// there could be other threads whose result sets contain references
// to the deleted records.
recordHeader->Flags |= _MY_ADAPTER_FLAG_RECORD_DELETED;
hr = _WriteRecordHeader(
Pipeline->StorageHandle,
currentRecordOffset,
recordHeader,
recordHeaderSize
);
if (FAILED(hr))
{
goto cleanup;
}
++fileHeader.DeletedRecordCount;
++deletedRecordCount;
}
}
currentRecordOffset.QuadPart += recordSize;
--remainingRecords;
}
// Write the updated file header to disk.
hr = _WriteFileHeader(
Pipeline->StorageHandle,
&fileHeader
);
if (FAILED(hr))
{
hr = WINBIO_E_DATABASE_CORRUPTED;
goto cleanup;
}
// Recompute the file hash and write it to the protected data area.
hr = _ReadProtectedData(
Pipeline->StorageHandle,
&protectedData
);
if (FAILED(hr))
{
goto cleanup;
}
hr = _ComputeFileHash(
Pipeline->StorageHandle,
_MY_ADAPTER_DPAPI_BLOCK_OFFSET,
(SIZE_T)(fileHeader.FirstFreeByte.QuadPart -
_MY_ADAPTER_DPAPI_BLOCK_SIZE),
protectedData.FileHash,
_MY_ADAPTER_FILE_HASH_LENGTH,
(PSIZE_T)&protectedData.FileHashLength
);
if (FAILED(hr))
{
hr = WINBIO_E_DATABASE_CORRUPTED;
goto cleanup;
}
hr = _WriteProtectedData(
Pipeline->StorageHandle,
&protectedData
);
if (FAILED(hr))
{
hr = WINBIO_E_DATABASE_CORRUPTED;
goto cleanup;
}
cleanup:
// Call the SecureZeroMemory function to overwrite the template encryption key
// on the stack.
SecureZeroMemory( &protectedData, sizeof(struct _MY_ADAPTER_DPAPI_DATA));
if (recordHeader != NULL)
{
_AdapterRelease(recordHeader);
recordHeader = NULL;
}
if (lockAcquired == TRUE)
{
_UnlockDatabase( Pipeline->StorageHandle);
lockAcquired = FALSE;
}
if (SUCCEEDED(hr))
{
if (deletedRecordCount == 0)
{
hr = WINBIO_E_DATABASE_NO_SUCH_RECORD;
}
}
return hr;
}
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows 7 [デスクトップ アプリのみ] |
サポートされている最小のサーバー | Windows Server 2008 R2 [デスクトップ アプリのみ] |
対象プラットフォーム | Windows |
ヘッダー | winbio_adapter.h (Winbio_adapter.h を含む) |
こちらもご覧ください
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示