Пользовательский интерфейс SmartCardCredentialsProvider.dll не принимает пользовательский ввод

Моя компания занимается программированием для настройки безопасности SmartCard в Windows. Однако мы попали в ловушку, когда обновились до Fall Creators, которые разработчик смог смягчить, не передав родительское окно в CredUIPromptForWindowsCredentialsW() функция (рабочий стол / root / NULL). Если мы пропустим родительское окно, это приведет к тому, что диалоговое окно "Вход в смарт-карту" станет недоступным, так как всплывающее окно откроется, но при нажатии на него будет слышен звуковой сигнал окна по умолчанию, и вы ничего не сможете набрать. Я посмотрел с помощью Spy++, и он утверждает, что нет никакого дочернего окна, которое мешает, но есть сообщения, попадающие в окно, которое может видеть Spy++ (WM_SETCURSOR, WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP и куча зарегистрированных SHELLHOOK с различными параметрами).

Приложение написано с использованием инфраструктуры MFC MBCS, если это имеет значение.

Вот что я пробовал:

  1. Отображение родительского окна (в данный момент скрыто). Это иногда работает, когда я использую ::ShowWindow(m_Parent, SW_SHOW); но никогда не работает, когда я использую ::SetWindowPos(m_Parent, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
  2. Я пытался обойти функции создания сообщений и потоков, пытаясь записать, что происходит, но, похоже, я не получил никакой информации.

Я действительно почесал голову от этого. Почему окно входа в систему Smart Card не получает фокус? Что может мешать этому? Нам нужно прекратить использовать этот обходной путь и фактически получить логин смарт-карты, чтобы иметь родительское окно.

Некоторые вещи, которые я нашел в окне "Отладочный вывод":

Exception thrown at 0x763008F2 in app.exe: Microsoft C++ exception: errorlib::specific_error_exception<hresult_error::tag> at memory location 0x3B74F824.
Exception thrown at 0x763008F2 in app.exe: Microsoft C++ exception: errorlib::specific_error_exception<hresult_error::tag> at memory location 0x3B74F824.

Exception thrown at 0x763008F2 in app.exe: Microsoft C++ exception: errorlib::specific_error_exception<hresult_error::tag> at memory location 0x3B74F8E4.
Exception thrown at 0x763008F2 in app.exe: Microsoft C++ exception: errorlib::specific_error_exception<hresult_error::tag> at memory location 0x3B74F8C8.

onecoreuap\ds\security\fido\credprov\dll\fidoscenariocredui.cpp(44)\fidocredprov.dll!3C8CD0D9: (caller: 3C8CB529) ReturnHr(1) tid(5488) 80070057 The parameter is incorrect.
    Msg:[InvalidFlags 32] 
onecoreuap\ds\security\fido\credprov\dll\fidoprovider.cpp(62)\fidocredprov.dll!3C8CB540: (caller: 27886879) ReturnHr(2) tid(5488) 80070057 The parameter is incorrect.

onecore\ds\security\biometrics\credprov\provider_v2\bioprovider.cpp(99)\BioCredProv.dll!3CDC9620: (caller: 27886879) ReturnHr(1) tid(5488) 80098003     CallContext:[\SetUsageScenario] 
onecore\ds\security\biometrics\credprov\provider_v2\bioprovider.cpp(206)\BioCredProv.dll!3CDC9117: (caller: 27886ECF) ReturnHr(2) tid(5488) 80004001 Not implemented
    CallContext:[\UnAdvise] 

onecoreuap\shell\auth\credprov2fahelper\dll\credprov2fahelper.cpp(80)\CredProv2faHelper.dll!2B0F63E5: (caller: 278870A4) ReturnHr(1) tid(5488) 800704EC This program is blocked by group policy. For more information, contact your system administrator.
    Msg:[Device unlock policy not configured] 
onecore\ds\security\ngc\utils\common\lib\sidutils.cpp(786)\ngccredprov.dll!3CE59F69: (caller: 3CE58CA0) ReturnHr(1) tid(5488) 80070057 The parameter is incorrect.
Exception thrown at 0x763008F2 (KernelBase.dll) in app.exe: 0x0000071A: The remote procedure call was canceled, or if a call time-out was specified, the call timed out.
Exception thrown at 0x763008F2 (KernelBase.dll) in app.exe: 0x0000071A: The remote procedure call was canceled, or if a call time-out was specified, the call timed out.

Exception thrown at 0x763008F2 (KernelBase.dll) in app.exe: 0x0000071A: The remote procedure call was canceled, or if a call time-out was specified, the call timed out.
Exception thrown at 0x763008F2 in app.exe: Microsoft C++ exception: unsigned long at memory location 0x3B74F194.

Хотя они появляются, когда родителем является root (рабочий стол) или наше окно, поэтому я не уверен, что они что-то значат.

РЕДАКТИРОВАТЬ

Вот код (более или менее), который используется для вызова диалогового окна Smart Card:

CREDUI_INFOW credUIInfo;
memset(&credUIInfo, 0, sizeof(credUIInfo));
credUIInfo.cbSize = sizeof(credUIInfo);
credUIInfo.hwndParent = m_Parent;
credUIInfo.pszCaptionText = L"Smart Card Login";
ULONG ulAuthPackageID = 0;

HANDLE hLSA = NULL;
DWORD dwErr = LsaNtStatusToWinError(LsaConnectUntrusted(&hLSA));
if (dwErr == ERROR_SUCCESS) {
    LSA_STRING lsaszAuthPackageName;
    SizeTToUShort(strlen("Negotiate"), &lsaszAuthPackageName.Length);
    lsaszAuthPackageName.MaximumLength = lsaszAuthPackageName.Length + sizeof(CHAR);
    lsaszAuthPackageName.Buffer = (PCHAR)"Negotiate";

    dwErr = LsaNtStatusToWinError(LsaLookupAuthenticationPackage(hLSA, &lsaszAuthPackageName, &ulAuthPackageID));
}

// Disconnect from the LSA server:
if (hLSA) {LsaDeregisterLogonProcess(hLSA);}

KERB_CERTIFICATE_LOGON credFilter;
memset(&credFilter, 0, sizeof(credFilter));
credFilter.MessageType = KerbCertificateLogon; // (indicates an interactive smart card certificate login)

LPVOID pCredBuffer = NULL;
DWORD dwCredLen = 0;

dwErr = CredUIPromptForWindowsCredentialsW(&credUIInfo, dwErr, &ulAuthPackageID, &credFilter, sizeof(credFilter), &pCredBuffer, &dwCredLen, NULL, CREDUIWIN_IN_CRED_ONLY);

РЕДАКТИРОВАТЬ 2

Похоже, что диалог отключен в соответствии с Spy++. Написание быстрого небольшого приложения, которое с учетом любого дескриптора окна включит окно, связанное с этим дескриптором, вызвав EnableWindow() фактически включит окно. Почему это так? Почему окно будет отключено?

1 ответ

Обойти эту проблему, которая, на мой взгляд, лучше, чем не устанавливать родителя, - опросить диалоговое окно безопасности, и когда оно станет видимым, но оно все еще не включено, включите его.

constexpr UINT_PTR enable_window_id = 0;
::SetTimer(m_Parent, enable_window_id, 100, [](HWND hwnd, UINT /*msg*/, UINT_PTR id, DWORD /*dwTime*/)
{
    if (HWND hChild = ::FindWindow(_T("Credential Dialog Xaml Host"), nullptr))
    {
        if (::IsWindowVisible(hChild) && !::IsWindowEnabled(hChild))
        {
            ::EnableWindow(hChild, TRUE);
            ::KillTimer(hwnd, id);
        }
    }
});

//...
// CredUIPromptForWindowsCredentials(...) call
//...

// If MS ever fixes this problem, will need to kill this timer manually
::KillTimer(m_Parent, enable_window_id);

Я лично думаю, что это действительно глупо, но кто знает, когда MS это исправит.

Другие вопросы по тегам