PIBIO_STORAGE_DELETE_RECORD_FN回调函数 (winbio_adapter.h)
由 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,则根据需要进行验证。
示例
以下伪代码显示了此函数的一种可能实现。 该示例不编译。 必须根据自己的目的调整它。
/////////////////////////////////////////////////////////////////////////////////////////
//
// 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 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈