Leaked source code of windows server 2003
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

//+------------------------------------------------------------
//
// 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