UNICODE_STRING转换为以空字符结尾的字符串

3
我需要将一个UNICODE_STRING结构转换为一个简单的NULL TERMINATED字符串。
typedef 
struct _UNICODE_STRING 
{
    USHORT  Length;  
    USHORT  MaximumLength;  
    PWSTR   Buffer;
} 
UNICODE_STRING, *PUNICODE_STRING;

我在MSDN上找不到关于它的清晰解决方案。有人遇到过吗?

我没有使用.net,所以我需要一个本地API解决方案。

非常感谢!


2
当你说"NULL TERMINATED STRING"时,是指以null结尾的wchar_t字符串还是以null结尾的ASCII/多字节字符字符串? - Michael Burr
5个回答

4

您应该使用 WideCharToMultiByte。对于输出缓冲区大小的估计,您可以使用 Length 字段 - 但请考虑真正的多字节字符串的情况,在这种情况下,它将失败并返回 ERROR_INSUFFICIENT_BUFFER,此时您需要重新开始使用更大的缓冲区。或者,您可以始终首先调用输出缓冲区大小为 0,这样它会告诉您所需缓冲区的大小。


2

当编译为Unicode并转换为ANSI时,以下方法适用于我(修改自http://support.microsoft.com/kb/138813):

HRESULT UnicodeToAnsi(LPCOLESTR pszW, LPSTR* ppszA){
    ULONG cbAnsi, cCharacters;
    DWORD dwError;
    // If input is null then just return the same.    
    if (pszW == NULL)    
    {
        *ppszA = NULL;
        return NOERROR;
    }
    cCharacters = wcslen(pszW)+1;
    cbAnsi = cCharacters*2;

    *ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi);
    if (NULL == *ppszA)
        return E_OUTOFMEMORY;

    if (0 == WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, *ppszA, cbAnsi, NULL, NULL)) 
    {
        dwError = GetLastError();
        CoTaskMemFree(*ppszA);
        *ppszA = NULL;
        return HRESULT_FROM_WIN32(dwError);
    }
    return NOERROR;
}


用法:

LPSTR pszstrA;
UnicodeToAnsi(my_unicode_string.Buffer, &pszstrA);
cout << "My ansi string: (" << pszstrA << ")\r\n";

1

替代代码可将数据转换为ANSI,并不需要传递作为参数传递给WideCharToMultiByte的UNICODE_STRING中的Unicode字符数。(请注意,UNICODE_STRING.Length是字节数而不是Unicode字符数,如果缓冲区没有零终止,则wcslen无法工作)。

UNICODE_STRING tmp;
// ...
STRING dest; // or ANSI_STRING in kernel mode

LONG (WINAPI *RtlUnicodeStringToAnsiString)(PVOID, PVOID, BOOL);
*(FARPROC *)&RtlUnicodeStringToAnsiString = 
    GetProcAddress(LoadLibraryA("NTDLL.DLL"), "RtlUnicodeStringToAnsiString");
if(!RtlUnicodeStringToAnsiString)
{
    return;
}

ULONG unicodeBufferSize = tmp.Length;
dest.Buffer = (PCHAR)malloc(unicodeBufferSize+1); // that must be enough...
dest.Length = 0;
dest.MaximumLength = unicodeBufferSize+1;

RtlUnicodeStringToAnsiString(&dest, &tmp, FALSE);
dest.Buffer[dest.Length] = 0; // now we get it in dest.Buffer

1

由于您没有说明您需要 ANSI 还是 UNICODE 的以空字符结尾的字符串,我假设您需要 UNICODE:

#include <string>

UNICODE_STRING us;
// fill us as needed...

std::wstring ws(us.Buffer, us.Length);
// use ws.c_str() where needed...

0
WCHAR* UnicodeStringToNulTerminated(UNICODE_STRING* str)
{
  WCHAR* result;
  if(str == NULL)
    return NULL;
  result = (WCHAR*)malloc(str->Length + 2);
  if(result == NULL)
    // raise?
    return NULL;
  memcpy(result, str->Buffer, str->Length);
  result[str->Length] = L'\0';
  return result;
}

'result->Length' 应为 'str->Length'。 - BCran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接