windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dpnathlp/common/strutils.cpp
2020-09-26 16:20:57 +08:00

329 lines
7.9 KiB
C++

/*==========================================================================
*
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
*
* File: StrUtils.cpp
* Content: Implements the string utils
*@@BEGIN_MSINTERNAL
* History:
* Date By Reason
* ==== == ======
* 02/12/2000 rmt Created
* 08/28/2000 masonb Voice Merge: Added check of return code of MultiByteToWideChar in STR_jkAnsiToWide
* 09/16/2000 aarono fix STR_AllocAndConvertToANSI, ANSI doesn't mean 1 byte per DBCS character so we
* must allow up to 2 bytes per char when allocating buffer (B#43286)
*@@END_MSINTERNAL
*
***************************************************************************/
#include "dncmni.h"
/*
** WideToAnsi
*
* CALLED BY: everywhere
*
* PARAMETERS: lpStr - destination string
* lpWStr - string to convert
* cchStr - size of dest buffer
*
* DESCRIPTION:
* converts unicode lpWStr to ansi lpStr.
* fills in unconvertable chars w/ DPLAY_DEFAULT_CHAR "-"
*
*
* RETURNS: if cchStr is 0, returns the size required to hold the string
* otherwise, returns the number of chars converted
*
*/
#undef DPF_MODNAME
#define DPF_MODNAME "STR_jkWideToAnsi"
HRESULT STR_jkWideToAnsi(LPSTR lpStr,LPCWSTR lpWStr,int cchStr)
{
int rval;
BOOL fDefault = FALSE;
// can't call us w/ null pointer & non-zero cch
DNASSERT(lpWStr || !cchStr);
// use the default code page (CP_ACP)
// -1 indicates WStr must be null terminated
rval = WideCharToMultiByte(CP_ACP,0,lpWStr,-1,lpStr,cchStr,NULL,&fDefault);
DNASSERT(!fDefault);
if(rval == 0)
{
return E_FAIL;
}
else
{
return S_OK;
}
} // WideToAnsi
#undef DPF_MODNAME
#define DPF_MODNAME "STR_jkAnsiToWide"
/*
** AnsiToWide
*
* CALLED BY: everywhere
*
* PARAMETERS: lpWStr - dest string
* lpStr - string to convert
* cchWstr - size of dest buffer
*
* DESCRIPTION: converts Ansi lpStr to Unicode lpWstr
*
*/
HRESULT STR_jkAnsiToWide(LPWSTR lpWStr,LPCSTR lpStr,int cchWStr)
{
int rval;
DNASSERT(lpStr);
DNASSERT(lpWStr);
rval = MultiByteToWideChar(CP_ACP,0,lpStr,-1,lpWStr,cchWStr);
if (!rval)
{
DPFX(DPFPREP,0,"MultiByteToWideChar failed in STR_jkAnsiToWide");
return E_FAIL;
}
else
{
return S_OK;
}
} // AnsiToWide
#ifndef WINCE
#undef DPF_MODNAME
#define DPF_MODNAME "STR_WideToAnsi"
//**********************************************************************
// ------------------------------
// WideToANSI - convert a wide string to an ANSI string
//
// Entry: Pointer to source wide string
// Size of source string (in WCHAR units, -1 implies NULL-terminated)
// Pointer to ANSI string destination
// Pointer to size of ANSI destination
//
// Exit: Error code:
// E_FAIL = operation failed
// S_OK = operation succeded
// E_OUTOFMEMORY = destination buffer too small
// ------------------------------
HRESULT STR_WideToAnsi( const WCHAR *const pWCHARString,
const DWORD dwWCHARStringLength,
char *const pString,
DWORD *const pdwStringLength )
{
HRESULT hr;
int iReturn;
BOOL fDefault;
char cMilleniumHackBuffer;
char *pMilleniumHackBuffer;
DNASSERT( pWCHARString != NULL );
DNASSERT( pdwStringLength != NULL );
DNASSERT( ( pString != NULL ) || ( *pdwStringLength == 0 ) );
//
// Initialize. A hack needs to be implemented for WinME parameter
// validation, because when you pass zero for a destination size, you
// MUST have a valid pointer. Works on Win95, 98, NT4, Win2K, etc.....
//
hr = S_OK;
if ( *pdwStringLength == 0 )
{
pMilleniumHackBuffer = &cMilleniumHackBuffer;
}
else
{
pMilleniumHackBuffer = pString;
}
fDefault = FALSE;
iReturn = WideCharToMultiByte( CP_ACP, // code page (default ANSI)
0, // flags (none)
pWCHARString, // pointer to WCHAR string
dwWCHARStringLength, // size of WCHAR string
pMilleniumHackBuffer, // pointer to destination ANSI string
*pdwStringLength, // size of destination string
NULL, // pointer to default for unmappable characters (none)
&fDefault // pointer to flag indicating that default was used
);
if ( iReturn == 0 )
{
DWORD dwError;
dwError = GetLastError();
DPFX( DPFPREP, 0, "Failed to convert WCHAR to multi-byte! %d", dwError );
hr = E_FAIL;
}
else
{
if ( *pdwStringLength == 0 )
{
hr = E_OUTOFMEMORY;
}
else
{
DNASSERT( hr == S_OK );
}
*pdwStringLength = iReturn;
}
//
// if you hit this ASSERT it's because you've probably got ASCII text as your
// input WCHAR string. Double-check your input!!
//
DNASSERT( fDefault == FALSE );
return hr;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// ANSIToWide - convert an ANSI string to a wide string
//
// Entry: Pointer to source multi-byte (ANSI) string
// Size of source string (-1 imples NULL-terminated)
// Pointer to multi-byte string destination
// Pointer to size of multi-byte destination (in WCHAR units)
//
// Exit: Error code:
// E_FAIL = operation failed
// S_OK = operation succeded
// E_OUTOFMEMORY = destination buffer too small
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "STR_AnsiToWide"
HRESULT STR_AnsiToWide( const char *const pString,
const DWORD dwStringLength,
WCHAR *const pWCHARString,
DWORD *const pdwWCHARStringLength )
{
HRESULT hr;
int iReturn;
WCHAR MilleniumHackBuffer;
WCHAR *pMilleniumHackBuffer;
DNASSERT( pString != NULL );
DNASSERT( pdwWCHARStringLength != NULL );
DNASSERT( ( pWCHARString != NULL ) || ( *pdwWCHARStringLength == 0 ) );
//
// Initialize. A hack needs to be implemented for WinME parameter
// validation, because when you pass zero for a destination size, you
// MUST have a valid pointer. Works on Win95, 98, NT4, Win2K, etc.....
//
hr = S_OK;
if ( *pdwWCHARStringLength == 0 )
{
pMilleniumHackBuffer = &MilleniumHackBuffer;
}
else
{
pMilleniumHackBuffer = pWCHARString;
}
iReturn = MultiByteToWideChar( CP_ACP, // code page (default ANSI)
0, // flags (none)
pString, // pointer to multi-byte string
dwStringLength, // size of string (assume null-terminated)
pMilleniumHackBuffer, // pointer to destination wide-char string
*pdwWCHARStringLength // size of destination in WCHARs
);
if ( iReturn == 0 )
{
DWORD dwError;
dwError = GetLastError();
DPFX(DPFPREP, 0, "Failed to convert multi-byte to WCHAR! %d", dwError );
hr = E_FAIL;
}
else
{
if ( *pdwWCHARStringLength == 0 )
{
hr = E_OUTOFMEMORY;
}
else
{
DNASSERT( hr == S_OK );
}
*pdwWCHARStringLength = iReturn;
}
return hr;
}
//**********************************************************************
// WideToAnsi
//
// Convert a WCHAR (Wide) string to a CHAR (ANSI) string
//
// CHAR *pStr CHAR string
// WCHAR *pWStr WCHAR string
// int iStrSize size (in bytes) of buffer pointed to by lpStr
#undef DPF_MODNAME
#define DPF_MODNAME "STR_AllocAndConvertToANSI"
/*
** GetAnsiString
*
* CALLED BY: Everywhere
*
* PARAMETERS: *ppszAnsi - pointer to string
* lpszWide - string to copy
*
* DESCRIPTION: handy utility function
* allocs space for and converts lpszWide to ansi
*
* RETURNS: string length
*
*/
HRESULT STR_AllocAndConvertToANSI(LPSTR * ppszAnsi,LPCWSTR lpszWide)
{
int iStrLen;
BOOL bDefault;
DNASSERT(ppszAnsi);
if (!lpszWide)
{
*ppszAnsi = NULL;
return S_OK;
}
*ppszAnsi = (char*) DNMalloc((wcslen(lpszWide)*2+1)*sizeof(char));
if (!*ppszAnsi)
{
DPFX(DPFPREP,0, "could not get ansi string -- out of memory");
return E_OUTOFMEMORY;
}
iStrLen = WideCharToMultiByte(CP_ACP,0,lpszWide,-1,*ppszAnsi,wcslen(lpszWide)*2+1,
NULL,&bDefault);
return S_OK;
} // OSAL_AllocAndConvertToANSI
#endif // !WINCE