0

From the wincrypt api I am receiving a void* pointing to a char*. This char* is pointing to the start of a char[]. I am also receiving a void* pointing to a int with the size of the char*.

Regarding pvData and cbData I have the following documentation from Microsoft.

Data type of pvData: A pointer to an array of BYTE values. The size of this array is specified in the cbData parameter. Returns a null-terminated Unicode character string that contains the display name for the certificate.

I want to convert this void* to a std::string but so far all I am getting when outputting my std::string is the first character.

I have read: Converting a void* to a std::string but since my void* is pointing to a char* instead of std::string the static_cast in the accepted answer fails and the returned std::string* triggers a null pointer exception.

So far I have the following:

// pvData = void* pointing to char*
// cbData = void* pointing to int*
std::string tempName;
tempName.assign(static_cast<char*>(pvData), static_cast<int*>(cbData));
printf("%S \n", pvData); // entire string is shown
printf("%s \n", tempName.c_str()); // only first character is shown

I have also tried

tempName = static_cast<char*>(pvData); // only single character returned

tempName.assign(static_cast<char*>(pvData)); // only single character returned

char* arr = static_cast<char*>(pvData);
std::string tempName(arr); // only single character returned empty with printf must 
// use std::cout

2 Answers2

5

If the char buffer isn't null-terminated, then to use the (void*)cbData length:

char* data = static_cast<char*>(pvData);
size_t len = *static_cast<int*>(cbData);
std::string tempName(data, len);

See the std::string constructor reference (#5, from buffer) and ::assign reference (#4, buffer).

EDIT: If you're trying to use the function CertGetCertificateContextProperty with dwPropId CERT_FRIENDLY_NAME_PROP_ID, here is how you should call the function:

CERT_CONTEXT ctx;
BYTE buf[100];
DWORD len = 100;
CertGetCertificateContextProperty(&ctx, CERT_FRIENDLY_NAME_PROP_ID, buf, &len);
std::string tempName(reinterpret_cast<char*>(buf), len);

No dealing with void* pointers!

qxz
  • 3,814
  • 1
  • 14
  • 29
  • Kind sir you won the internet for today, I was close but no sigar. passing the int straight to std::string::assign instead of making it a size_t was the cause of the issue! –  Aug 21 '16 at 20:37
  • 1
    @Corne I think the issue was that you were casting the `void*` to an `int` when you should have cast it to an `int*`. – Galik Aug 21 '16 at 20:40
  • @Galik no that was a typo which I have removed to avoid confusing, sorry about that~! –  Aug 21 '16 at 20:42
  • @Corne See my edit – was this what you were trying to do? – qxz Aug 21 '16 at 20:47
  • @qyz yes the official example from microsoft showed it using void* no idea it could be this simple THANK YOU!. –  Aug 21 '16 at 20:49
  • 1
    np. With WinAPI functions (or other API functions) that take a `void*`, you generally are supposed to pass them just a normal pointer(-to-buffer) of the desired type. – qxz Aug 21 '16 at 20:53
1

The documentation specifically states that it returns a Unicode string, which in Microsoft-speak means UTF-16. Characters that are part of the ASCII range will contain a zero in their second byte, which ends a string copy prematurely. You would get better results using wstring with a cast to wchar_t*.

If copying to string appears to work, it's because those zero bytes are invisible.

Putting this in the context of your original code:

std::wstring tempName;
tempName.assign(static_cast<wchar_t*>(pvData), (*static_cast<int*>(cbData)) / sizeof(wchar_t));
printf("%S \n", tempName.c_str());

Note that this isn't the easiest way to do it, you should also follow the advice from qxz regarding the string constructor and the passing of cbData.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I also noticed this in my output because there is a space between each character now. This explains why copying while size_t is specified makes it work. i'll be sure to switch to Unicode variables as described. –  Aug 21 '16 at 21:01