windows-nt/Source/XPSP1/NT/sdktools/unicows/godot/convert.c
2020-09-26 16:20:57 +08:00

591 lines
19 KiB
C

/*++
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;
};