我的公司正在为Windows中的SmartCard安全设置进行编程。但是,当我们更新到Fall Creators时,我们遇到了麻烦,开发人员可以通过不将父窗口传递给CredUIPromptForWindowsCredentialsW()
函数(desktop / root / NULL
)来缓解这种情况。如果我们通过父窗口,则会导致无法访问智能卡登录对话框,如弹出窗口,但是当您单击它时,会听到窗口的默认蜂鸣声,您无法键入任何内容。我看过使用Spy ++并且它声明没有子窗口干扰,但有些消息进入Spy ++可以看到的窗口(WM_SETCURSOR
,WM_MOUSEMOVE
,WM_LBUTTONDOWN
, WM_LBUTTONUP
以及一堆具有各种参数的注册SHELLHOOK
。
如果有所不同,应用程序是使用MFC MBCS框架编写的。
我尝试过的事情是:
::ShowWindow(m_Parent, SW_SHOW);
时有效,但在我使用::SetWindowPos(m_Parent, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
我真的在摸不着头脑。为什么智能卡登录窗口无法获得焦点?有什么可能干扰这个?我们需要停止使用此解决方法,并实际让智能卡登录具有父窗口。
我在Debug Output窗口中找到的一些东西是:
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.
虽然这些是父级是根(桌面)或我们的窗口时出现的,所以我不确定它们是否有意义。
以下是用于打开智能卡对话框的代码(或多或少):
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);
根据Spy ++,似乎禁用了该对话框。编写一个快速的小应用程序,给定任何窗口句柄,通过调用EnableWindow()
启用与该句柄关联的窗口将实际启用该窗口。为什么会这样呢?为什么要禁用窗口?
答案 0 :(得分:0)
这个问题的解决方法,我认为最好不设置父级,是轮询安全性对话框,一旦它可见但仍未启用,则启用它。
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什么时候会修复它。