mirror of https://github.com/tongzx/nt5src
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.
590 lines
19 KiB
590 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 2000-2001, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
convert.c
|
|
|
|
Abstract:
|
|
|
|
These functions make A->W and W->A translations of all types
|
|
easier.
|
|
|
|
StackAllocCheck
|
|
DevModeAfromW
|
|
DevModeWfromA
|
|
LogFontAfromW
|
|
Win32FindDataWfromA
|
|
TextMetricWfromA
|
|
NewTextMetricWfromA
|
|
NewTextMetricExWfromA
|
|
MenuItemInfoAfromW
|
|
CpgFromLocale
|
|
CbPerChOfCpg
|
|
GrszToGrwz
|
|
GrwzToGrsz
|
|
SzToWzCch
|
|
|
|
Revision History:
|
|
|
|
17 Mar 2001 v-michka Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
/*-------------------------------
|
|
StackAllocCheck
|
|
|
|
Verify there is room on the stack for the allocation
|
|
-------------------------------*/
|
|
BOOL StackAllocCheck(size_t size)
|
|
{
|
|
BOOL RetVal;
|
|
PVOID mem;
|
|
|
|
__try
|
|
{
|
|
mem = (void *)((size)?(_alloca(size)):NULL);
|
|
RetVal = TRUE;
|
|
}
|
|
__except (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW ? EXCEPTION_EXECUTE_HANDLER :
|
|
EXCEPTION_CONTINUE_SEARCH )
|
|
{
|
|
gresetstkoflw();
|
|
mem = NULL;
|
|
SetLastError(ERROR_STACK_OVERFLOW);
|
|
RetVal = FALSE;
|
|
}
|
|
|
|
return(RetVal);
|
|
}
|
|
|
|
/*-------------------------------
|
|
GodotToCpgCchOnHeap
|
|
|
|
Converts the given string to Ansi.
|
|
-------------------------------*/
|
|
ALLOCRETURN GodotToCpgCchOnHeap(LPCWSTR lpwz, int cchMax, LPSTR * lpsz, UINT cpg, UINT mcs)
|
|
{
|
|
// Parameter check
|
|
if(!lpsz)
|
|
return(arBadParam);
|
|
|
|
if(FSTRING_VALID(lpwz))
|
|
{
|
|
int cch = gwcslen(lpwz);
|
|
|
|
if(cchMax !=-1 && cchMax < cch)
|
|
cch = cchMax;
|
|
|
|
*lpsz = GodotHeapAlloc((cch+1)*mcs);
|
|
if(! *lpsz)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return(arFailed);
|
|
}
|
|
|
|
WideCharToMultiByte(cpg, 0, lpwz, cch, *lpsz, cch*mcs, NULL, NULL);
|
|
return(arAlloc);
|
|
}
|
|
else
|
|
{
|
|
// Copy the NULL or the ATOM. No alloc needed
|
|
*lpsz = (LPSTR)lpwz;
|
|
return(arNoAlloc);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------
|
|
GodotToUnicodeCpgCchOnHeap
|
|
|
|
Converts the given string to Unicode.
|
|
-------------------------------*/
|
|
ALLOCRETURN GodotToUnicodeCpgCchOnHeap(LPCSTR lpsz, int cchMax, LPWSTR * lpwz, UINT cpg)
|
|
{
|
|
// Parameter check
|
|
if(!lpwz)
|
|
return(arBadParam);
|
|
|
|
if(FSTRING_VALID(lpsz))
|
|
{
|
|
int cch = lstrlenA(lpsz);
|
|
|
|
if(cchMax !=-1 && cchMax < cch)
|
|
cch = cchMax;
|
|
|
|
*lpwz = GodotHeapAlloc((cch + 1)*sizeof(WCHAR));
|
|
if(! *lpwz)
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return(arFailed);
|
|
}
|
|
|
|
MultiByteToWideChar(cpg, 0, lpsz, cch, *lpwz, cch*sizeof(WCHAR));
|
|
return(arAlloc);
|
|
}
|
|
else
|
|
{
|
|
// Copy the NULL or the ATOM. No alloc needed
|
|
*lpwz = (LPWSTR)lpsz;
|
|
return(arNoAlloc);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------
|
|
DevModeAfromW
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void DevModeAfromW(LPDEVMODEA lpdma, LPDEVMODEW lpdmw)
|
|
{
|
|
WideCharToMultiByte(g_acp, 0,
|
|
(LPWSTR)(lpdmw->dmDeviceName), CCHDEVICENAME,
|
|
(LPSTR)(lpdma->dmDeviceName), CCHDEVICENAME*g_mcs,
|
|
NULL, NULL);
|
|
memcpy(&lpdma->dmSpecVersion,
|
|
&lpdmw->dmSpecVersion,
|
|
(4*sizeof(WORD) + sizeof(DWORD) + (13*sizeof(short))));
|
|
WideCharToMultiByte(g_acp, 0,
|
|
(LPWSTR)(lpdmw->dmFormName), CCHFORMNAME,
|
|
(LPSTR)(lpdma->dmFormName), CCHFORMNAME*g_mcs,
|
|
NULL, NULL);
|
|
memcpy(&lpdma->dmLogPixels, &lpdmw->dmLogPixels, (sizeof(WORD) + (11*sizeof(DWORD))));
|
|
lpdma->dmSize = CDSIZEOF_STRUCT(DEVMODEA, dmReserved2);
|
|
|
|
// Make sure we copy the extra driver bytes.
|
|
if (lpdmw->dmDriverExtra)
|
|
memcpy((char*)lpdma + lpdma->dmSize, (char*)lpdmw + lpdmw->dmSize, lpdmw->dmDriverExtra);
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
DevModeWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void DevModeWfromA(LPDEVMODEW lpdmw, LPDEVMODEA lpdma)
|
|
{
|
|
MultiByteToWideChar(g_acp, 0,
|
|
(LPSTR)(lpdma->dmDeviceName), CCHDEVICENAME,
|
|
(LPWSTR)(lpdmw->dmDeviceName), CCHDEVICENAME);
|
|
memcpy(&lpdmw->dmSpecVersion,
|
|
&lpdma->dmSpecVersion,
|
|
4*sizeof(WORD) + sizeof(DWORD) + (13*sizeof(short)));
|
|
MultiByteToWideChar(g_acp, 0,
|
|
(LPSTR)(lpdma->dmFormName), CCHFORMNAME,
|
|
(LPWSTR)(lpdmw->dmFormName), CCHFORMNAME);
|
|
memcpy(&lpdmw->dmLogPixels, &lpdma->dmLogPixels, sizeof(WORD) + (11*sizeof(DWORD)));
|
|
lpdmw->dmSize = CDSIZEOF_STRUCT(DEVMODEW, dmReserved2);
|
|
|
|
// Make sure we copy the extra driver bytes.
|
|
if (lpdma->dmDriverExtra)
|
|
memcpy((char*)lpdmw + lpdmw->dmSize, (char*)lpdma + lpdma->dmSize, lpdma->dmDriverExtra);
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
HDevModeAfromW
|
|
|
|
Wrapper around DevModeAfromW that does the right thing with global
|
|
memory. Does not require that hdmw be set (but will not touch hdma
|
|
unless it is).
|
|
-------------------------------*/
|
|
HGLOBAL HDevModeAfromW(HGLOBAL * lphdmw, BOOL fFree)
|
|
{
|
|
HGLOBAL hdma = NULL;
|
|
|
|
if(lphdmw && *lphdmw)
|
|
{
|
|
LPDEVMODEW lpdmw = (LPDEVMODEW)GlobalLock(*lphdmw);
|
|
if(lpdmw)
|
|
{
|
|
if(hdma = GlobalAlloc(GHND, sizeof(DEVMODEA) + lpdmw->dmDriverExtra))
|
|
{
|
|
LPDEVMODEA lpdma = (LPDEVMODEA)GlobalLock(hdma);
|
|
if(lpdma)
|
|
{
|
|
DevModeAfromW(lpdma, lpdmw);
|
|
GlobalUnlock(hdma);
|
|
}
|
|
else
|
|
GlobalFree(hdma);
|
|
}
|
|
GlobalUnlock(*lphdmw);
|
|
if(fFree)
|
|
{
|
|
GlobalFree(*lphdmw);
|
|
*lphdmw = NULL;
|
|
}
|
|
}
|
|
}
|
|
return(hdma);
|
|
}
|
|
|
|
/*-------------------------------
|
|
HDevModeWfromA
|
|
|
|
Wrapper around DevModeWfromA that does the right thing with global
|
|
memory. Does not require that hdma be set (but will not touch hdma
|
|
unless it is).
|
|
-------------------------------*/
|
|
HGLOBAL HDevModeWfromA(HGLOBAL * lphdma, BOOL fFree)
|
|
{
|
|
HGLOBAL hdmw = NULL;
|
|
|
|
if(lphdma && *lphdma)
|
|
{
|
|
LPDEVMODEA lpdma = (LPDEVMODEA)GlobalLock(*lphdma);
|
|
if(lpdma)
|
|
{
|
|
if(hdmw = GlobalAlloc(GHND, sizeof(DEVMODEW) + lpdma->dmDriverExtra))
|
|
{
|
|
LPDEVMODEW lpdmw = (LPDEVMODEW)GlobalLock(hdmw);
|
|
if(lpdmw)
|
|
{
|
|
DevModeWfromA(lpdmw, lpdma);
|
|
GlobalUnlock(hdmw);
|
|
}
|
|
else
|
|
GlobalFree(hdmw);
|
|
}
|
|
GlobalUnlock(*lphdma);
|
|
if(fFree)
|
|
{
|
|
GlobalFree(*lphdma);
|
|
*lphdma = NULL;
|
|
}
|
|
}
|
|
}
|
|
return(hdmw);
|
|
}
|
|
|
|
/*-------------------------------
|
|
HDevNamesAfromW
|
|
|
|
The name says it all. Does not require hdnw to be set (but will not
|
|
touch hdma unless it is).
|
|
-------------------------------*/
|
|
HGLOBAL HDevNamesAfromW(HGLOBAL * lphdnw, BOOL fFree)
|
|
{
|
|
HGLOBAL hdna = NULL;
|
|
|
|
if(lphdnw && *lphdnw)
|
|
{
|
|
LPDEVNAMES lpdnw = (LPDEVNAMES)GlobalLock(*lphdnw);
|
|
if(lpdnw)
|
|
{
|
|
int cchDriver = gwcslen((LPCWSTR)lpdnw + lpdnw->wDriverOffset) + 1;
|
|
int cchDevice = gwcslen((LPCWSTR)lpdnw + lpdnw->wDeviceOffset) + 1;
|
|
int cchOutput = gwcslen((LPCWSTR)lpdnw + lpdnw->wOutputOffset) + 1;
|
|
if(hdna = GlobalAlloc(GHND, sizeof(DEVNAMES) +
|
|
(g_mcs * (cchDriver + cchDevice + cchOutput))))
|
|
{
|
|
LPDEVNAMES lpdna = (LPDEVNAMES)GlobalLock(hdna);
|
|
if(!lpdna)
|
|
GlobalFree(hdna);
|
|
else
|
|
{
|
|
lpdna->wDriverOffset = sizeof(DEVNAMES);
|
|
lpdna->wDeviceOffset = lpdna->wDriverOffset + cchDriver;
|
|
lpdna->wOutputOffset = lpdna->wDeviceOffset + cchDevice;
|
|
lpdna->wDefault = lpdna->wDefault;
|
|
|
|
WideCharToMultiByte(g_acp, 0,
|
|
(LPWSTR)lpdnw + lpdnw->wDriverOffset, cchDriver*g_mcs,
|
|
(LPSTR)lpdna + lpdna->wDriverOffset, cchDriver,
|
|
NULL, NULL);
|
|
WideCharToMultiByte(g_acp, 0,
|
|
(LPWSTR)lpdnw + lpdnw->wDeviceOffset, cchDevice*g_mcs,
|
|
(LPSTR)lpdna + lpdna->wDeviceOffset, cchDevice,
|
|
NULL, NULL);
|
|
WideCharToMultiByte(g_acp, 0,
|
|
(LPWSTR)lpdnw + lpdnw->wOutputOffset, cchOutput*g_mcs,
|
|
(LPSTR)lpdna + lpdna->wOutputOffset, cchOutput,
|
|
NULL, NULL);
|
|
GlobalUnlock(hdna);
|
|
}
|
|
}
|
|
GlobalUnlock(*lphdnw);
|
|
if(fFree)
|
|
{
|
|
GlobalFree(*lphdnw);
|
|
*lphdnw = NULL;
|
|
}
|
|
}
|
|
}
|
|
return(hdna);
|
|
}
|
|
|
|
/*-------------------------------
|
|
HDevNamesWfromA
|
|
|
|
The name says it all. Does not require hdna to be set (but does
|
|
not touch hdnw unless it is).
|
|
-------------------------------*/
|
|
HGLOBAL HDevNamesWfromA(HGLOBAL * lphdna, BOOL fFree)
|
|
{
|
|
HGLOBAL hdnw = NULL;
|
|
|
|
if(lphdna && *lphdna)
|
|
{
|
|
LPDEVNAMES lpdna = (LPDEVNAMES)GlobalLock(*lphdna);
|
|
if(lpdna)
|
|
{
|
|
int cchDriver = lstrlenA((LPCSTR)lpdna + lpdna->wDriverOffset) + 1;
|
|
int cchDevice = lstrlenA((LPCSTR)lpdna + lpdna->wDeviceOffset) + 1;
|
|
int cchOutput = lstrlenA((LPCSTR)lpdna + lpdna->wOutputOffset) + 1;
|
|
if(hdnw = GlobalAlloc(GHND, sizeof(DEVNAMES) +
|
|
(sizeof(WCHAR) * (cchDriver + cchDevice + cchOutput))))
|
|
{
|
|
LPDEVNAMES lpdnw = (LPDEVNAMES)GlobalLock(hdnw);
|
|
if(!lpdnw)
|
|
GlobalFree(hdnw);
|
|
else
|
|
{
|
|
lpdnw->wDriverOffset = sizeof(DEVNAMES) / sizeof(WCHAR);
|
|
lpdnw->wDeviceOffset = lpdnw->wDriverOffset + cchDriver;
|
|
lpdnw->wOutputOffset = lpdnw->wDeviceOffset + cchDevice;
|
|
lpdnw->wDefault = lpdna->wDefault;
|
|
|
|
MultiByteToWideChar(g_acp, 0,
|
|
(LPSTR)lpdna + lpdna->wDriverOffset, cchDriver,
|
|
(LPWSTR)lpdnw + lpdnw->wDriverOffset, cchDriver);
|
|
MultiByteToWideChar(g_acp, 0,
|
|
(LPSTR)lpdna + lpdna->wDeviceOffset, cchDevice,
|
|
(LPWSTR)lpdnw + lpdnw->wDeviceOffset, cchDevice);
|
|
MultiByteToWideChar(g_acp, 0,
|
|
(LPSTR)lpdna + lpdna->wOutputOffset, cchOutput,
|
|
(LPWSTR)lpdnw + lpdnw->wOutputOffset, cchOutput);
|
|
GlobalUnlock(hdnw);
|
|
}
|
|
}
|
|
GlobalUnlock(*lphdna);
|
|
if(fFree)
|
|
{
|
|
GlobalFree(*lphdna);
|
|
*lphdna = NULL;
|
|
}
|
|
}
|
|
}
|
|
return(hdnw);
|
|
}
|
|
|
|
/*-------------------------------
|
|
LogFontAfromW
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void LogFontAfromW(LPLOGFONTA lplfa, LPLOGFONTW lplfw)
|
|
{
|
|
memcpy(lplfa, lplfw, (5*sizeof(LONG)+8*sizeof(BYTE)));
|
|
WideCharToMultiByte(g_acp, 0,
|
|
lplfw->lfFaceName, LF_FACESIZE,
|
|
lplfa->lfFaceName, LF_FACESIZE,
|
|
NULL, NULL);
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
LogFontWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void LogFontWfromA(LPLOGFONTW lplfw, LPLOGFONTA lplfa)
|
|
{
|
|
memcpy(lplfw, lplfa, (5*sizeof(LONG)+8*sizeof(BYTE)));
|
|
MultiByteToWideChar(g_acp, 0, lplfa->lfFaceName, LF_FACESIZE, lplfw->lfFaceName, LF_FACESIZE);
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
Win32FindDataWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void Win32FindDataWfromA(PWIN32_FIND_DATAW w32fdw, PWIN32_FIND_DATAA w32fda)
|
|
{
|
|
UINT cpg = FILES_CPG;
|
|
|
|
memcpy(w32fdw, w32fda, (3*sizeof(FILETIME)+5*sizeof(DWORD)));
|
|
MultiByteToWideChar(cpg, 0, w32fda->cFileName, MAX_PATH, w32fdw->cFileName, MAX_PATH);
|
|
MultiByteToWideChar(cpg, 0, w32fda->cAlternateFileName, 14, w32fdw->cAlternateFileName, 14);
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
TextMetricWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void TextMetricWfromA(LPTEXTMETRICW lptmw, LPTEXTMETRICA lptma)
|
|
{
|
|
memcpy(lptmw, lptma, (11*sizeof(LONG)));
|
|
MultiByteToWideChar(g_acp, 0, &lptma->tmFirstChar, sizeof(char), &lptmw->tmFirstChar, sizeof(WCHAR));
|
|
MultiByteToWideChar(g_acp, 0, &lptma->tmLastChar, sizeof(char), &lptmw->tmLastChar, sizeof(WCHAR));
|
|
MultiByteToWideChar(g_acp, 0, &lptma->tmDefaultChar, sizeof(char), &lptmw->tmDefaultChar, sizeof(WCHAR));
|
|
MultiByteToWideChar(g_acp, 0, &lptma->tmBreakChar, sizeof(char), &lptmw->tmBreakChar, sizeof(WCHAR));
|
|
memcpy(&lptmw->tmItalic, &lptma->tmItalic, 5*sizeof(BYTE));
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
NewTextMetricWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void NewTextMetricWfromA(LPNEWTEXTMETRICW lpntmw, LPNEWTEXTMETRICA lpntma)
|
|
{
|
|
TextMetricWfromA((LPTEXTMETRICW)lpntmw, (LPTEXTMETRICA)lpntma);
|
|
memcpy(&lpntmw->ntmFlags, &lpntma->ntmFlags, (sizeof(DWORD) + 3*sizeof(UINT)));
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
NewTextMetricExWfromA
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
-------------------------------*/
|
|
void NewTextMetricExWfromA(NEWTEXTMETRICEXW * lpntmew, NEWTEXTMETRICEXA * lpntmea)
|
|
{
|
|
TextMetricWfromA((LPTEXTMETRICW)lpntmew, (LPTEXTMETRICA)lpntmea);
|
|
memcpy(&lpntmew->ntmTm.ntmFlags, &lpntmea->ntmTm.ntmFlags, (sizeof(DWORD) + 3*sizeof(UINT)));
|
|
memcpy(&lpntmew->ntmFontSig, &lpntmea->ntmFontSig, sizeof(FONTSIGNATURE));
|
|
return;
|
|
}
|
|
|
|
/*-------------------------------
|
|
MenuItemInfoAfromW
|
|
|
|
The name says it all. Assumes that it is being passed already alloc'ed parameters
|
|
If the return value is TRUE, then the dwTypeData is a heap pointer to free.
|
|
-------------------------------*/
|
|
BOOL MenuItemInfoAfromW(LPMENUITEMINFOA lpmiia, LPCMENUITEMINFOW lpmiiw)
|
|
{
|
|
DWORD RetVal = FALSE;
|
|
|
|
ZeroMemory(lpmiia, sizeof(MENUITEMINFOA));
|
|
lpmiia->cbSize = sizeof(MENUITEMINFOA);
|
|
lpmiia->fMask = lpmiiw->fMask;
|
|
lpmiia->fType = lpmiiw->fType;
|
|
lpmiia->fState = lpmiiw->fState;
|
|
lpmiia->wID = lpmiiw->wID;
|
|
lpmiia->hSubMenu = lpmiiw->hSubMenu;
|
|
lpmiia->hbmpChecked = lpmiiw->hbmpChecked;
|
|
lpmiia->hbmpUnchecked = lpmiiw->hbmpUnchecked;
|
|
lpmiia->dwItemData = lpmiiw->dwItemData;
|
|
lpmiia->hbmpItem = lpmiiw->hbmpItem;
|
|
|
|
// Ok, now lets take care of the "strings", though we
|
|
// do need to find out if they are in fact strings, first!
|
|
if(((FWIN95()) &&
|
|
((lpmiiw->fMask & MIIM_TYPE) && (lpmiiw->fType == MFT_STRING))) ||
|
|
((!FWIN95() &&
|
|
((lpmiiw->fMask & MIIM_STRING) ||
|
|
((lpmiiw->fMask & MIIM_FTYPE) && (lpmiiw->fType == MFT_STRING))))))
|
|
{
|
|
if (FSTRING_VALID(lpmiiw->dwTypeData))
|
|
{
|
|
// Ok, it looks like a string and they say its a string, so lets
|
|
// treat it like one. Be sure not to copy more than cch.
|
|
size_t cch = gwcslen(lpmiiw->dwTypeData)+1;
|
|
|
|
if (cch > lpmiiw->cch)
|
|
cch = lpmiiw->cch;
|
|
if(arAlloc == GodotToCpgCchOnHeap(lpmiiw->dwTypeData,
|
|
cch,
|
|
&(LPSTR)(lpmiia->dwTypeData),
|
|
g_acp,
|
|
g_mcs))
|
|
{
|
|
RetVal = TRUE;
|
|
}
|
|
|
|
// Set the final length explicitly; don't set by the buffer,
|
|
// which may be more than we actually needed on MBCS
|
|
lpmiia->cch = lstrlenA( lpmiia->dwTypeData);
|
|
}
|
|
else
|
|
{
|
|
// Think its a string per flags but does not look like a string,
|
|
// so copy like an atom but set cch just in case!
|
|
lpmiia->dwTypeData = (LPSTR)lpmiiw->dwTypeData;
|
|
lpmiia->cch = sizeof(lpmiia->dwTypeData);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This ain't a string, darn it! cch is 0 and that's that! Its gonna be
|
|
// ignored anyway.
|
|
lpmiia->dwTypeData = (LPSTR)lpmiiw->dwTypeData;
|
|
lpmiia->cch = 0;
|
|
}
|
|
return(RetVal);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
GrszToGrwz (stolen from Office!)
|
|
|
|
Converts a group of ANSI strings into a group of Unicode strings.
|
|
Each string in the group is terminated by a null. Returns
|
|
resulting length of the Unicode string stored in wzTo as a cb
|
|
|
|
If return value is greater than cchTo, wzTo is not written to.
|
|
-------------------------------------------------------------- MIKEKELL -*/
|
|
int GrszToGrwz(const CHAR* szFrom, WCHAR* wzTo, int cchTo)
|
|
{
|
|
int cchRet = 0;
|
|
const char *szFromSav = szFrom;
|
|
|
|
do
|
|
{
|
|
int cch = strlen(szFrom)+1;
|
|
cchRet += MultiByteToWideChar(g_acp, 0, szFrom, cch, NULL, 0);
|
|
szFrom += cch;
|
|
}
|
|
while (*szFrom);
|
|
|
|
cchRet++;
|
|
szFrom = szFromSav;
|
|
|
|
if (wzTo && (cchRet <= cchTo))
|
|
{
|
|
do
|
|
{
|
|
int cchConv;
|
|
int cch = strlen(szFrom)+1;
|
|
cchConv = MultiByteToWideChar(g_acp, 0, szFrom, cch, wzTo, cchTo);
|
|
szFrom += cch;
|
|
wzTo += cchConv;
|
|
cchTo -= cchConv;
|
|
}
|
|
while (*szFrom);
|
|
*wzTo = 0; // add extra null terminator.
|
|
};
|
|
|
|
return cchRet;
|
|
}
|
|
|
|
/*-------------------------------
|
|
SzToWzCch
|
|
|
|
Returns the unicode length of the string (including the
|
|
null terminator). If this length is <= cch, then it also
|
|
converts the string storing it into wz (otherwise, wz is unchanged)
|
|
-------------------------------*/
|
|
int SzToWzCch(const CHAR *sz, WCHAR *wz, int cch)
|
|
{
|
|
int cchNeed;
|
|
|
|
cchNeed = MultiByteToWideChar(g_acp, 0, sz, -1, NULL, 0);
|
|
|
|
if (cchNeed <= cch)
|
|
{
|
|
MultiByteToWideChar(g_acp, 0, sz, -1, wz, cch);
|
|
};
|
|
return cchNeed;
|
|
};
|
|
|
|
|