PIBIO_STORAGE_ADD_RECORD_FN Rückruffunktion (winbio_adapter.h)
Wird vom Engine-Adapter aufgerufen, um der Datenbank eine Vorlage hinzuzufügen.
Syntax
PIBIO_STORAGE_ADD_RECORD_FN PibioStorageAddRecordFn;
HRESULT PibioStorageAddRecordFn(
[in, out] PWINBIO_PIPELINE Pipeline,
[in] PWINBIO_STORAGE_RECORD RecordContents
)
{...}
Parameter
[in, out] Pipeline
Zeiger auf die WINBIO_PIPELINE Struktur, die der biometrischen Einheit zugeordnet ist, die den Vorgang ausführt.
[in] RecordContents
Zeiger auf eine WINBIO_STORAGE_RECORD-Struktur , die die hinzuzufügende Vorlage enthält.
Rückgabewert
Wenn die Funktion erfolgreich ist, wird S_OK zurückgegeben. Wenn die Funktion fehlschlägt, muss sie einen der folgenden HRESULT-Werte zurückgeben, um den Fehler anzugeben.
Rückgabecode | Beschreibung |
---|---|
|
Ein Durch den RecordContents-Parameter angegebenes Element der Struktur ist ungültig. |
|
Ein obligatorisches Zeigerargument ist NULL. |
|
Die in der WINBIO_STORAGE_RECORD-Struktur angegebene Größe des Indexvektors stimmt nicht mit der Indexgröße überein, die beim Erstellen der Datenbank angegeben wurde. |
|
Die Datenbank enthält bereits eine Vorlage mit der Kombination von Werten, die durch die Parameter Identity und SubFactor angegeben werden. |
|
Es liegt ein nicht angegebenes Problem mit der Datenbank vor. |
|
Die Datenbank ist voll, und es können keine weiteren Datensätze hinzugefügt werden. |
|
Die Datenbank ist gesperrt. |
|
Fehler beim Hinzufügen von Datensätzen aufgrund eines nicht angegebenen Problems. |
|
Der StorageContext-Member des Pipelineobjekts ist NULL , oder der FileHandle-Member ist ungültig. |
Hinweise
Der durch den RecordContents-Parameter identifizierte Arbeitsspeicher ist die Eigenschaft von Windows Biometric Framework. Der Speicheradapter darf nach der Rückgabe von StorageAdapterAddRecord keine Kopie dieses Zeigers oder von zeigern, die in der WINBIO_STORAGE_RECORD-Struktur enthalten sind, beibehalten.
Versuchen Sie nicht, den für den SubFactor-Wert des RecordContents-Parameters angegebenen Wert zu überprüfen. Der Windows-Biometriedienst überprüft den angegebenen Wert, bevor er an Ihre Implementierung übergeben wird. Wenn der Wert WINBIO_SUBTYPE_NO_INFORMATION oder WINBIO_SUBTYPE_ANY ist, überprüfen Sie ggf..
Beispiele
Der folgende Pseudocode zeigt eine mögliche Implementierung dieser Funktion. Das Beispiel wird nicht kompiliert. Sie müssen es an Ihren Zweck anpassen.
/////////////////////////////////////////////////////////////////////////////////////////
//
// StorageAdapterAddRecord
//
// Purpose:
// Adds a template to the database.
//
// Parameters:
// Pipeline - Pointer to a WINBIO_PIPELINE structure associated with
// the biometric unit performing the operation.
// RecordContents - Pointer to a WINBIO_STORAGE_RECORD structure that contains
// the template to add.
//
static HRESULT
WINAPI
StorageAdapterAddRecord(
__inout PWINBIO_PIPELINE Pipeline,
__in PWINBIO_STORAGE_RECORD RecordContents
)
{
HRESULT hr = S_OK;
struct _MY_ADAPTER_RECORD_HEADER *newRecord = NULL;
SIZE_T newRecordSize = 0;
BOOL lockAcquired = FALSE;
ULONG index = 0;
PUCHAR encryptedTemplateBlob = NULL;
SIZE_T encryptedTemplateBlobSize = 0;
struct _MY_ADAPTER_FILE_HEADER fileHeader = {0};
SIZE_T templateBlobOffset = 0;
SIZE_T payloadBlobOffset = 0;
struct _MY_ADAPTER_DPAPI_DATA protectedData = {0};
SIZE_T duplicateRecordCount = 0;
// Verify that pointer arguments are not NULL.
if (!ARGUMENT_PRESENT(Pipeline) ||
!ARGUMENT_PRESENT(RecordContents))
{
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 various values associated with the record contents. The
// following example code assumes that a database record contains
// a valid:
// Identity
// Sub-factor characteristic
// Biometric template
// Payload associated with the template
// Index vector
//
if (!ARGUMENT_PRESENT(RecordContents->Identity))
{
hr = E_POINTER;
goto cleanup;
}
if (RecordContents->Identity->Type != WINBIO_ID_TYPE_GUID &&
RecordContents->Identity->Type != WINBIO_ID_TYPE_SID)
{
hr = E_INVALIDARG;
goto cleanup;
}
if (RecordContents->SubFactor == WINBIO_SUBTYPE_NO_INFORMATION ||
RecordContents->SubFactor == WINBIO_SUBTYPE_ANY)
{
hr = E_INVALIDARG;
goto cleanup;
}
if (RecordContents->TemplateBlobSize == 0 ||
!ARGUMENT_PRESENT(RecordContents->TemplateBlob))
{
hr = E_INVALIDARG;
goto cleanup;
}
if (RecordContents->PayloadBlobSize > 0 &&
!ARGUMENT_PRESENT(RecordContents->PayloadBlob))
{
hr = E_POINTER;
goto cleanup;
}
if (RecordContents->IndexElementCount != storageContext->IndexElementCount)
{
hr = WINBIO_E_DATABASE_BAD_INDEX_VECTOR;
goto cleanup;
}
if (RecordContents->IndexElementCount > 0 &&
!ARGUMENT_PRESENT(RecordContents->IndexVector))
{
hr = E_POINTER;
goto cleanup;
}
// Call a private function (_CheckForDuplicateEnrollments) to query the
// database for existing records with the same identity and sub-factor
// values as the new record. If a duplicate is found, return.
hr = _CheckForDuplicateEnrollments(
Pipeline,
RecordContents->Identity,
RecordContents->SubFactor,
&duplicateRecordCount
);
if (FAILED(hr))
{
goto cleanup;
}
if (duplicateRecordCount > 0)
{
hr = WINBIO_E_DUPLICATE_ENROLLMENT;
goto cleanup;
}
// Call a custom function (_EncryptTemplateData) to encrypt the template
// data. Do this now so that you can determine how much space will be
// required to store the encrypted template.
hr = _EncryptTemplateData(
&storageContext->CryptoContext,
RecordContents->TemplateBlob,
RecordContents->TemplateBlobSize,
&encryptedTemplateBlob,
&encryptedTemplateBlobSize
);
if (FAILED(hr))
{
hr = WINBIO_E_DATABASE_WRITE_ERROR;
goto cleanup;
}
// Call a custom function (_AllocateNewRecord) to allocate memory for the
// new record. You must allocate enough memory to hold the index vector, the
// encrypted template, the identity structure, sub-factor information, and the
// payload blob. You must also allocate enough memory to hold and any other
// data that will be used by the storage adapter but that will
// not be made visible to the engine adapter.
hr = _AllocateNewRecord(
RecordContents->IndexElementCount,
encryptedTemplateBlobSize,
RecordContents->PayloadBlobSize,
&newRecord, // [out] Address of the new record buffer
&newRecordSize // [out] Size of the new record buffer
);
if (FAILED(hr))
{
goto cleanup;
}
// Copy the identity information into the new record.
CopyMemory(
&newRecord->Identity,
RecordContents->Identity,
sizeof(WINBIO_IDENTITY)
);
// Copy the sub-factor information to the new record.
newRecord->SubFactor = RecordContents->SubFactor;
// Copy the index vector, if present, into the new record.
if (RecordContents->IndexElementCount > 0)
{
PULONG indexVector = _GetIndexVector(newRecord);
for (index=0; index < RecordContents->IndexElementCount; ++index)
{
indexVector[index] = RecordContents->IndexVector[index];
}
}
// Copy the encrypted template.
templateBlobOffset =
sizeof(struct _MY_ADAPTER_RECORD_HEADER) +
RecordContents->IndexElementCount * sizeof(ULONG);
newRecord->TemplateBlobSize = RecordContents->TemplateBlobSize;
newRecord->EncryptedTemplateBlobSize = encryptedTemplateBlobSize;
CopyMemory(
(PUCHAR)newRecord + templateBlobOffset,
encryptedTemplateBlob,
encryptedTemplateBlobSize
);
// Copy the payload blob if present.
if (RecordContents->PayloadBlobSize > 0)
{
payloadBlobOffset =
templateBlobOffset +
encryptedTemplateBlobSize;
newRecord->PayloadBlobSize = RecordContents->PayloadBlobSize;
CopyMemory(
(PUCHAR)newRecord + payloadBlobOffset,
RecordContents->PayloadBlob,
RecordContents->PayloadBlobSize
);
}
// Call a custom function (_LockDatabase) to lock the database for writing
// (EXCLUSIVE ownership).
hr = _LockDatabase(Pipeline->StorageHandle, TRUE);
if (FAILED(hr))
{
goto cleanup;
}
lockAcquired = TRUE;
// Call a custom function (_ReadFileHeader) to read the header block.
hr = _ReadFileHeader( Pipeline->StorageHandle, &fileHeader );
if (FAILED(hr))
{
goto cleanup;
}
// Write the new data record to the first free byte at the end of the
// active data area in the database file.
hr = _WriteRecord(
Pipeline->StorageHandle,
fileHeader.FirstFreeByte,
newRecord
);
if (FAILED(hr))
{
goto cleanup;
}
// Update the bookkeeping information in the header and write the header
// back to the file.
fileHeader.FirstFreeByte.QuadPart += newRecord->RecordSize;
++fileHeader.TotalRecordCount;
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 in the database
// file. The hash value is an integrity check on data stored in the file. Note that
// the DPAPI-protected data block is NOT included in the hash.
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 SecureZero function to overwrite the template encryption key
// on the stack.
SecureZeroMemory( &protectedData, sizeof(struct _MY_ADAPTER_DPAPI_DATA));
if (lockAcquired == TRUE)
{
_UnlockDatabase( Pipeline->StorageHandle);
lockAcquired = FALSE;
}
if (encryptedTemplateBlob != NULL)
{
SecureZeroMemory(encryptedTemplateBlob, encryptedTemplateBlobSize);
_AdapterRelease(encryptedTemplateBlob);
encryptedTemplateBlob = NULL;
}
if (newRecord != NULL)
{
SecureZeroMemory( newRecord, newRecordSize);
_AdapterRelease(newRecord);
newRecord = NULL;
}
return hr;
}
Anforderungen
Anforderung | Wert |
---|---|
Unterstützte Mindestversion (Client) | Windows 7 [nur Desktop-Apps] |
Unterstützte Mindestversion (Server) | Windows Server 2008 R2 [nur Desktop-Apps] |
Zielplattform | Windows |
Kopfzeile | winbio_adapter.h (Winbio_adapter.h einschließen) |
Weitere Informationen
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für