UNICODE_STRING для Null прекращено - PullRequest
1 голос
/ 03 ноября 2008

Мне нужно преобразовать структуру UNICODE_STRING в простую пустую строку.

typedef 
struct _UNICODE_STRING 
{
    USHORT  Length;  
    USHORT  MaximumLength;  
    PWSTR   Buffer;
} 
UNICODE_STRING, *PUNICODE_STRING;

Я не могу найти чистое решение по MSDN по этому поводу. Кто-нибудь был там? Я не использую .net, поэтому мне нужно собственное решение API.

Большое спасибо!

Ответы [ 5 ]

4 голосов
/ 03 ноября 2008

Вы должны использовать WideCharToMultiByte. В качестве оценки размера выходного буфера вы можете использовать поле Length, но рассмотрите случай истинных многобайтовых строк, в этом случае он завершится ошибкой с ERROR_INSUFFICIENT_BUFFER, и вам нужно начать с большего буфера. Или вы вызываете его с размером выходного буфера сначала всегда 0, поэтому он сообщает вам необходимый размер буфера.

1 голос
/ 04 июля 2012

При компиляции для 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";
0 голосов
/ 16 ноября 2012

Альтернативный код, который преобразуется в ANSI и не требует количества символов Юникода в UNICODE_STRING, который должен быть передан в качестве параметра в WideCharToMultiByte. (Обратите внимание, что UNICODE_STRING.Length - это число байтов, а не символов Юникода, и 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
0 голосов
/ 04 июля 2012

Поскольку вы не сказали, нужна ли вам строка с нулевым символом в конце 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 голосов
/ 11 марта 2012
WCHAR* UnicodeStringToNulTerminated(UNICODE_STRING* str)
{
  WCHAR* result;
  if(str == NULL)
    return NULL;
  result = (WCHAR*)malloc(result->Length + 2);
  if(result == NULL)
    // raise?
    return NULL;
  memcpy(result, str->Buffer, str->Length);
  result[str->Length] = L'\0';
  return result;
}
...