libwinpr-crt: implement unicode functions

This commit is contained in:
Marc-André Moreau 2012-05-23 01:49:21 -04:00
parent a09dbbd671
commit 5207d65c2a
4 changed files with 252 additions and 7 deletions

View File

@ -25,6 +25,10 @@
#include <winpr/winpr.h>
#ifdef _WIN32
#include <winnls.h>
#endif
#include <winpr/string.h>
#endif /* WINPR_CRT_H */

View File

@ -27,6 +27,23 @@
#ifndef _WIN32
#define CSTR_LESS_THAN 1
#define CSTR_EQUAL 2
#define CSTR_GREATER_THAN 3
#define CP_ACP 0
#define CP_OEMCP 1
#define CP_MACCP 2
#define CP_THREAD_ACP 3
#define CP_SYMBOL 42
#define CP_UTF7 65000
#define CP_UTF8 65001
#define MB_PRECOMPOSED 0x00000001
#define MB_COMPOSITE 0x00000002
#define MB_USEGLYPHCHARS 0x00000004
#define MB_ERR_INVALID_CHARS 0x00000008
WINPR_API char* _strdup(const char* strSource);
WINPR_API wchar_t* _wcsdup(const wchar_t* strSource);
@ -102,6 +119,12 @@ WINPR_API BOOL IsCharLowerW(WCHAR ch);
#define IsCharLower IsCharLowerA
#endif
WINPR_API int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar);
WINPR_API int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
#endif
#endif /* WINPR_CRT_STRING_H */

View File

@ -285,4 +285,219 @@ BOOL IsCharLowerW(WCHAR ch)
return 0;
}
/*
* Advanced String Techniques in C++ - Part I: Unicode
* http://www.flipcode.com/archives/Advanced_String_Techniques_in_C-Part_I_Unicode.shtml
*/
/*
* Conversion *to* Unicode
* MultiByteToWideChar: http://msdn.microsoft.com/en-us/library/windows/desktop/dd319072/
*/
int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)
{
size_t ibl;
size_t obl;
char* pin;
char* pout;
char* pout0;
if (lpMultiByteStr == NULL)
return 0;
if (cbMultiByte < 0)
cbMultiByte = strlen(lpMultiByteStr) + 1;
ibl = cbMultiByte;
obl = 2 * ibl;
if (cchWideChar < 1)
return (obl / 2);
pin = (char*) lpMultiByteStr;
pout0 = (char*) lpWideCharStr;
pout = pout0;
#ifdef HAVE_ICONV
{
iconv_t* out_iconv_h;
out_iconv_h = iconv_open(WINDOWS_CODEPAGE, DEFAULT_CODEPAGE);
if (errno == EINVAL)
{
printf("Error opening iconv converter to %s from %s\n", WINDOWS_CODEPAGE, DEFAULT_CODEPAGE);
return 0;
}
if (iconv(out_iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
{
printf("MultiByteToWideChar: iconv() error\n");
return NULL;
}
iconv_close(out_iconv_h);
}
#else
while ((ibl > 0) && (obl > 0))
{
unsigned int wc;
wc = (unsigned int) (unsigned char) (*pin++);
ibl--;
if (wc >= 0xF0)
{
wc = (wc - 0xF0) << 18;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80) << 12;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80) << 6;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80);
ibl -= 3;
}
else if (wc >= 0xE0)
{
wc = (wc - 0xE0) << 12;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80) << 6;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80);
ibl -= 2;
}
else if (wc >= 0xC0)
{
wc = (wc - 0xC0) << 6;
wc += ((unsigned int) (unsigned char) (*pin++) - 0x80);
ibl -= 1;
}
if (wc <= 0xFFFF)
{
*pout++ = (char) (wc & 0xFF);
*pout++ = (char) (wc >> 8);
obl -= 2;
}
else
{
wc -= 0x10000;
*pout++ = (char) ((wc >> 10) & 0xFF);
*pout++ = (char) ((wc >> 18) + 0xD8);
*pout++ = (char) (wc & 0xFF);
*pout++ = (char) (((wc >> 8) & 0x03) + 0xDC);
obl -= 4;
}
}
#endif
if (ibl > 0)
{
printf("MultiByteToWideChar: string not fully converted - %d chars left\n", (int) ibl);
return 0;
}
return (pout - pout0) / 2;
}
/*
* Conversion *from* Unicode
* WideCharToMultiByte: http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130/
*/
int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)
{
char* pout;
char* conv_pout;
size_t conv_in_len;
size_t conv_out_len;
unsigned char* conv_pin;
if (cchWideChar < 1)
if (cchWideChar == 0)
return 0;
conv_pin = (unsigned char*) lpWideCharStr;
conv_in_len = cchWideChar;
pout = lpMultiByteStr;
conv_pout = pout;
conv_out_len = cbMultiByte;
#ifdef HAVE_ICONV
{
iconv_t* in_iconv_h;
in_iconv_h = iconv_open(DEFAULT_CODEPAGE, WINDOWS_CODEPAGE);
if (errno == EINVAL)
{
printf("Error opening iconv converter to %s from %s\n", DEFAULT_CODEPAGE, WINDOWS_CODEPAGE);
return 0;
}
if (iconv(in_iconv_h, (ICONV_CONST char **) &conv_pin, &conv_in_len, &conv_pout, &conv_out_len) == (size_t) - 1)
{
printf("WideCharToMultiByte: iconv failure\n");
return 0;
}
iconv_close(in_iconv_h);
}
#else
while (conv_in_len >= 2)
{
unsigned int wc;
wc = (unsigned int) (unsigned char) (*conv_pin++);
wc += ((unsigned int) (unsigned char) (*conv_pin++)) << 8;
conv_in_len -= 2;
if (wc >= 0xD800 && wc <= 0xDFFF && conv_in_len >= 2)
{
/* Code points U+10000 to U+10FFFF using surrogate pair */
wc = ((wc - 0xD800) << 10) + 0x10000;
wc += (unsigned int) (unsigned char) (*conv_pin++);
wc += ((unsigned int) (unsigned char) (*conv_pin++) - 0xDC) << 8;
conv_in_len -= 2;
}
if (wc <= 0x7F)
{
*conv_pout++ = (char) wc;
conv_out_len--;
}
else if (wc <= 0x07FF)
{
*conv_pout++ = (char) (0xC0 + (wc >> 6));
*conv_pout++ = (char) (0x80 + (wc & 0x3F));
conv_out_len -= 2;
}
else if (wc <= 0xFFFF)
{
*conv_pout++ = (char) (0xE0 + (wc >> 12));
*conv_pout++ = (char) (0x80 + ((wc >> 6) & 0x3F));
*conv_pout++ = (char) (0x80 + (wc & 0x3F));
conv_out_len -= 3;
}
else
{
*conv_pout++ = (char) (0xF0 + (wc >> 18));
*conv_pout++ = (char) (0x80 + ((wc >> 12) & 0x3F));
*conv_pout++ = (char) (0x80 + ((wc >> 6) & 0x3F));
*conv_pout++ = (char) (0x80 + (wc & 0x3F));
conv_out_len -= 4;
}
}
#endif
if (conv_in_len > 0)
{
printf("WideCharToMultiByte: conversion failure - %d chars left\n", (int) conv_in_len);
return 0;
}
*conv_pout = 0;
return conv_out_len;
}
#endif

View File

@ -26,6 +26,7 @@
#include <freerdp/crypto/tls.h>
#include <freerdp/utils/stream.h>
#include <winpr/crt.h>
#include <winpr/sspi.h>
#include <winpr/credssp.h>
@ -79,16 +80,17 @@
void credssp_SetContextIdentity(rdpCredssp* context, char* user, char* domain, char* password)
{
size_t size;
context->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
context->identity.User = (uint16*) freerdp_uniconv_out(context->uniconv, user, &size);
context->identity.UserLength = (uint32) size;
context->identity.UserLength = strlen(user) * 2;
context->identity.User = (uint16*) malloc(context->identity.UserLength);
MultiByteToWideChar(CP_ACP, 0, user, strlen(user), (LPWSTR) context->identity.User, context->identity.UserLength / 2);
if (domain)
{
context->identity.Domain = (uint16*) freerdp_uniconv_out(context->uniconv, domain, &size);
context->identity.DomainLength = (uint32) size;
context->identity.DomainLength = strlen(user) * 2;
context->identity.Domain = (uint16*) malloc(context->identity.DomainLength);
MultiByteToWideChar(CP_ACP, 0, user, strlen(user), (LPWSTR) context->identity.Domain, context->identity.DomainLength / 2);
}
else
{
@ -96,8 +98,9 @@ void credssp_SetContextIdentity(rdpCredssp* context, char* user, char* domain, c
context->identity.DomainLength = 0;
}
context->identity.Password = (uint16*) freerdp_uniconv_out(context->uniconv, (char*) password, &size);
context->identity.PasswordLength = (uint32) size;
context->identity.PasswordLength = strlen(password) * 2;
context->identity.Password = (uint16*) malloc(context->identity.PasswordLength);
MultiByteToWideChar(CP_ACP, 0, password, strlen(password), (LPWSTR) context->identity.Password, context->identity.PasswordLength / 2);
}
/**