220 lines
5.5 KiB
C
220 lines
5.5 KiB
C
/*
|
|
* Author: NoMachine <developers@nomachine.com>
|
|
*
|
|
* Copyright (c) 2009, 2010 NoMachine
|
|
* All rights reserved
|
|
*
|
|
* Support functions and system calls' replacements needed to let the
|
|
* software run on Win32 based operating systems.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <winsock2.h>
|
|
#include <Windows.h>
|
|
#include "Debug.h"
|
|
|
|
#undef DEBUG
|
|
|
|
#ifdef DEBUG
|
|
# define DBG_MSG(...) debug3(__VA_ARGS__)
|
|
#else
|
|
# define DBG_MSG(...)
|
|
#endif
|
|
|
|
#define SocketErrorStringSize 1024
|
|
|
|
char * strerror_win32(int error)
|
|
{
|
|
|
|
static char SocketErrorString[2 * SocketErrorStringSize] = { 0 };
|
|
|
|
DWORD error_win32 = WSAGetLastError();
|
|
|
|
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, error_win32, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
|
(LPTSTR) SocketErrorString, SocketErrorStringSize,
|
|
NULL ) != 0)
|
|
{
|
|
return SocketErrorString;
|
|
}
|
|
else
|
|
{
|
|
return "Unknown error";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Convert string encoding from one 8-bit CP to another 8-bit CP.
|
|
* WARNING: Returned strong MUST be free by caller.
|
|
*
|
|
* src - source string (IN).
|
|
* srcSize - size of src string in bytes or -1 if zero terminated (IN).
|
|
* srcCP - code page used by src string (IN).
|
|
* dstCP - target code page (IN).
|
|
* retSize - size of returned string, may be NULL (OUT/OPTIONAL).
|
|
*
|
|
* RETURNS: Pointer to new allocated string encoded in target CP
|
|
* or NULL if error.
|
|
*
|
|
*/
|
|
|
|
void *CovertCodePage(const char *src, int srcSize,
|
|
DWORD srcCP, DWORD dstCP, int *retSize)
|
|
{
|
|
int exitCode = -1;
|
|
|
|
int utf16Len = 0;
|
|
int dstLen = 0;
|
|
|
|
wchar_t *utf16 = NULL;
|
|
|
|
char *ret = NULL;
|
|
|
|
DBG_MSG("-> ConvertCodePage(src=[%s], srcSize=[%d])...", src, srcSize);
|
|
|
|
/*
|
|
* Check args.
|
|
*/
|
|
|
|
FAIL(src == NULL);
|
|
|
|
/*
|
|
* Retrieve size for UTF16.
|
|
*/
|
|
|
|
DBG_MSG("Retrieving size of UTF16...");
|
|
|
|
utf16Len = MultiByteToWideChar(srcCP, 0, src, srcSize, NULL, 0);
|
|
|
|
FAIL(utf16Len <= 0);
|
|
|
|
/*
|
|
* Allocate buffer for UTF16.
|
|
*/
|
|
|
|
DBG_MSG("Allocating [%d] bytes for UTF16...", utf16Len * sizeof(wchar_t));
|
|
|
|
utf16 = (wchar_t *) malloc((utf16Len + 1) * sizeof(wchar_t));
|
|
|
|
FAIL(utf16 == NULL);
|
|
|
|
/*
|
|
* Convert src to UTF16.
|
|
*/
|
|
|
|
DBG_MSG("Allocating [%d] bytes for UTF16...", utf16Len * sizeof(wchar_t));
|
|
|
|
FAIL(MultiByteToWideChar(srcCP, 0, src, srcSize, utf16, utf16Len) < 0);
|
|
|
|
/*
|
|
* Allocate buffer for return.
|
|
*/
|
|
|
|
DBG_MSG("Allocating buffer for dst...");
|
|
|
|
dstLen = WideCharToMultiByte(dstCP, 0, utf16, -1, NULL, 0, NULL, NULL);
|
|
|
|
ret = malloc(dstLen + 1);
|
|
|
|
FAIL(ret == NULL);
|
|
|
|
ret[dstLen] = 0;
|
|
|
|
/*
|
|
* Convert utf16 to target CP.
|
|
*/
|
|
|
|
DBG_MSG("Converting UTF16 to dst...");
|
|
|
|
dstLen = WideCharToMultiByte(dstCP, 0, utf16, utf16Len,
|
|
ret, dstLen + 1, NULL, NULL);
|
|
|
|
FAIL(dstLen < 0);
|
|
|
|
if (retSize)
|
|
{
|
|
*retSize = dstLen;
|
|
}
|
|
|
|
/*
|
|
* Clean up.
|
|
*/
|
|
|
|
exitCode = 0;
|
|
|
|
fail:
|
|
|
|
if (exitCode)
|
|
{
|
|
debug3("ERROR: Cannot convert [%s] from CP[0x%x] to CP[0x%x]."
|
|
"Error code is : %d.\n", src, srcCP, dstCP, GetLastError());
|
|
|
|
if (ret)
|
|
{
|
|
free(ret);
|
|
|
|
ret = NULL;
|
|
}
|
|
}
|
|
|
|
if (utf16)
|
|
{
|
|
free(utf16);
|
|
}
|
|
|
|
DBG_MSG("<- ConvertCodePage()...");
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Covert string from UTF8 to CP used by current thread (Local8).
|
|
*
|
|
* utf8 - string in UTF8 (IN).
|
|
* utf8Size - size of utf8 string in bytes or -1 if zero terminated (IN).
|
|
* bytesReturned - size of returned Local8 string (OUT).
|
|
*
|
|
* RETURNS: Pointer to new allocated Local8 string or NULL if error.
|
|
*/
|
|
|
|
void *CovertUtf8ToLocal8(const char *utf8, int utf8Size, int *bytesReturned)
|
|
{
|
|
return CovertCodePage(utf8, utf8Size, CP_UTF8, GetACP(), bytesReturned);
|
|
}
|
|
|
|
/*
|
|
* Covert string from CP used by current thread (Local8) to UTF8.
|
|
*
|
|
* local8 - string in Local8 CP (IN).
|
|
* local8Size - size of local8 string in bytes or -1 if zero terminated (IN).
|
|
* bytesReturned - size of returned UTF8 string (OUT).
|
|
*
|
|
* RETURNS: Pointer to new allocated UTF8 string or NULL if error.
|
|
*/
|
|
|
|
void *ConvertLocal8ToUtf8(const char *local8, int local8Size, int *bytesReturned)
|
|
{
|
|
return CovertCodePage(local8, local8Size,
|
|
GetACP(), CP_UTF8, bytesReturned);
|
|
}
|