fungsi panggilan balik PIBIO_STORAGE_DELETE_RECORD_FN (winbio_adapter.h)
Dipanggil oleh Windows Biometric Framework untuk menghapus satu atau beberapa templat dari database.
Sintaks
PIBIO_STORAGE_DELETE_RECORD_FN PibioStorageDeleteRecordFn;
HRESULT PibioStorageDeleteRecordFn(
[in, out] PWINBIO_PIPELINE Pipeline,
[in] PWINBIO_IDENTITY Identity,
[in] WINBIO_BIOMETRIC_SUBTYPE SubFactor
)
{...}
Parameter
[in, out] Pipeline
Arahkan ke struktur WINBIO_PIPELINE yang terkait dengan unit biometrik yang melakukan operasi.
[in] Identity
Penunjuk ke struktur WINBIO_IDENTITY yang berisi GUID atau SID templat yang akan dihapus.
[in] SubFactor
Nilai WINBIO_BIOMETRIC_SUBTYPE yang menentukan subfaktor yang terkait dengan templat yang akan dihapus.
Mengembalikan nilai
Jika fungsi berhasil, fungsi akan mengembalikan S_OK. Jika fungsi gagal, fungsi harus mengembalikan salah satu nilai HRESULT berikut untuk menunjukkan kesalahan.
Menampilkan kode | Deskripsi |
---|---|
|
Argumen yang ditentukan oleh parameter SubFactor tidak valid atau anggota struktur yang ditentukan oleh parameter Identitas tidak valid. |
|
Memori tidak dapat dialokasikan untuk header rekaman. |
|
Argumen pointer wajib adalah NULL. |
|
Ada masalah yang tidak ditentukan dengan database. |
|
Tidak ada rekaman yang cocok yang dapat ditemukan dalam database. |
|
Anggota StorageContext dari objek alur adalah NULL atau anggota FileHandle tidak valid. |
Keterangan
Jika bidang Jenis struktur WINBIO_IDENTITY yang ditunjukkan oleh parameter Identitas diatur ke WINBIO_IDENTITY_TYPE_WILDCARD dan parameter SubFactor sama dengan WINBIO_SUBTYPE_ANY, adaptor penyimpanan harus menghapus semua rekaman dari database.
Jangan mencoba memvalidasi nilai yang disediakan untuk parameter SubFactor . Layanan Biometrik Windows akan memvalidasi nilai yang disediakan sebelum meneruskannya ke implementasi Anda. Jika nilainya WINBIO_SUBTYPE_NO_INFORMATION atau WINBIO_SUBTYPE_ANY, validasi jika sesuai.
Contoh
Pseudocode berikut menunjukkan satu kemungkinan implementasi fungsi ini. Contoh tidak dikompilasi. Anda harus menyesuaikannya agar sesuai dengan tujuan Anda.
/////////////////////////////////////////////////////////////////////////////////////////
//
// 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;
}
Persyaratan
Persyaratan | Nilai |
---|---|
Klien minimum yang didukung | Windows 7 [hanya aplikasi desktop] |
Server minimum yang didukung | Windows Server 2008 R2 [hanya aplikasi desktop] |
Target Platform | Windows |
Header | winbio_adapter.h (termasuk Winbio_adapter.h) |
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk