【WBF】非同期で生体認証ユニットのIDを取得する

# 使用するWindows Biometric Frameworkの関数
- 非同期でWindows Biometric Frameworkを使用するためののハンドル処理
  -  WinBioAsyncOpenSession: ハンドルの取得<br>
     https://docs.microsoft.com/en-us/windows/win32/api/winbio/nf-winbio-winbioasyncopensession
  - WinBioCloseSession: ハンドルの破棄<br>
    https://docs.microsoft.com/en-us/windows/win32/api/winbio/nf-winbio-winbioclosesession

- ユニットIDを取得するための関数
  - WinBioLocateSensor<br>
    https://docs.microsoft.com/en-us/windows/win32/api/winbio/nf-winbio-winbiolocatesensor

- 取得した結果のメモリの解放
  - WinBioFree<br>
    https://docs.microsoft.com/en-us/windows/win32/api/winbio/nf-winbio-winbiofree

# サンプルコード
```C++
// ====================================================================================================
//  インクルード
// ====================================================================================================
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <WinBio.h>
#include <locale.h>

// ====================================================================================================
//  ライブラリ
// ====================================================================================================
#pragma comment(lib, "WinBio.lib")

// ====================================================================================================
//  コールバック関数
// ====================================================================================================
void CALLBACK WINBIO_ASYNC_COMPLETION_CALLBACK(PWINBIO_ASYNC_RESULT AsyncResult)
{
    // 結果出力
    wprintf_s(L"Operation Type [%d]\n", AsyncResult->Operation);
    wprintf_s(L"Sequence Number [%lld]\n", AsyncResult->SequenceNumber);

    FILETIME stFileTime;
    stFileTime.dwHighDateTime = (DWORD)(AsyncResult->TimeStamp >> 32);
    stFileTime.dwLowDateTime = (DWORD)(AsyncResult->TimeStamp & 0xFFFFFFFF);

    SYSTEMTIME stSystemTime;
    FileTimeToSystemTime(&stFileTime, &stSystemTime);

    wprintf_s(L"Time Stamp [%d/%02d/%02d(%d) %02d:%02d:%02d.%03d]\n", 
        stSystemTime.wYear, stSystemTime.wMonth, stSystemTime.wDay, stSystemTime.wDayOfWeek,
        stSystemTime.wHour, stSystemTime.wMinute, stSystemTime.wSecond, stSystemTime.wMilliseconds);

    wprintf_s(L"API Status [0x%08X]\n", AsyncResult->ApiStatus);
    wprintf_s(L"Unit ID [%d]\n", AsyncResult->UnitId);

    // WINBIO_ASYNC_RESULT構造体の解放
    WinBioFree(AsyncResult);
}

// ====================================================================================================
//  エントリーポイント
// ====================================================================================================
int main()
{
    HRESULT hr = S_OK;
    WINBIO_SESSION_HANDLE SessionHandle = NULL;

    try
    {
        // 標準出力に日本語を出力できるようにする
        setlocale(LC_ALL, "Japanese");

        // 指紋認証サービスプロバイダーに非同期で接続
        hr = WinBioAsyncOpenSession(
            WINBIO_TYPE_FINGERPRINT, 
            WINBIO_POOL_SYSTEM, 
            WINBIO_FLAG_DEFAULT, 
            NULL, 
            0, 
            WINBIO_DB_DEFAULT, 
            WINBIO_ASYNC_NOTIFY_CALLBACK, 
            NULL, 
            0,
            WINBIO_ASYNC_COMPLETION_CALLBACK,
            NULL,
            FALSE,
            &SessionHandle
        );
        if (FAILED(hr))
        {
            wprintf_s(L"WinBioAsyncOpenSession failed. hr = 0x%x\n", hr);
            throw hr;
        }

        // ユーザーがタッチorスワイプした指紋センサーのユニットIDを取得する
        hr = WinBioLocateSensor(SessionHandle, NULL);
        if (FAILED(hr))
        {
            wprintf_s(L"WinBioLocateSensor failed. hr = 0x%x\n", hr);
            throw hr;
        }

        wprintf_s(L"ユニットIDを取得したい指紋センサーをタッチorスワイプしてください。\n");
    }
    catch (HRESULT hrError) { hr = hrError; }
    catch (...) { hr = E_UNEXPECTED; }

    // ユーザーの入力待ち
    _getch();

    // セッションを閉じる
    if (SessionHandle != NULL)
        WinBioCloseSession(SessionHandle);

    return 0;
}
```
上記コードを実行し、何かキーを押す前に指紋センサーをタッチorスワイプすると、コールバック関数が呼ばれます。