Return 从本机代码到托管损坏了返回的对象
Return from native code to managed corrupts the returned object
我正在尝试使用 C++/CLI 和 yubico 的 libu2f-host(https://github.com/Yubico/libu2f-host) 在我的 WPF 程序中构建 U2F 身份验证的实现我的 C++/CLI dll 中有一个完全原生的函数,它调用适当的 libu2f 函数,然后它 return 是指向 u2f_reply(我自己的 class)的指针,其中包含响应和错误代码。
但是,当 dll 的托管部分接收到此对象时,响应代码仍然正确,但响应字符串似乎已完全损坏。
我尝试立即 returning char 指针,然后使用 marshal 将其转换为托管字符串,我尝试使用标准 C# 字符串。
我尝试使用 memcpy 将响应复制到 reply->response 但没有成功。
Managed_U2F_Reply^ Utilities::AuthenticateU2F(System::String^ challenge)
{
IntPtr ptrToChallenge = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(challenge);
u2f_reply* reply = NativeUtilities::AuthenticateU2F(static_cast<char*>(ptrToChallenge.ToPointer()));
//clean up before return
System::Runtime::InteropServices::Marshal::FreeHGlobal(ptrToChallenge);
Managed_U2F_Reply^ managedReply = gcnew Managed_U2F_Reply();
managedReply->ResultCode = reply->responseCode;
if (managedReply->ResultCode == 0)
{
managedReply->Response = gcnew String(reply->response, 0, reply->length);
}
return managedReply;
}
struct u2f_reply
{
int responseCode;
int length;
char* response;
};
u2f_reply* NativeUtilities::AuthenticateU2F(char* challenge)
{
u2f_reply* reply = new u2f_reply();
char response[2048] = { 0 };
size_t response_len = sizeof(response);
u2fh_devs* devs = NULL;
u2fh_rc rc;
u2fh_initflags flags = (u2fh_initflags)0;
rc = u2fh_global_init(flags);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_init(&devs);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_discover(devs, NULL);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_authenticate2(devs, challenge, "https://demo.yubico.com", response, &response_len, U2FH_REQUEST_USER_PRESENCE);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
u2fh_devs_done(devs);
u2fh_global_done();
reply->length = response_len;
reply->response = response;//adding printf here prints it out correctly, yet it doesn't when I call it in Utilities::AuthenticateU2F
reply->responseCode = rc;
return reply;
}
我希望它 return 一个带有响应数据的 json 对象,如下所示:https://developers.yubico.com/libu2f-host/,但我得到一个随机的 ASCII 字符串(无法粘贴)这里)并且没有错误
感谢 Hans Passant,我使用以下方法解决了这个问题:
u2f_reply* NativeUtilities::AuthenticateU2F(char* challenge)
{
u2f_reply* reply = new u2f_reply();
char response[2048] = { 0 };
size_t response_len = sizeof(response);
u2fh_devs* devs = NULL;
u2fh_rc rc;
u2fh_initflags flags = (u2fh_initflags)0;
rc = u2fh_global_init(flags);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_init(&devs);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_discover(devs, NULL);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_authenticate2(devs, challenge, "https://demo.yubico.com", response, &response_len, U2FH_REQUEST_USER_PRESENCE);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
u2fh_devs_done(devs);
u2fh_global_done();
reply->length = response_len;
reply->response = new char[response_len];
memcpy_s(reply->response, response_len, response, response_len);
reply->responseCode = rc;
return reply;
}
我正在尝试使用 C++/CLI 和 yubico 的 libu2f-host(https://github.com/Yubico/libu2f-host) 在我的 WPF 程序中构建 U2F 身份验证的实现我的 C++/CLI dll 中有一个完全原生的函数,它调用适当的 libu2f 函数,然后它 return 是指向 u2f_reply(我自己的 class)的指针,其中包含响应和错误代码。 但是,当 dll 的托管部分接收到此对象时,响应代码仍然正确,但响应字符串似乎已完全损坏。
我尝试立即 returning char 指针,然后使用 marshal 将其转换为托管字符串,我尝试使用标准 C# 字符串。 我尝试使用 memcpy 将响应复制到 reply->response 但没有成功。
Managed_U2F_Reply^ Utilities::AuthenticateU2F(System::String^ challenge)
{
IntPtr ptrToChallenge = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(challenge);
u2f_reply* reply = NativeUtilities::AuthenticateU2F(static_cast<char*>(ptrToChallenge.ToPointer()));
//clean up before return
System::Runtime::InteropServices::Marshal::FreeHGlobal(ptrToChallenge);
Managed_U2F_Reply^ managedReply = gcnew Managed_U2F_Reply();
managedReply->ResultCode = reply->responseCode;
if (managedReply->ResultCode == 0)
{
managedReply->Response = gcnew String(reply->response, 0, reply->length);
}
return managedReply;
}
struct u2f_reply
{
int responseCode;
int length;
char* response;
};
u2f_reply* NativeUtilities::AuthenticateU2F(char* challenge)
{
u2f_reply* reply = new u2f_reply();
char response[2048] = { 0 };
size_t response_len = sizeof(response);
u2fh_devs* devs = NULL;
u2fh_rc rc;
u2fh_initflags flags = (u2fh_initflags)0;
rc = u2fh_global_init(flags);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_init(&devs);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_discover(devs, NULL);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_authenticate2(devs, challenge, "https://demo.yubico.com", response, &response_len, U2FH_REQUEST_USER_PRESENCE);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
u2fh_devs_done(devs);
u2fh_global_done();
reply->length = response_len;
reply->response = response;//adding printf here prints it out correctly, yet it doesn't when I call it in Utilities::AuthenticateU2F
reply->responseCode = rc;
return reply;
}
我希望它 return 一个带有响应数据的 json 对象,如下所示:https://developers.yubico.com/libu2f-host/,但我得到一个随机的 ASCII 字符串(无法粘贴)这里)并且没有错误
感谢 Hans Passant,我使用以下方法解决了这个问题:
u2f_reply* NativeUtilities::AuthenticateU2F(char* challenge)
{
u2f_reply* reply = new u2f_reply();
char response[2048] = { 0 };
size_t response_len = sizeof(response);
u2fh_devs* devs = NULL;
u2fh_rc rc;
u2fh_initflags flags = (u2fh_initflags)0;
rc = u2fh_global_init(flags);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_init(&devs);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_devs_discover(devs, NULL);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
rc = u2fh_authenticate2(devs, challenge, "https://demo.yubico.com", response, &response_len, U2FH_REQUEST_USER_PRESENCE);
if (rc != U2FH_OK)
{
reply->responseCode = rc;
return reply;
}
u2fh_devs_done(devs);
u2fh_global_done();
reply->length = response_len;
reply->response = new char[response_len];
memcpy_s(reply->response, response_len, response, response_len);
reply->responseCode = rc;
return reply;
}