如何解决Windows结构的格式化
使用fmt lib创建格式化程序以在我的代码中打印某些Windows结构时遇到了一些麻烦。 我在下面准备了一个基本示例。目的是能够以预结构化的方式打印出大型结构,并且仅打印我想要的内容,但我不太理解错误。
#include <windows.h>
#include <ntsecapi.h>
#include <iostream>
#include <fmt/format.h>
//#pragma comment(lib,"netapi32.lib")
#pragma comment(lib,"secur32.lib")
#pragma comment(lib,"ntdll.lib")
template <>
struct fmt::formatter<_Security_logoN_SESSION_DATA>
{
constexpr auto parse(format_parse_context& ctx)
{
// no specifiers
return ctx.begin();
}
template <typename F>
auto format(const _Security_logoN_SESSION_DATA& c,F &ctx)
{
std::wstring name(c.UserName.Buffer,c.UserName.Length);
std::wstring domainName(c.logonDomain.Buffer,c.logonDomain.Length);
auto s = fmt::format(L"UserName: {}\n"
"logonDomain: {}\n",name,domainName);
return format_to(ctx.out(),s);
}
};
VOID DumplogonData(PLUID logonLuid)
{
NTSTATUS status;
PSecurity_logoN_SESSION_DATA pData = nullptr;
if (!logonLuid)
return;
status = LsaGetlogonSessionData(logonLuid,&pData);
if (!NT_SUCCESS(status))
{
fmt::print("Failed to get logon session data: {}\n",RtlNtStatusTodosError(status));
LsaFreeReturnBuffer(pData);
}
fmt::print(L"logonSession Data\n{}\n",*pData);
LsaFreeReturnBuffer(pData);
}
BOOL EnumeratelogonSessions()
{
PLUID luidList = nullptr;
ULONG ulSessionCount;
NTSTATUS status;
status = LSAEnumeratelogonSessions(
&ulSessionCount,&luidList);
if (!NT_SUCCESS(status))
{
fmt::print("Failed to enumerate logon sessions\n");
return FALSE;
}
for (ULONG i = 0; i < ulSessionCount; ++i)
{
DumplogonData(&luidList[i]);
}
return TRUE;
}
int main(int argc,char **argv)
{
EnumeratelogonSessions();
std::getchar();
}
调用error C2338: Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/dev/api.html#udt
时,此格式将抛出fmt::print(L"logonSession Data\n{}\n",*pData);
。
任何帮助使该格式化程序正常工作的东西吗?
解决方法
一个问题是您试图传递指向_SECURITY_LOGON_SESSION_DATA
的指针,而不是指向它的(const)引用。应该是:
fmt::print(L"LogonSession Data\n{}\n",*pData);
与formatter::format
方法相同。
另一个问题是您的formatter
不支持wchar_t
,应该是:
template <typename Char>
struct fmt::formatter<_SECURITY_LOGON_SESSION_DATA,Char> {
...
};
如果要支持其他字符类型。或使用普通的多字节字符串而不是宽字符串。
,借助格式化程序的修复程序,我还需要专门研究parse
函数,以下是有效的格式化程序。
template <typename Char>
struct fmt::formatter<_SECURITY_LOGON_SESSION_DATA,Char>
{
template <typename ParseContext>
constexpr auto parse(ParseContext& ctx)
{
// no specifiers
return ctx.begin();
}
template <typename F>
auto format(const _SECURITY_LOGON_SESSION_DATA& c,F &ctx)
{
std::wstring name(c.UserName.Buffer,c.UserName.Length);
std::wstring domainName(c.LogonDomain.Buffer,c.LogonDomain.Length);
auto s = fmt::format(L"UserName: {}\n"
"LogonDomain: {}\n",name,domainName);
return format_to(ctx.out(),s);
}
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。