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.
 
 
 
 
 
 

1203 lines
31 KiB

//--------------------------------------------------------------------------
// WrapWide.cpp
//--------------------------------------------------------------------------
#include "pch.hxx"
#include "dllmain.h"
// --------------------------------------------------------------------------
// AllocateStringA
// --------------------------------------------------------------------------
LPSTR AllocateStringA(DWORD cch)
{
// Allocate It
return((LPSTR)g_pMalloc->Alloc((cch + 1) * sizeof(CHAR)));
}
// --------------------------------------------------------------------------
// AllocateStringW
// --------------------------------------------------------------------------
LPWSTR AllocateStringW(DWORD cch)
{
// Allocate It
return((LPWSTR)g_pMalloc->Alloc((cch + 1) * sizeof(WCHAR)));
}
// --------------------------------------------------------------------------
// DuplicateStringA
// --------------------------------------------------------------------------
LPSTR DuplicateStringA(LPCSTR psz)
{
// Locals
HRESULT hr=S_OK;
DWORD cch;
LPSTR pszT;
// Trace
TraceCall("DuplicateStringA");
// Invalid Arg
if (NULL == psz)
return(NULL);
// Length
cch = lstrlenA(psz);
// Allocate
IF_NULLEXIT(pszT = AllocateStringA(cch));
// Copy (including NULL)
CopyMemory(pszT, psz, (cch + 1) * sizeof(CHAR));
exit:
// Done
return(pszT);
}
// --------------------------------------------------------------------------
// DuplicateStringW
// --------------------------------------------------------------------------
LPWSTR DuplicateStringW(LPCWSTR psz)
{
// Locals
HRESULT hr=S_OK;
DWORD cch;
LPWSTR pszT;
// Trace
TraceCall("DuplicateStringW");
// Invalid Arg
if (NULL == psz)
return(NULL);
// Length
cch = lstrlenW(psz);
// Allocate
IF_NULLEXIT(pszT = AllocateStringW(cch));
// Copy (including NULL)
CopyMemory(pszT, psz, (cch + 1) * sizeof(WCHAR));
exit:
// Done
return(pszT);
}
// --------------------------------------------------------------------------
// ConvertToUnicode
// --------------------------------------------------------------------------
LPWSTR ConvertToUnicode(UINT cp, LPCSTR pcszSource)
{
// Locals
HRESULT hr=S_OK;
INT cchNarrow;
INT cchWide;
LPWSTR pwszDup=NULL;
// No Source
if (pcszSource == NULL)
goto exit;
// Length
cchNarrow = lstrlenA(pcszSource) + 1;
// Determine how much space is needed for translated widechar
cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, NULL, 0);
// Error
if (cchWide == 0)
goto exit;
// Alloc temp buffer
IF_NULLEXIT(pwszDup = AllocateStringW(cchWide));
// Do the actual translation
cchWide = MultiByteToWideChar(cp, MB_PRECOMPOSED, pcszSource, cchNarrow, pwszDup, cchWide+1);
// Error
if (cchWide == 0)
{
SafeMemFree(pwszDup);
goto exit;
}
exit:
// Done
return(pwszDup);
}
// --------------------------------------------------------------------------
// ConvertToANSI
// --------------------------------------------------------------------------
LPSTR ConvertToANSI(UINT cp, LPCWSTR pcwszSource)
{
// Locals
HRESULT hr=S_OK;
INT cchNarrow;
INT cchWide;
LPSTR pszDup=NULL;
// No Source
if (pcwszSource == NULL)
goto exit;
// Length
cchWide = lstrlenW(pcwszSource) + 1;
// Determine how much space is needed for translated widechar
cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, NULL, 0, NULL, NULL);
// Error
if (cchNarrow == 0)
goto exit;
// Alloc temp buffer
IF_NULLEXIT(pszDup = AllocateStringA(cchNarrow + 1));
// Do the actual translation
cchNarrow = WideCharToMultiByte(cp, 0, pcwszSource, cchWide, pszDup, cchNarrow + 1, NULL, NULL);
// Error
if (cchNarrow == 0)
{
SafeMemFree(pszDup);
goto exit;
}
exit:
// Done
return(pszDup);
}
//--------------------------------------------------------------------------
// GetFullPathNameWrapW
//--------------------------------------------------------------------------
DWORD GetFullPathNameWrapW(LPCWSTR pwszFileName, DWORD nBufferLength,
LPWSTR pwszBuffer, LPWSTR *ppwszFilePart)
{
// Locals
HRESULT hr=S_OK;
DWORD dwReturn;
LPSTR pszFileName=NULL;
LPSTR pszFilePart=NULL;
LPSTR pszBuffer=NULL;
DWORD dwError=0;
// Trace
TraceCall("GetFullPathNameWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(GetFullPathNameW(pwszFileName, nBufferLength, pwszBuffer, ppwszFilePart));
// Convert
if (pwszFileName)
{
// To ANSI
IF_NULLEXIT(pszFileName = ConvertToANSI(CP_ACP, pwszFileName));
}
// Allocate
if (pwszBuffer && nBufferLength)
{
// Allocate a Buffer
IF_NULLEXIT(pszBuffer = AllocateStringA(nBufferLength));
}
// Call
dwReturn = GetFullPathNameA(pszFileName, nBufferLength, pszBuffer, &pszFilePart);
// Save Last Error
dwError = GetLastError();
// If we have a buffer
if (pwszBuffer && nBufferLength)
{
// Convert to Unicode
if (0 == (dwReturn = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszBuffer, -1, pwszBuffer, nBufferLength)))
{
TraceResult(E_FAIL);
goto exit;
}
if(dwReturn < nBufferLength)
pwszBuffer[dwReturn] = L'\0';
else
Assert(FALSE);
}
// Set ppwszFilePath
if (ppwszFilePart)
{
// Do we have a file part
if (pszFilePart && pszBuffer && pwszBuffer && nBufferLength)
{
// Set Length
DWORD cch = (DWORD)(pszFilePart - pszBuffer);
// Set
*ppwszFilePart = (LPWSTR)((LPBYTE)pwszBuffer + (cch * sizeof(WCHAR)));
}
// Otherwise
else
*ppwszFilePart = NULL;
}
exit:
// Cleanup
g_pMalloc->Free(pszFileName);
g_pMalloc->Free(pszBuffer);
// Save Last Error
SetLastError(dwError);
// Done
return(SUCCEEDED(hr) ? dwReturn : 0);
}
//--------------------------------------------------------------------------
// CreateMutexWrapW
//--------------------------------------------------------------------------
HANDLE CreateMutexWrapW(LPSECURITY_ATTRIBUTES pMutexAttributes,
BOOL bInitialOwner, LPCWSTR pwszName)
{
// Locals
HRESULT hr=S_OK;
HANDLE hMutex=NULL;
LPSTR pszName=NULL;
DWORD dwError=0;
// Trace
TraceCall("CreateMutexWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(CreateMutexW(pMutexAttributes, bInitialOwner, pwszName));
// Convert to Ansi
if (pwszName)
{
// To ANSI
IF_NULLEXIT(pszName = ConvertToANSI(CP_ACP, pwszName));
}
// Call ANSI
hMutex = CreateMutexA(pMutexAttributes, bInitialOwner, pszName);
// Save Last Error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszName);
// Save Last Error
SetLastError(dwError);
// Done
return(hMutex);
}
//--------------------------------------------------------------------------
// CharLowerBuffWrapW
//--------------------------------------------------------------------------
DWORD CharLowerBuffWrapW(LPWSTR pwsz, DWORD cch)
{
// Locals
HRESULT hr=S_OK;
LPSTR psz=NULL;
DWORD dwReturn=0;
DWORD dwError=0;
DWORD cchMax;
// Trace
TraceCall("CharLowerBuffWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(CharLowerBuffW(pwsz, cch));
// Convert
if (pwsz)
{
// Convert to ANSI
IF_NULLEXIT(psz = ConvertToANSI(CP_ACP, pwsz));
}
// Call ANSI
dwReturn = CharLowerBuffA(psz, cch);
// Get the last error
dwError = GetLastError();
// If psz
if (psz)
{
// Convert back to unicode
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, psz, -1, pwsz, cch);
}
exit:
// Cleanup
g_pMalloc->Free(psz);
// Save the last error
SetLastError(dwError);
// Done
return(dwReturn);
}
//--------------------------------------------------------------------------
// CreateFileWrapW
//--------------------------------------------------------------------------
HANDLE CreateFileWrapW(LPCWSTR pwszFileName, DWORD dwDesiredAccess,
DWORD dwShareMode, LPSECURITY_ATTRIBUTES pSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
// Locals
HRESULT hr=S_OK;
HANDLE hFile=INVALID_HANDLE_VALUE;
LPSTR pszFileName=NULL;
DWORD dwError=0;
// Trace
TraceCall("CreateFileWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(CreateFileW(pwszFileName, dwDesiredAccess, dwShareMode, pSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile));
// To ANSI
if (pwszFileName)
{
// Convert to ANSI
IF_NULLEXIT(pszFileName = ConvertToANSI(CP_ACP, pwszFileName));
}
// Call ANSI
hFile = CreateFileA(pszFileName, dwDesiredAccess, dwShareMode, pSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
// Save the last Error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszFileName);
// Set Last Error
SetLastError(dwError);
// Done
return(hFile);
}
//--------------------------------------------------------------------------
// GetDiskFreeSpaceWrapW
//--------------------------------------------------------------------------
BOOL GetDiskFreeSpaceWrapW(LPCWSTR pwszRootPathName, LPDWORD pdwSectorsPerCluster,
LPDWORD pdwBytesPerSector, LPDWORD pdwNumberOfFreeClusters,
LPDWORD pdwTotalNumberOfClusters)
{
// Locals
HRESULT hr=S_OK;
BOOL fReturn=FALSE;
LPSTR pszRootPathName=NULL;
DWORD dwError=0;
// Trace
TraceCall("GetClassInfoWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(GetDiskFreeSpaceW(pwszRootPathName, pdwSectorsPerCluster, pdwBytesPerSector, pdwNumberOfFreeClusters, pdwTotalNumberOfClusters));
// To ANSI
if (pwszRootPathName)
{
// to ANSI
IF_NULLEXIT(pszRootPathName = ConvertToANSI(CP_ACP, pwszRootPathName));
}
// Call ANSI
fReturn = GetDiskFreeSpaceA(pszRootPathName, pdwSectorsPerCluster, pdwBytesPerSector, pdwNumberOfFreeClusters, pdwTotalNumberOfClusters);
// Save Last Error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszRootPathName);
// Save Last Error
SetLastError(dwError);
// Done
return(fReturn);
}
//--------------------------------------------------------------------------
// OpenFileMappingWrapW
//--------------------------------------------------------------------------
HANDLE OpenFileMappingWrapW(DWORD dwDesiredAccess, BOOL bInheritHandle,
LPCWSTR pwszName)
{
// Locals
HRESULT hr=S_OK;
HANDLE hMapping=NULL;
LPSTR pszName=NULL;
DWORD dwError=0;
// Trace
TraceCall("OpenFileMappingWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(OpenFileMappingW(dwDesiredAccess, bInheritHandle, pwszName));
// To ANSI
if (pwszName)
{
// to ANSI
IF_NULLEXIT(pszName = ConvertToANSI(CP_ACP, pwszName));
}
// Call ANSI
hMapping = OpenFileMappingA(dwDesiredAccess, bInheritHandle, pszName);
// Save the last error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszName);
// Set the last error
SetLastError(dwError);
// Done
return(hMapping);
}
//--------------------------------------------------------------------------
// CreateFileMappingWrapW
//--------------------------------------------------------------------------
HANDLE CreateFileMappingWrapW(HANDLE hFile, LPSECURITY_ATTRIBUTES pFileMappingAttributes,
DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow,
LPCWSTR pwszName)
{
// Locals
HRESULT hr=S_OK;
HANDLE hMapping=NULL;
LPSTR pszName=NULL;
DWORD dwError=0;
// Trace
TraceCall("OpenFileMappingWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(CreateFileMappingW(hFile, pFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, pwszName));
// To ANSI
if (pwszName)
{
// to ANSI
IF_NULLEXIT(pszName = ConvertToANSI(CP_ACP, pwszName));
}
// Call ANSI
hMapping = CreateFileMappingA(hFile, pFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, pszName);
// Save last error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszName);
// Save last error
SetLastError(dwError);
// Done
return(hMapping);
}
//--------------------------------------------------------------------------
// MoveFileWrapW
//--------------------------------------------------------------------------
BOOL MoveFileWrapW(LPCWSTR pwszExistingFileName, LPCWSTR pwszNewFileName)
{
// Locals
HRESULT hr=S_OK;
BOOL fReturn=FALSE;
LPSTR pszExistingFileName=NULL;
LPSTR pszNewFileName=NULL;
DWORD dwError=0;
// Trace
TraceCall("MoveFileWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(MoveFileW(pwszExistingFileName, pwszNewFileName));
// To ANSI
if (pwszExistingFileName)
{
// to ANSI
IF_NULLEXIT(pszExistingFileName = ConvertToANSI(CP_ACP, pwszExistingFileName));
}
// To ANSI
if (pwszNewFileName)
{
// to ANSI
IF_NULLEXIT(pszNewFileName = ConvertToANSI(CP_ACP, pwszNewFileName));
}
// Call ANSI
fReturn = MoveFileA(pszExistingFileName, pszNewFileName);
// Save the last Error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszExistingFileName);
g_pMalloc->Free(pszNewFileName);
// Save the last Error
SetLastError(dwError);
// Done
return(fReturn);
}
//--------------------------------------------------------------------------
// DeleteFileWrapW
//--------------------------------------------------------------------------
BOOL DeleteFileWrapW(LPCWSTR pwszFileName)
{
// Locals
HRESULT hr=S_OK;
BOOL fReturn=FALSE;
LPSTR pszFileName=NULL;
DWORD dwError=0;
// Trace
TraceCall("DeleteFileWrapW");
// If WinNT, call Unicode Version
if (g_fIsWinNT)
return(DeleteFileW(pwszFileName));
// To ANSI
if (pwszFileName)
{
// to ANSI
IF_NULLEXIT(pszFileName = ConvertToANSI(CP_ACP, pwszFileName));
}
// Call ANSI
fReturn = DeleteFileA(pszFileName);
// Save the last Error
dwError = GetLastError();
exit:
// Cleanup
g_pMalloc->Free(pszFileName);
// Save the last Error
SetLastError(dwError);
// Done
return(fReturn);
}
/**********************************************************************************\
* from msoert ported by YSt 6/25/99
*
* bobn 6/23/99
*
* The following code was ported from ShlWapi. There were problems with
* our implementation on Win95 and it seemed prudent to have a solution
* without a bunch of special cases.
*
*
\**********************************************************************************/
#define DBCS_CHARSIZE (2)
int DDB_MBToWCS(LPSTR pszIn, int cchIn, LPWSTR *ppwszOut)
{
int cch = 0;
int cbAlloc;
if ((0 != cchIn) && (NULL != ppwszOut))
{
cchIn++;
cbAlloc = cchIn * sizeof(WCHAR);
*ppwszOut = (LPWSTR)LocalAlloc(LMEM_FIXED, cbAlloc);
if (NULL != *ppwszOut)
{
cch = MultiByteToWideChar(CP_ACP, 0, pszIn, cchIn, *ppwszOut, cchIn);
if (!cch)
{
LocalFree(*ppwszOut);
*ppwszOut = NULL;
}
else
{
cch--; // Just return the number of characters
}
}
}
return cch;
}
int DDB_WCSToMB(LPCWSTR pwszIn, int cchIn, LPSTR *ppszOut)
{
int cch = 0;
int cbAlloc;
if ((0 != cchIn) && (NULL != ppszOut))
{
cchIn++;
cbAlloc = cchIn * DBCS_CHARSIZE;
*ppszOut = (LPSTR)LocalAlloc(LMEM_FIXED, cbAlloc);
if (NULL != *ppszOut)
{
cch = WideCharToMultiByte(CP_ACP, 0, pwszIn, cchIn,
*ppszOut, cbAlloc, NULL, NULL);
if (!cch)
{
LocalFree(*ppszOut);
*ppszOut = NULL;
}
else
{
cch--; // Just return the number of characters
}
}
}
return cch;
}
/****************************** Module Header ******************************\
* Module Name: wsprintf.c
*
* Copyright (c) 1985-91, Microsoft Corporation
* sprintf.c
*
* Implements Windows friendly versions of sprintf and vsprintf
*
* History:
* 2-15-89 craigc Initial
* 11-12-90 MikeHar Ported from windows 3
\***************************************************************************/
/* Max number of characters. Doesn't include termination character */
#define out(c) if (cchLimit) {*lpOut++=(c); cchLimit--;} else goto errorout
/***************************************************************************\
* DDB_SP_GetFmtValueW
*
* reads a width or precision value from the format string
*
* History:
* 11-12-90 MikeHar Ported from windows 3
* 07-27-92 GregoryW Created Unicode version (copied from DDB_SP_GetFmtValue)
\***************************************************************************/
LPCWSTR DDB_SP_GetFmtValueW(
LPCWSTR lpch,
int *lpw)
{
int ii = 0;
/* It might not work for some locales or digit sets */
while (*lpch >= L'0' && *lpch <= L'9') {
ii *= 10;
ii += (int)(*lpch - L'0');
lpch++;
}
*lpw = ii;
/*
* return the address of the first non-digit character
*/
return lpch;
}
/***************************************************************************\
* DDB_SP_PutNumberW
*
* Takes an unsigned long integer and places it into a buffer, respecting
* a buffer limit, a radix, and a case select (upper or lower, for hex).
*
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW need to increment lpstr after assignment of mod
* 02-11-92 GregoryW temporary version until we have C runtime support
\***************************************************************************/
int DDB_SP_PutNumberW(
LPWSTR lpstr,
DWORD n,
int limit,
DWORD radix,
int uppercase,
int *pcch)
{
DWORD mod;
*pcch = 0;
/* It might not work for some locales or digit sets */
if(uppercase)
uppercase = 'A'-'0'-10;
else
uppercase = 'a'-'0'-10;
if (limit) {
do {
mod = n % radix;
n /= radix;
mod += '0';
if (mod > '9')
mod += uppercase;
*lpstr++ = (WCHAR)mod;
(*pcch)++;
} while((*pcch < limit) && n);
}
return (n == 0) && (*pcch > 0);
}
/***************************************************************************\
* DDB_SP_ReverseW
*
* reverses a string in place
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW fixed boundary conditions; removed count
* 02-11-92 GregoryW temporary version until we have C runtime support
\***************************************************************************/
void DDB_SP_ReverseW(
LPWSTR lpFirst,
LPWSTR lpLast)
{
WCHAR ch;
while(lpLast > lpFirst){
ch = *lpFirst;
*lpFirst++ = *lpLast;
*lpLast-- = ch;
}
}
/***************************************************************************\
* wvsprintfW (API)
*
* wsprintfW() calls this function.
*
* History:
* 11-Feb-1992 GregoryW copied xwvsprintf
* Temporary hack until we have C runtime support
* 1-22-97 tnoonan Converted to wvnsprintfW
\***************************************************************************/
int DDB_wvnsprintfW(
LPWSTR lpOut,
int cchLimitIn,
LPCWSTR lpFmt,
va_list arglist)
{
BOOL fAllocateMem = FALSE;
WCHAR prefix, fillch;
int left, width, prec, size, sign, radix, upper, hprefix;
int cchLimit = --cchLimitIn, cch, cchAvailable;
LPWSTR lpT, lpTWC;
LPSTR psz;
va_list varglist = arglist;
union {
long l;
unsigned long ul;
CHAR sz[2];
WCHAR wsz[2];
} val;
if (cchLimit < 0)
return 0;
while (*lpFmt != 0) {
if (*lpFmt == L'%') {
/*
* read the flags. These can be in any order
*/
left = 0;
prefix = 0;
while (*++lpFmt) {
if (*lpFmt == L'-')
left++;
else if (*lpFmt == L'#')
prefix++;
else
break;
}
/*
* find fill character
*/
if (*lpFmt == L'0') {
fillch = L'0';
lpFmt++;
} else
fillch = L' ';
/*
* read the width specification
*/
lpFmt = DDB_SP_GetFmtValueW(lpFmt, &cch);
width = cch;
/*
* read the precision
*/
if (*lpFmt == L'.') {
lpFmt = DDB_SP_GetFmtValueW(++lpFmt, &cch);
prec = cch;
} else
prec = -1;
/*
* get the operand size
* default size: size == 0
* long number: size == 1
* wide chars: size == 2
* It may be a good idea to check the value of size when it
* is tested for non-zero below (IanJa)
*/
hprefix = 0;
if ((*lpFmt == L'w') || (*lpFmt == L't')) {
size = 2;
lpFmt++;
} else if (*lpFmt == L'l') {
size = 1;
lpFmt++;
} else {
size = 0;
if (*lpFmt == L'h') {
lpFmt++;
hprefix = 1;
}
}
upper = 0;
sign = 0;
radix = 10;
switch (*lpFmt) {
case 0:
goto errorout;
case L'i':
case L'd':
size=1;
sign++;
/*** FALL THROUGH to case 'u' ***/
case L'u':
/* turn off prefix if decimal */
prefix = 0;
donumeric:
/* special cases to act like MSC v5.10 */
if (left || prec >= 0)
fillch = L' ';
/*
* if size == 1, "%lu" was specified (good);
* if size == 2, "%wu" was specified (bad)
*/
if (size) {
val.l = va_arg(varglist, LONG);
} else if (sign) {
val.l = va_arg(varglist, SHORT);
} else {
val.ul = va_arg(varglist, unsigned);
}
if (sign && val.l < 0L)
val.l = -val.l;
else
sign = 0;
lpT = lpOut;
/*
* blast the number backwards into the user buffer
* DDB_SP_PutNumberW returns FALSE if it runs out of space
*/
if (!DDB_SP_PutNumberW(lpOut, val.l, cchLimit, radix, upper, &cch))
{
break;
}
// Now we have the number backwards, calculate how much
// more buffer space we'll need for this number to
// format correctly.
cchAvailable = cchLimit - cch;
width -= cch;
prec -= cch;
if (prec > 0)
{
width -= prec;
cchAvailable -= prec;
}
if (width > 0)
{
cchAvailable -= width - (sign ? 1 : 0);
}
if (sign)
{
cchAvailable--;
}
if (cchAvailable < 0)
{
break;
}
// We have enough space to format the buffer as requested
// without overflowing.
lpOut += cch;
cchLimit -= cch;
/*
* fill to the field precision
*/
while (prec-- > 0)
out(L'0');
if (width > 0 && !left) {
/*
* if we're filling with spaces, put sign first
*/
if (fillch != L'0') {
if (sign) {
sign = 0;
out(L'-');
width--;
}
if (prefix) {
out(prefix);
out(L'0');
prefix = 0;
}
}
if (sign)
width--;
/*
* fill to the field width
*/
while (width-- > 0)
out(fillch);
/*
* still have a sign?
*/
if (sign)
out(L'-');
if (prefix) {
out(prefix);
out(L'0');
}
/*
* now reverse the string in place
*/
DDB_SP_ReverseW(lpT, lpOut - 1);
} else {
/*
* add the sign character
*/
if (sign) {
out(L'-');
width--;
}
if (prefix) {
out(prefix);
out(L'0');
}
/*
* reverse the string in place
*/
DDB_SP_ReverseW(lpT, lpOut - 1);
/*
* pad to the right of the string in case left aligned
*/
while (width-- > 0)
out(fillch);
}
break;
case L'X':
upper++;
/*** FALL THROUGH to case 'x' ***/
case L'x':
radix = 16;
if (prefix)
if (upper)
prefix = L'X';
else
prefix = L'x';
goto donumeric;
case L'c':
if (!size && !hprefix) {
size = 1; // force WCHAR
}
/*** FALL THROUGH to case 'C' ***/
case L'C':
/*
* if size == 0, "%C" or "%hc" was specified (CHAR);
* if size == 1, "%c" or "%lc" was specified (WCHAR);
* if size == 2, "%wc" or "%tc" was specified (WCHAR)
*/
cch = 1; /* One character must be copied to the output buffer */
if (size) {
val.wsz[0] = va_arg(varglist, WCHAR);
val.wsz[1] = 0;
lpT = val.wsz;
goto putwstring;
} else {
val.sz[0] = va_arg(varglist, CHAR);
val.sz[1] = 0;
psz = (LPSTR)(val.sz);
goto putstring;
}
case L's':
if (!size && !hprefix) {
size = 1; // force LPWSTR
}
/*** FALL THROUGH to case 'S' ***/
case L'S':
/*
* if size == 0, "%S" or "%hs" was specified (LPSTR)
* if size == 1, "%s" or "%ls" was specified (LPWSTR);
* if size == 2, "%ws" or "%ts" was specified (LPWSTR)
*/
if (size) {
lpT = va_arg(varglist, LPWSTR);
cch = lstrlenW(lpT);
} else {
psz = va_arg(varglist, LPSTR);
cch = lstrlen((LPCSTR)psz);
putstring:
cch = DDB_MBToWCS(psz, cch, &lpTWC);
fAllocateMem = (BOOL) cch;
lpT = lpTWC;
}
putwstring:
if (prec >= 0 && cch > prec)
cch = prec;
width -= cch;
if (left) {
while (cch--)
out(*lpT++);
while (width-- > 0)
out(fillch);
} else {
while (width-- > 0)
out(fillch);
while (cch--)
out(*lpT++);
}
if (fAllocateMem) {
LocalFree(lpTWC);
fAllocateMem = FALSE;
}
break;
default:
normalch:
out((WCHAR)*lpFmt);
break;
} /* END OF SWITCH(*lpFmt) */
} /* END OF IF(%) */ else
goto normalch; /* character not a '%', just do it */
/*
* advance to next format string character
*/
lpFmt++;
} /* END OF OUTER WHILE LOOP */
errorout:
*lpOut = 0;
if (fAllocateMem)
{
LocalFree(lpTWC);
}
return cchLimitIn - cchLimit;
}
int wsprintfWrapW( LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ... )
{
va_list arglist;
int ret;
Assert(lpOut);
Assert(lpFmt);
lpOut[0] = 0;
va_start(arglist, lpFmt);
ret = DDB_wvnsprintfW(lpOut, cchLimitIn, lpFmt, arglist);
va_end(arglist);
return ret;
}