Private Pool Enrollment

The following sections contain the code necessary for private sensor pool enrollment.

Targetver.h

This sample was created for Windows 7 and later operating systems.

#pragma once
#ifndef _WIN32_WINNT            
#define _WIN32_WINNT NTDDI_WIN7 
#endif

Stdafx.h

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently but
// are changed infrequently
//

#pragma once

#include "targetver.h"

// Use secure (template) versions of nonsecure 
// CRT text routines
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES     1

#include <stdio.h>
#include <tchar.h>

#include <windows.h>
#include <winbio.h>

#include "BioHelper.h"

#ifndef ARGUMENT_PRESENT
#define ARGUMENT_PRESENT(x) (((x) != NULL))
#endif

PrivatePoolEnroll.cpp

/******************************************************************************
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) Microsoft.  All rights reserved.

This source code is only intended as a supplement to Microsoft Development
Tools and/or WinHelp documentation.  See these sources for detailed information
regarding the Microsoft samples programs.
******************************************************************************/

// PrivatePoolEnroll.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "PrivatePoolCommonDefs.h"   // From Private Pool Setup
#include "Strsafe.h"                 // For StringCbGets()


//
// Forward declarations of local functions...
//
static void onEnrollOrPractice(
    __in bool CommitEnrollment
    );

static bool selectSensorMenu(
    __in LPCTSTR Prompt,
    __in WINBIO_UNIT_SCHEMA *UnitArray,
    __in SIZE_T UnitCount,
    __out SIZE_T *SelectedUnit
    );

static bool selectSubFactorMenu(
    __out PWINBIO_BIOMETRIC_SUBTYPE SubFactor
    );

static bool getUlongValue(
    __out PULONG Value
    );

static void displayIdentity(
    __in PWINBIO_IDENTITY Identity,
    __in WINBIO_BIOMETRIC_SUBTYPE SubFactor
    );
//-----------------------------------------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
    _tprintf( _T("\nWinBio Private Pool Enrollment\n\n"));

    if (argc < 2)
    {
        _tprintf(_T("Usage: %s -enroll | -practice\n"), argv[0]);
        _tprintf(
            _T("\n")
            _T("  -enroll       create enrollment for a new finger\n")
            _T("  -practice     perform enrollment, but discard results\n")
            _T("\n")
            );
    }
    else
    {
        if (_tcsicmp( argv[1], _T("-enroll")) == 0)
        {
            onEnrollOrPractice(true);
        }
        else if (_tcsicmp( argv[1], _T("-practice")) == 0)
        {
            onEnrollOrPractice(false);
        }
        else
        {
            _tprintf(_T("*** Error - Unknown command option: %s\n"), argv[1]);
        }
    }

    return 0;
}
//-----------------------------------------------------------------------------

static void onEnrollOrPractice(
    __in bool CommitEnrollment
    )
{
    WINBIO_UNIT_ID unitIdArray[1] = {};
    SIZE_T unitIdCount = ARRAYSIZE(unitIdArray);

    WINBIO_UNIT_SCHEMA *unitSchemaArray = NULL;
    SIZE_T unitSchemaCount = 0;
    HRESULT hr = WinBioEnumBiometricUnits( 
                    WINBIO_TYPE_FINGERPRINT, 
                    &unitSchemaArray, 
                    &unitSchemaCount 
                    );
    if (SUCCEEDED(hr))
    {
        SIZE_T selectedUnit = 0;
        if (selectSensorMenu( 
                _T("Choose a sensor for the private pool"), 
                unitSchemaArray, 
                unitSchemaCount, 
                &selectedUnit
                ))
        {
            // Build the array of Unit IDs that will make
            // up the private pool
            unitIdArray[0] = unitSchemaArray[selectedUnit].UnitId;
            unitIdCount = 1;
        }
        else
        {
            hr = E_INVALIDARG;
        }
        WinBioFree( unitSchemaArray );
        unitSchemaArray = NULL;
        unitSchemaCount = 0;
    }
    if (SUCCEEDED(hr))
    {
        WINBIO_UUID privateDatabaseId = PRIVATE_POOL_DATABASE_ID;
        WINBIO_SESSION_HANDLE sessionHandle = NULL;
        hr = WinBioOpenSession( 
                WINBIO_TYPE_FINGERPRINT, 
                WINBIO_POOL_PRIVATE, 
                WINBIO_FLAG_BASIC, 
                unitIdArray, 
                unitIdCount, 
                &privateDatabaseId, 
                &sessionHandle 
                );
        if (SUCCEEDED(hr))
        {
            WINBIO_BIOMETRIC_SUBTYPE subFactor = WINBIO_SUBTYPE_NO_INFORMATION;
            if (selectSubFactorMenu( &subFactor ) &&
                subFactor != WINBIO_SUBTYPE_NO_INFORMATION &&
                subFactor != WINBIO_SUBTYPE_ANY)
            {
                //
                // Locate sensor
                //
                _tprintf(_T("\nTap the sensor once when you're ready to begin enrolling...\n\n"));
                WINBIO_UNIT_ID unitId = 0;
                hr = WinBioLocateSensor( sessionHandle, &unitId);
                if (SUCCEEDED(hr))
                {
                    //
                    // Enroll begin
                    //
                    _tprintf(_T("\n(Begining enrollment sequence)\n\n"));
                    hr = WinBioEnrollBegin(
                            sessionHandle,
                            subFactor,
                            unitId
                            );
                    if (SUCCEEDED(hr))
                    {
                        SIZE_T swipeCount = 0;
                        for (swipeCount = 1;; ++swipeCount)
                        {
                            _tprintf(
                                _T("Swipe your finger on the sensor to capture %s sample.\n"),
                                (swipeCount == 1)?_T("the first"):_T("another")
                                );

                            WINBIO_REJECT_DETAIL rejectDetail = 0;
                            hr = WinBioEnrollCapture(
                                    sessionHandle,
                                    &rejectDetail
                                    );
                            _tprintf(_T("   Sample %d captured from unit number %d.\n"), swipeCount, unitId);
                            if (hr == WINBIO_I_MORE_DATA)
                            {
                                _tprintf(_T("   More data required.\n\n"));
                                continue;
                            }
                            if (FAILED(hr))
                            {
                                if (hr == WINBIO_E_BAD_CAPTURE)
                                {
                                    _tprintf(_T("*** Error - Bad capture.\n"));
                                    _tprintf(
                                        _T("- %s\n"), 
                                        BioHelper::ConvertRejectDetailToString( rejectDetail )
                                        );
                                    hr = S_OK;
                                    continue;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                _tprintf(_T("   Template completed.\n\n"));
                                break;
                            }
                        }
                        _tprintf(_T("\n"));
                        if (SUCCEEDED(hr))
                        {
                            if (CommitEnrollment)
                            {
                                // ENROLL
                                WINBIO_IDENTITY identity = {};
                                BOOLEAN isNewTemplate = FALSE;

                                _tprintf(_T("Committing enrollment...\n"));
                                hr = WinBioEnrollCommit( sessionHandle, &identity, &isNewTemplate);
                                if (SUCCEEDED(hr))
                                {
                                    _tprintf(_T("Enrollment committed to database\n"));
                                    displayIdentity( &identity, subFactor );
                                }
                            }
                            else
                            {
                                // PRACTICE
                                _tprintf(_T("Discarding enrollment...\n"));
                                hr = WinBioEnrollDiscard( sessionHandle );
                                if (SUCCEEDED(hr))
                                {
                                    _tprintf(_T("Template discarded.\n"));
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                hr = E_INVALIDARG;
            }

            WinBioCloseSession( sessionHandle );
            sessionHandle = NULL;
        }
    }

    if (FAILED(hr))
    {
        LPTSTR errorMessage = BioHelper::ConvertErrorCodeToString( hr );
        _tprintf(_T("*** Error - %s\n"), errorMessage );
        LocalFree(errorMessage);
        errorMessage = NULL;
    }
}
//-----------------------------------------------------------------------------

static bool selectSensorMenu(
    __in LPCTSTR Prompt,
    __in WINBIO_UNIT_SCHEMA *UnitArray,
    __in SIZE_T UnitCount,
    __out SIZE_T *SelectedUnit
    )
{
    if (!ARGUMENT_PRESENT(UnitArray) ||
        !ARGUMENT_PRESENT(SelectedUnit) ||
        UnitCount == 0)
    {
        return false;
    }

    _tprintf(_T("\n%s:\n\n"), Prompt);
    for (SIZE_T i = 0; i < UnitCount; ++i)
    {
        _tprintf(
            _T(" %3d - %ls (%ls)\n"), 
            (i + 1), 
            UnitArray[i].Manufacturer, 
            UnitArray[i].Description 
            );
    }

    _tprintf(_T("\nSelect sensor and press <ENTER>: "));
    TCHAR buffer[20] = {};
    HRESULT hr = StringCbGets( buffer, 20*sizeof(TCHAR) );
    _tprintf(_T("\n"));

    int selected = _tstoi( buffer );
    if (selected <= 0 ||
        selected > (int)UnitCount)
    {
        return false;
    }
    *SelectedUnit = (SIZE_T)(selected - 1);
    return true;
}
//-----------------------------------------------------------------------------

static bool selectSubFactorMenu(
    __out PWINBIO_BIOMETRIC_SUBTYPE SubFactor
    )
{
    static const WINBIO_BIOMETRIC_SUBTYPE subFactors[] = {
        WINBIO_ANSI_381_POS_RH_THUMB,
        WINBIO_ANSI_381_POS_RH_INDEX_FINGER,
        WINBIO_ANSI_381_POS_RH_MIDDLE_FINGER,
        WINBIO_ANSI_381_POS_RH_RING_FINGER,
        WINBIO_ANSI_381_POS_RH_LITTLE_FINGER,
        WINBIO_ANSI_381_POS_LH_THUMB,
        WINBIO_ANSI_381_POS_LH_INDEX_FINGER,
        WINBIO_ANSI_381_POS_LH_MIDDLE_FINGER,
        WINBIO_ANSI_381_POS_LH_RING_FINGER,
        WINBIO_ANSI_381_POS_LH_LITTLE_FINGER,
    };
    _tprintf(_T("\n- Select a sub-factor:\n\n"));

    for (SIZE_T index = 0; index < ARRAYSIZE(subFactors); ++index)
    {
        _tprintf(
            _T("    %2d - %s\n"),
            (index + 1),
            BioHelper::ConvertSubFactorToString( subFactors[index] )
            );
    }

    ULONG chosen = 0;
    if (getUlongValue( &chosen ) &&
        (chosen - 1) < ARRAYSIZE(subFactors))
    {
        *SubFactor = subFactors[chosen - 1];
        return true;
    }
    return false;
}
//-----------------------------------------------------------------------------

static bool getUlongValue(
    __out PULONG Value
    )
{
    ULONG value = 0;

    _tprintf( _T("\n- Enter a number: "));
    if (_tscanf_s(_T("%u"), &value) != 0)
    {
        *Value = value;
        return true;
    }
    return false;
}
//-----------------------------------------------------------------------------

static void displayIdentity(
    __in PWINBIO_IDENTITY Identity,
    __in WINBIO_BIOMETRIC_SUBTYPE SubFactor
    )
{
    _tprintf(_T("\n- Identity: "));
    switch (Identity->Type)
    {
    case WINBIO_ID_TYPE_NULL:
        _tprintf(_T("NULL value\n"));
        break;

    case WINBIO_ID_TYPE_WILDCARD:
        _tprintf(_T("WILDCARD value\n"));
        if (Identity->Value.Wildcard != WINBIO_IDENTITY_WILDCARD)
        {
            _tprintf(
                _T("\n*** Error: Invalid wildcard marker (0x%08x)\n"), 
                Identity->Value.Wildcard
                );
        }
        break;

    case WINBIO_ID_TYPE_GUID:
        _tprintf(_T("GUID\n"));
        _tprintf(
            _T("    Value:      {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n"),
            Identity->Value.TemplateGuid.Data1,
            Identity->Value.TemplateGuid.Data2,
            Identity->Value.TemplateGuid.Data3,
            Identity->Value.TemplateGuid.Data4[0],
            Identity->Value.TemplateGuid.Data4[1],
            Identity->Value.TemplateGuid.Data4[2],
            Identity->Value.TemplateGuid.Data4[3],
            Identity->Value.TemplateGuid.Data4[4],
            Identity->Value.TemplateGuid.Data4[5],
            Identity->Value.TemplateGuid.Data4[6],
            Identity->Value.TemplateGuid.Data4[7]
            );
        break;

    default:
        _tprintf(_T("(Invalid type)\n"));
        // invalid type
        break;
    }
    _tprintf(
        _T("    Subfactor:  %s\n"), 
        BioHelper::ConvertSubFactorToString(SubFactor)
        );
}
//-----------------------------------------------------------------------------