windows 凭证提示问题,CredUnPackAuthenticationBuffer 错误 50
Problem with windows credential prompt, CredUnPackAuthenticationBuffer error 50
我正在尝试显示 Windows 默认凭据提示并以字符串形式检索用户名、密码和域。
我正在使用此文档:
CredUIPromptForWindowsCredentialsW
CredUnPackAuthenticationBufferW
当出现提示时,我输入随机用户名和密码(例如,用户名:test,密码:test123),按回车键,函数 CredUnPackAuthenticationBuffer()
失败并显示 ERROR_NOT_SUPPORTED
代码:
#include <Windows.h>
#include <wincred.h> //Link library Credui.lib for CredUIPromptForWindowsCredentials() to work
#include <iostream>
#include <string>
//Display error in console and close application
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName);
int wmain(int argc, WCHAR* argv[])
{
CREDUI_INFO cuiInfo;
cuiInfo.cbSize = sizeof(CREDUI_INFO);
cuiInfo.hbmBanner = nullptr;
cuiInfo.hwndParent = nullptr;
cuiInfo.pszCaptionText = L"CaptionText";
cuiInfo.pszMessageText = L"MessageText";
DWORD dwAuthError = 0;
ULONG dwAuthPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredBufferSize = 0;
BOOL credSaveCheckbox = false;
DWORD dwError = 0;
DWORD lastError = 0;
dwError = CredUIPromptForWindowsCredentials(
&cuiInfo,
dwAuthError,
&dwAuthPackage,
nullptr,
NULL,
&outCredBuffer,
&outCredBufferSize,
&credSaveCheckbox,
CREDUIWIN_CHECKBOX | CREDUIWIN_GENERIC);
if (dwError == ERROR_SUCCESS)
{
DWORD maxUserNameSize = CREDUI_MAX_USERNAME_LENGTH;
DWORD maxDomainNameSize = CREDUI_MAX_DOMAIN_TARGET_LENGTH;
DWORD maxPasswordLength = CREDUI_MAX_PASSWORD_LENGTH;
LPWSTR szUserName = new WCHAR[maxUserNameSize];
LPWSTR szDomain = new WCHAR[maxDomainNameSize];
LPWSTR szPassword = new WCHAR[maxPasswordLength];
DWORD dwCredBufferSize = outCredBufferSize; //ULONG to DWORD
DWORD lastError = 0;
dwError = CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
&outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
lastError = GetLastError();
//Check for error
if (dwError == FALSE)
{
DisplayConsoleError(L"Blah", L"CredUnPackAuthenticationBuffer", lastError);
}
else
{
std::wcout << L"username " << szUserName << std::endl;
std::wcout << L"domain " << szDomain << std::endl;
std::wcout << L"password " << szPassword << std::endl;
}
}
else
{
lastError = dwError;
}
SecureZeroMemory(outCredBuffer, outCredBufferSize);
CoTaskMemFree(outCredBuffer);
return lastError;
}
另外在 VS2019 中调试 CredUIPromptForWindowsCredentials()
失败(加载符号有问题?),但编译后的 .exe 工作正常。作为解决方法,我将调试器附加到进程。
我是 winapi 的初学者,所以如果有人能解释为什么会出现此错误,我做错了什么以及如何修复此代码,我将不胜感激。
编辑
将错误检查移至 SecureZeroMemory()
和 CoTaskMemFree()
函数上方,以避免在检查错误消息之前调用其他 API 函数,
但错误仍然存在。
DisplayConsoleError:
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName, DWORD lastError)
{
std::cout << std::endl;
std::cout << "Error\t" << std::endl;
std::wcout << L"In function:\t" << fName << std::endl;
std::cout << "Code:\t" << lastError << std::endl;
std::cout << std::endl;
}
编辑 2 考虑到@RemyLebeau 反馈对代码的更改
看看你代码中的这个函数:
CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
&outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
您需要将 &outCredBuffer
更改为 outCredBuffer
。
#include <Windows.h>
#include <wincred.h> //Link library Credui.lib for CredUIPromptForWindowsCredentials() to work
#include <iostream>
#include <string>
//Display error in console and close application
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName, DWORD lastError)
{
std::cout << std::endl;
std::cout << "Error\t" << std::endl;
std::wcout << L"In function:\t" << fName << std::endl;
std::cout << "Code:\t" << lastError << std::endl;
std::cout << std::endl;
}
int wmain(int argc, WCHAR* argv[])
{
CREDUI_INFO cuiInfo;
cuiInfo.cbSize = sizeof(CREDUI_INFO);
cuiInfo.hbmBanner = nullptr;
cuiInfo.hwndParent = nullptr;
cuiInfo.pszCaptionText = L"CaptionText";
cuiInfo.pszMessageText = L"MessageText";
DWORD dwAuthError = 0;
ULONG dwAuthPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredBufferSize = 0;
BOOL credSaveCheckbox = false;
DWORD dwError = 0;
DWORD lastError = 0;
dwError = CredUIPromptForWindowsCredentials(
&cuiInfo,
dwAuthError,
&dwAuthPackage,
nullptr,
NULL,
&outCredBuffer,
&outCredBufferSize,
&credSaveCheckbox,
CREDUIWIN_CHECKBOX | CREDUIWIN_GENERIC);
if (dwError == ERROR_SUCCESS)
{
DWORD maxUserNameSize = CREDUI_MAX_USERNAME_LENGTH;
DWORD maxDomainNameSize = CREDUI_MAX_DOMAIN_TARGET_LENGTH;
DWORD maxPasswordLength = CREDUI_MAX_PASSWORD_LENGTH;
LPWSTR szUserName = new WCHAR[maxUserNameSize];
LPWSTR szDomain = new WCHAR[maxDomainNameSize];
LPWSTR szPassword = new WCHAR[maxPasswordLength];
DWORD dwCredBufferSize = outCredBufferSize; //ULONG to DWORD
DWORD lastError = 0;
dwError = CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
lastError = GetLastError();
//Check for error
if (dwError == FALSE)
{
DisplayConsoleError(L"Blah", L"CredUnPackAuthenticationBuffer", lastError);
}
else
{
std::wcout << L"username " << szUserName << std::endl;
std::wcout << L"domain " << szDomain << std::endl;
std::wcout << L"password " << szPassword << std::endl;
}
}
else
{
lastError = dwError;
}
SecureZeroMemory(outCredBuffer, outCredBufferSize);
CoTaskMemFree(outCredBuffer);
return lastError;
}
我正在尝试显示 Windows 默认凭据提示并以字符串形式检索用户名、密码和域。
我正在使用此文档:
CredUIPromptForWindowsCredentialsW
CredUnPackAuthenticationBufferW
当出现提示时,我输入随机用户名和密码(例如,用户名:test,密码:test123),按回车键,函数 CredUnPackAuthenticationBuffer()
失败并显示 ERROR_NOT_SUPPORTED
代码:
#include <Windows.h>
#include <wincred.h> //Link library Credui.lib for CredUIPromptForWindowsCredentials() to work
#include <iostream>
#include <string>
//Display error in console and close application
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName);
int wmain(int argc, WCHAR* argv[])
{
CREDUI_INFO cuiInfo;
cuiInfo.cbSize = sizeof(CREDUI_INFO);
cuiInfo.hbmBanner = nullptr;
cuiInfo.hwndParent = nullptr;
cuiInfo.pszCaptionText = L"CaptionText";
cuiInfo.pszMessageText = L"MessageText";
DWORD dwAuthError = 0;
ULONG dwAuthPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredBufferSize = 0;
BOOL credSaveCheckbox = false;
DWORD dwError = 0;
DWORD lastError = 0;
dwError = CredUIPromptForWindowsCredentials(
&cuiInfo,
dwAuthError,
&dwAuthPackage,
nullptr,
NULL,
&outCredBuffer,
&outCredBufferSize,
&credSaveCheckbox,
CREDUIWIN_CHECKBOX | CREDUIWIN_GENERIC);
if (dwError == ERROR_SUCCESS)
{
DWORD maxUserNameSize = CREDUI_MAX_USERNAME_LENGTH;
DWORD maxDomainNameSize = CREDUI_MAX_DOMAIN_TARGET_LENGTH;
DWORD maxPasswordLength = CREDUI_MAX_PASSWORD_LENGTH;
LPWSTR szUserName = new WCHAR[maxUserNameSize];
LPWSTR szDomain = new WCHAR[maxDomainNameSize];
LPWSTR szPassword = new WCHAR[maxPasswordLength];
DWORD dwCredBufferSize = outCredBufferSize; //ULONG to DWORD
DWORD lastError = 0;
dwError = CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
&outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
lastError = GetLastError();
//Check for error
if (dwError == FALSE)
{
DisplayConsoleError(L"Blah", L"CredUnPackAuthenticationBuffer", lastError);
}
else
{
std::wcout << L"username " << szUserName << std::endl;
std::wcout << L"domain " << szDomain << std::endl;
std::wcout << L"password " << szPassword << std::endl;
}
}
else
{
lastError = dwError;
}
SecureZeroMemory(outCredBuffer, outCredBufferSize);
CoTaskMemFree(outCredBuffer);
return lastError;
}
另外在 VS2019 中调试 CredUIPromptForWindowsCredentials()
失败(加载符号有问题?),但编译后的 .exe 工作正常。作为解决方法,我将调试器附加到进程。
我是 winapi 的初学者,所以如果有人能解释为什么会出现此错误,我做错了什么以及如何修复此代码,我将不胜感激。
编辑
将错误检查移至 SecureZeroMemory()
和 CoTaskMemFree()
函数上方,以避免在检查错误消息之前调用其他 API 函数,
但错误仍然存在。
DisplayConsoleError:
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName, DWORD lastError)
{
std::cout << std::endl;
std::cout << "Error\t" << std::endl;
std::wcout << L"In function:\t" << fName << std::endl;
std::cout << "Code:\t" << lastError << std::endl;
std::cout << std::endl;
}
编辑 2 考虑到@RemyLebeau 反馈对代码的更改
看看你代码中的这个函数:
CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
&outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
您需要将 &outCredBuffer
更改为 outCredBuffer
。
#include <Windows.h>
#include <wincred.h> //Link library Credui.lib for CredUIPromptForWindowsCredentials() to work
#include <iostream>
#include <string>
//Display error in console and close application
void DisplayConsoleError(const WCHAR* errorMessage, const WCHAR* fName, DWORD lastError)
{
std::cout << std::endl;
std::cout << "Error\t" << std::endl;
std::wcout << L"In function:\t" << fName << std::endl;
std::cout << "Code:\t" << lastError << std::endl;
std::cout << std::endl;
}
int wmain(int argc, WCHAR* argv[])
{
CREDUI_INFO cuiInfo;
cuiInfo.cbSize = sizeof(CREDUI_INFO);
cuiInfo.hbmBanner = nullptr;
cuiInfo.hwndParent = nullptr;
cuiInfo.pszCaptionText = L"CaptionText";
cuiInfo.pszMessageText = L"MessageText";
DWORD dwAuthError = 0;
ULONG dwAuthPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredBufferSize = 0;
BOOL credSaveCheckbox = false;
DWORD dwError = 0;
DWORD lastError = 0;
dwError = CredUIPromptForWindowsCredentials(
&cuiInfo,
dwAuthError,
&dwAuthPackage,
nullptr,
NULL,
&outCredBuffer,
&outCredBufferSize,
&credSaveCheckbox,
CREDUIWIN_CHECKBOX | CREDUIWIN_GENERIC);
if (dwError == ERROR_SUCCESS)
{
DWORD maxUserNameSize = CREDUI_MAX_USERNAME_LENGTH;
DWORD maxDomainNameSize = CREDUI_MAX_DOMAIN_TARGET_LENGTH;
DWORD maxPasswordLength = CREDUI_MAX_PASSWORD_LENGTH;
LPWSTR szUserName = new WCHAR[maxUserNameSize];
LPWSTR szDomain = new WCHAR[maxDomainNameSize];
LPWSTR szPassword = new WCHAR[maxPasswordLength];
DWORD dwCredBufferSize = outCredBufferSize; //ULONG to DWORD
DWORD lastError = 0;
dwError = CredUnPackAuthenticationBuffer(
CRED_PACK_GENERIC_CREDENTIALS,
outCredBuffer,
dwCredBufferSize,
szUserName,
&maxUserNameSize,
szDomain,
&maxDomainNameSize,
szPassword,
&maxPasswordLength
);
lastError = GetLastError();
//Check for error
if (dwError == FALSE)
{
DisplayConsoleError(L"Blah", L"CredUnPackAuthenticationBuffer", lastError);
}
else
{
std::wcout << L"username " << szUserName << std::endl;
std::wcout << L"domain " << szDomain << std::endl;
std::wcout << L"password " << szPassword << std::endl;
}
}
else
{
lastError = dwError;
}
SecureZeroMemory(outCredBuffer, outCredBufferSize);
CoTaskMemFree(outCredBuffer);
return lastError;
}