智能卡凭据提供程序.dll UI 不接受用户输入



我的公司正在为 Windows 中的智能卡安全设置编程。 但是,当我们更新到 Fall Creators 时,我们遇到了一个障碍,开发人员能够通过不将父窗口传递给CredUIPromptForWindowsCredentialsW()函数(桌面/根/NULL)来缓解这种情况。 如果我们传递父窗口,则会导致智能卡登录对话框无法访问,就像弹出窗口一样,但是当您单击它时,会听到窗口的默认哔哔声,您无法键入任何内容。 我使用 Spy++ 查看过,它指出没有干扰的子窗口,但是有一些消息进入 Spy++ 可以看到的窗口(WM_SETCURSORWM_MOUSEMOVEWM_LBUTTONDOWNWM_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. 我试图绕道消息和线程创建函数,试图记录正在发生的事情,但我似乎没有得到任何信息。

我真的对此摸不着头脑。 为什么智能卡登录窗口无法获得焦点? 什么会干扰这一点? 我们需要停止使用此解决方法,并实际获取智能卡登录名以具有父窗口。

我在"调试输出"窗口中找到的一些内容是:

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.
onecoreuapdssecurityfidocredprovdllfidoscenariocredui.cpp(44)fidocredprov.dll!3C8CD0D9: (caller: 3C8CB529) ReturnHr(1) tid(5488) 80070057 The parameter is incorrect.
Msg:[InvalidFlags 32] 
onecoreuapdssecurityfidocredprovdllfidoprovider.cpp(62)fidocredprov.dll!3C8CB540: (caller: 27886879) ReturnHr(2) tid(5488) 80070057 The parameter is incorrect.
onecoredssecuritybiometricscredprovprovider_v2bioprovider.cpp(99)BioCredProv.dll!3CDC9620: (caller: 27886879) ReturnHr(1) tid(5488) 80098003     CallContext:[SetUsageScenario] 
onecoredssecuritybiometricscredprovprovider_v2bioprovider.cpp(206)BioCredProv.dll!3CDC9117: (caller: 27886ECF) ReturnHr(2) tid(5488) 80004001 Not implemented
CallContext:[UnAdvise] 
onecoreuapshellauthcredprov2fahelperdllcredprov2fahelper.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] 
onecoredssecurityngcutilscommonlibsidutils.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.

虽然这些出现在父级是根(桌面)或我们的窗口时,所以我不确定它们是否意味着什么。

编辑

以下是用于调出智能卡对话框的代码(或多或少):

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()启用与该句柄关联的窗口,实际上将启用窗口。 为什么会这样呢? 为什么窗口会被禁用?

解决此问题的解决方法(我认为比不设置父级更好)是轮询安全对话框,一旦它可见并且仍未启用,请启用它。

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 什么时候会修复它。

相关内容

  • 没有找到相关文章

最新更新