You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
575 lines
17 KiB
575 lines
17 KiB
//+------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 2000, Microsoft Corporation
|
|
//
|
|
// File: CodePageConvert.cpp
|
|
//
|
|
// Contents: Implementation of functions
|
|
// HrCodePageConvert
|
|
// HrCodePageConvert
|
|
// HrCodePageConvertFree
|
|
// HrCodePageConvertInternal
|
|
//
|
|
// History:
|
|
// aszafer 2000/03/15 created
|
|
//
|
|
//-------------------------------------------------------------
|
|
|
|
#include "CodePageConvert.h"
|
|
#include "dbgtrace.h"
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: HrCodePageConvert
|
|
//
|
|
// Synopsis: Converts a zero terminated string to a different code page
|
|
//
|
|
// NOTES:
|
|
// caller needs to provide buffer where target string is returned
|
|
//
|
|
// Arguments:
|
|
// uiSourceCodePage Source Code Page
|
|
// pszSourceString Source String
|
|
// uiTargetCodePage Target Code Page
|
|
// pszTargetString p to prealloc buffer where target string is returned
|
|
// cbTargetStringBuffer cbytes of preallocated buffer for target string
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
|
|
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
|
|
// HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) if
|
|
// uiSourceCodePage = uiTargetCodePage and
|
|
// cbTargetStringBuffer is too small
|
|
//
|
|
// History:
|
|
// aszafer 2000/03/29 created
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT HrCodePageConvert (
|
|
IN UINT uiSourceCodePage, // Source code page
|
|
IN LPSTR pszSourceString, // Source String
|
|
IN UINT uiTargetCodePage, // Target code page
|
|
OUT LPSTR pszTargetString, // p to buffer where target string is returned
|
|
IN int cbTargetStringBuffer) // cbytes in buffer for target string
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
TraceFunctEnter("HrCodePageConvert");
|
|
|
|
_ASSERT(pszSourceString);
|
|
_ASSERT(pszTargetString);
|
|
_ASSERT(cbTargetStringBuffer);
|
|
|
|
//
|
|
// Take care of trivial cases first
|
|
//
|
|
if (uiTargetCodePage == uiSourceCodePage){
|
|
|
|
if (pszTargetString == pszSourceString)
|
|
goto CLEANUP ;
|
|
|
|
if (lstrlen(pszSourceString) < cbTargetStringBuffer){
|
|
|
|
lstrcpy(pszTargetString,pszSourceString);
|
|
|
|
}else{
|
|
|
|
DebugTrace(0,
|
|
"Insufficient cbTargetStringBuffer = %08lx",cbTargetStringBuffer);
|
|
hr = HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ;
|
|
|
|
}
|
|
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
|
|
//
|
|
// If case is not trivial, call into HrCodePageConvertInternal
|
|
//
|
|
hr = HrCodePageConvertInternal (
|
|
uiSourceCodePage, // source code page
|
|
pszSourceString, // source string
|
|
uiTargetCodePage, // target code page
|
|
pszTargetString, // target string or NULL
|
|
cbTargetStringBuffer, // cb in target string or 0
|
|
NULL ); // NULL or p to where target string is returned
|
|
|
|
|
|
if (FAILED(hr))
|
|
DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr);
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DebugTrace(0,"returning %08lx", hr);
|
|
TraceFunctLeave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: HrCodePageConvert
|
|
//
|
|
// Synopsis: Converts a zero terminated string to a different code page
|
|
//
|
|
// NOTES:
|
|
// 1. if the fucntion succeeds, the caller needs to call
|
|
// HrCodePageConvertFree (*ppszTargetString) when done,
|
|
// to free memory allocated inside this function
|
|
// 2. if the function fails, it will internally free all allocated memory
|
|
//
|
|
// Arguments:
|
|
// uiSourceCodePage Source Code Page
|
|
// pszSourceString Source String
|
|
// uiTargetCodePage Target Code Page
|
|
// ppszTargetString p to where to return target string
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
|
|
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
|
|
//
|
|
// History:
|
|
// aszafer 2000/03/29 created
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT HrCodePageConvert (
|
|
IN UINT uiSourceCodePage, // Source code page
|
|
IN LPSTR pszSourceString, // Source string
|
|
IN UINT uiTargetCodePage, // Target code page
|
|
OUT LPSTR * ppszTargetString) // p to where target string is returned
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszTargetString = NULL;
|
|
|
|
TraceFunctEnter("HrCodePageConvert");
|
|
|
|
_ASSERT(pszSourceString);
|
|
_ASSERT(ppszTargetString);
|
|
|
|
//
|
|
// Take care of trivial cases first
|
|
//
|
|
if (uiTargetCodePage == uiSourceCodePage){
|
|
|
|
pszTargetString = new CHAR[lstrlen(pszSourceString) + 1];
|
|
if (pszTargetString == NULL) {
|
|
|
|
hr = E_OUTOFMEMORY ;
|
|
DebugTrace(0,"alloc for pszTargetString failed hr = %08lx", hr);
|
|
goto CLEANUP ;
|
|
|
|
}
|
|
|
|
lstrcpy(pszTargetString,pszSourceString);
|
|
*ppszTargetString = pszTargetString;
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
|
|
//
|
|
// If case is not trivial, call into HrCodePageConvertInternal
|
|
//
|
|
hr = HrCodePageConvertInternal (
|
|
uiSourceCodePage, // source code page
|
|
pszSourceString, // source string
|
|
uiTargetCodePage, // target code page
|
|
NULL, // target string or NULL
|
|
0, // cb in target string or 0
|
|
ppszTargetString ); // NULL or p to where target string is returned
|
|
|
|
|
|
if (FAILED(hr))
|
|
DebugTrace(0,"HrCodePageConvertInternal failed hr = %08lx", hr);
|
|
|
|
|
|
CLEANUP:
|
|
|
|
DebugTrace(0,"returning %08lx", hr);
|
|
TraceFunctLeave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: HrCodePageConvertInternal
|
|
//
|
|
// Synopsis: Converts a zero terminated string to a different code page
|
|
//
|
|
// NOTES:
|
|
// pointers to Source and Target strings may be the same
|
|
//
|
|
// Arguments:
|
|
// uiSourceCodePage Source Code Page
|
|
// pszSourceString Source String
|
|
// uiTargetCodePage Target Code Page
|
|
//
|
|
// either:
|
|
// pszTargetString p to buffer prealloc by caller where target string
|
|
// is returned
|
|
// cbTargetStringBuffer cbytes in prealloc buffer for target string
|
|
// ppszTargetString NULL,
|
|
//
|
|
// or:
|
|
// pszTargetString NULL
|
|
// cbTargetStringBuffer 0
|
|
// ppszTargetString p to where target string is to be returned
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_OUTOFMEMORY if dynamic allocation of an internal buffer fails
|
|
// HRESULT_FROM_WIN32(GetLastError()) if Wide<->Multibyte calls fail
|
|
//
|
|
// History:
|
|
// aszafer 2000/03/29 created
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT HrCodePageConvertInternal (
|
|
IN UINT uiSourceCodePage, // source code page
|
|
IN LPSTR pszSourceString, // source string
|
|
IN UINT uiTargetCodePage, // target code page
|
|
OUT LPSTR pszTargetString, // target string or NULL
|
|
IN int cbTargetStringBuffer, // cb in target string or 0
|
|
OUT LPSTR* ppszTargetString ) // NULL or p to where target string is returned
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
WCHAR wsz[TEMPBUFFER_WCHARS] ;
|
|
int cwch = sizeof(wsz)/sizeof(WCHAR) ;
|
|
WCHAR* pwsz = wsz ;
|
|
CHAR* psz ;
|
|
int iSourceStringLengh ;
|
|
int cch ;
|
|
BOOL fAlloc1 = FALSE ;
|
|
BOOL fAlloc2 = FALSE ;
|
|
|
|
TraceFunctEnter("HrCodePageConvertInternal");
|
|
|
|
_ASSERT(((pszTargetString != NULL) && (cbTargetStringBuffer != 0)) ||
|
|
(ppszTargetString != NULL) );
|
|
|
|
psz = pszTargetString;
|
|
cch = cbTargetStringBuffer;
|
|
|
|
//
|
|
// If stack allocated temp buffer may not be sufficient
|
|
// for unicode string, allocate from heap
|
|
//
|
|
iSourceStringLengh = lstrlen(pszSourceString) + 1 ; //includes terminator
|
|
if (iSourceStringLengh > TEMPBUFFER_WCHARS){
|
|
//
|
|
// Here we assume that each character in the source code page
|
|
// can be represented by a single unicode character
|
|
//
|
|
cwch = iSourceStringLengh ;
|
|
pwsz = new WCHAR[iSourceStringLengh];
|
|
|
|
if (pwsz == NULL) {
|
|
|
|
hr = E_OUTOFMEMORY ;
|
|
DebugTrace(0,"alloc for pwsz failed hr = %08lx", hr);
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
fAlloc1 = TRUE ;
|
|
}
|
|
|
|
//
|
|
// Convert to unicode
|
|
//
|
|
cwch = MultiByteToWideChar(
|
|
uiSourceCodePage, // code page
|
|
0, // dwFlags
|
|
pszSourceString, // string to map
|
|
-1 , // number of bytes in string
|
|
pwsz, // wide-character buffer
|
|
cwch ); // size of buffer
|
|
|
|
if(cwch == 0) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DebugTrace(0,"MultiByteToWideChar2 failed hr = %08lx", hr);
|
|
_ASSERT(FAILED(hr));
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
//
|
|
// If cbTargetStringBuffer == 0, allocate space for target string
|
|
//
|
|
if (cbTargetStringBuffer == 0){
|
|
|
|
cch = WideCharToMultiByte(
|
|
uiTargetCodePage, // codepage
|
|
0, // dwFlags
|
|
pwsz, // wide-character string
|
|
cwch, // number of wchars in string
|
|
NULL, // buffer for new string
|
|
0, // size of buffer
|
|
NULL, // default for unmappable chars
|
|
NULL); // set when default char used
|
|
|
|
if(cch == 0) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DebugTrace(0,"WideCharToMultiByte1 failed hr = %08lx", hr);
|
|
_ASSERT(FAILED(hr));
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
|
|
psz = new CHAR[cch];
|
|
if (psz == NULL) {
|
|
|
|
hr = E_OUTOFMEMORY ;
|
|
DebugTrace(0,"alloc for psz failed hr = %08lx", hr);
|
|
goto CLEANUP ;
|
|
|
|
}
|
|
fAlloc2 = TRUE ;
|
|
}
|
|
|
|
//
|
|
// Convert to target code page
|
|
//
|
|
cch = WideCharToMultiByte(
|
|
uiTargetCodePage, // codepage
|
|
0, // dwFlags
|
|
pwsz, // wide-character string
|
|
cwch, // number of wchars in string
|
|
psz, // buffer for new string
|
|
cch, // size of buffer
|
|
NULL, // default for unmappable chars
|
|
NULL); // set when default char used
|
|
|
|
if(cch == 0) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DebugTrace(0,"WideCharToMultiByte2 failed hr = %08lx", hr);
|
|
_ASSERT(FAILED(hr));
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
//
|
|
// If target string had to be allocated, output pointer to it
|
|
//
|
|
if (cbTargetStringBuffer == 0)
|
|
*ppszTargetString = psz ;
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if (fAlloc1)
|
|
delete[] pwsz ;
|
|
|
|
if (FAILED(hr)){
|
|
|
|
if (fAlloc2)
|
|
delete[] psz ;
|
|
}
|
|
|
|
DebugTrace(0,"returning %08lx", hr);
|
|
TraceFunctLeave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: HrCodePageConvertFree
|
|
//
|
|
// Synopsis: Use to free memory if HrCodePageConvert or HrCodePageConvertInternal
|
|
// allocate buffer for target string
|
|
//
|
|
// Arguments:
|
|
// pszTargetString p to buffer to be freed
|
|
//
|
|
// History:
|
|
// aszafer 2000/03/29 created
|
|
//
|
|
//-------------------------------------------------------------
|
|
VOID HrCodePageConvertFree(LPSTR pszTargetString)
|
|
{
|
|
_ASSERT(pszTargetString);
|
|
|
|
delete pszTargetString;
|
|
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: wcsutf8cmpi
|
|
//
|
|
// Synopsis: Compare a Unicode string to a UTF8 string and see
|
|
// if they are identical
|
|
//
|
|
// Arguments: pwszStr1 - Unicode string
|
|
// pszStr2 - UTF8 string
|
|
//
|
|
// Returns: S_OK - identical
|
|
// S_FALSE - different
|
|
// E_* - error
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT wcsutf8cmpi(LPWSTR pwszStr1, LPCSTR pszStr2) {
|
|
int rc;
|
|
HRESULT hr;
|
|
WCHAR wszStr2[TEMPBUFFER_WCHARS];
|
|
LPWSTR pwszStr2 = wszStr2;
|
|
DWORD cStr2;
|
|
|
|
// convert string 2 to wide
|
|
cStr2 = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, 0);
|
|
if (cStr2 > (sizeof(wszStr2) / sizeof(WCHAR)) ) {
|
|
pwszStr2 = new WCHAR[cStr2 + 1];
|
|
if (pwszStr2 == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
rc = MultiByteToWideChar(CP_UTF8, 0, pszStr2, -1, pwszStr2, cStr2);
|
|
if (rc == 0) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
// do the comparison
|
|
rc = _wcsicmp(pwszStr1, pwszStr2);
|
|
if (rc == 0) hr = S_OK; else hr = S_FALSE;
|
|
|
|
Exit:
|
|
if (pwszStr2 != wszStr2) {
|
|
delete[] pwszStr2;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CodePageConvertFree
|
|
//
|
|
// Synopsis: Free memory allocated in CodePageConvert
|
|
//
|
|
// Arguments:
|
|
// pwszTargetString: Memory to free
|
|
//
|
|
// Returns: NOTHING
|
|
//
|
|
// History:
|
|
// jstamerj 2001/03/20 16:37:28: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
VOID CodePageConvertFree(
|
|
IN LPWSTR pwszTargetString)
|
|
{
|
|
delete [] pwszTargetString;
|
|
} // CodePageConvertFree
|
|
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: HrConvertToUnicodeWithAlloc
|
|
//
|
|
// Synopsis: Convet an MBCS string to unicode (And allocate the
|
|
// unicode string buffer)
|
|
//
|
|
// Arguments:
|
|
// uiSourceCodePage: Source code page
|
|
// pszSourceString: Source string
|
|
// ppwszTargetString: Out parameter -- will be set to pointer to
|
|
// allocated buffer. This should be free'd with CodePageConvertFree
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// E_OUTOFMEMORY
|
|
// or error from MultiByteToWideChar
|
|
//
|
|
// History:
|
|
// jstamerj 2001/03/20 16:38:52: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
HRESULT HrConvertToUnicodeWithAlloc(
|
|
IN UINT uiSourceCodePage,
|
|
IN LPSTR pszSourceString,
|
|
OUT LPWSTR* ppwszTargetString)
|
|
{
|
|
return HrConvertToUnicodeWithAlloc(
|
|
uiSourceCodePage,
|
|
lstrlen(pszSourceString),
|
|
pszSourceString,
|
|
ppwszTargetString);
|
|
}
|
|
|
|
HRESULT HrConvertToUnicodeWithAlloc(
|
|
IN UINT uiSourceCodePage,
|
|
IN DWORD dwcbSourceString,
|
|
IN LPSTR pszSourceString,
|
|
OUT LPWSTR* ppwszTargetString)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int ich = 0;
|
|
int ich2 = 0;
|
|
LPWSTR pwszTmp = NULL;
|
|
TraceFunctEnterEx((LPARAM)0, "HrConvertToUnicodeWithAlloc");
|
|
|
|
ich = MultiByteToWideChar(
|
|
uiSourceCodePage,
|
|
0,
|
|
pszSourceString,
|
|
dwcbSourceString,
|
|
NULL,
|
|
0);
|
|
if(ich == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
ErrorTrace((LPARAM)0, "MultiByteToWideChar failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
pwszTmp = new WCHAR[ich + 1];
|
|
if(pwszTmp == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
ich2 = MultiByteToWideChar(
|
|
uiSourceCodePage,
|
|
0,
|
|
pszSourceString,
|
|
dwcbSourceString,
|
|
pwszTmp,
|
|
ich);
|
|
if(ich2 == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
ErrorTrace((LPARAM)0, "MultiByteToWideChar2 failed hr %08lx", hr);
|
|
goto CLEANUP;
|
|
}
|
|
pwszTmp[ich] = '\0';
|
|
//
|
|
// Success!
|
|
//
|
|
*ppwszTargetString = pwszTmp;
|
|
|
|
CLEANUP:
|
|
if(FAILED(hr))
|
|
{
|
|
if(pwszTmp)
|
|
delete [] pwszTmp;
|
|
}
|
|
DebugTrace((LPARAM)0, "returning %08lx", hr);
|
|
TraceFunctLeaveEx((LPARAM)0);
|
|
return hr;
|
|
} // HrConvertToUnicodeWithAlloc
|