mirror of https://github.com/lianthony/NT4.0
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.
642 lines
15 KiB
642 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
EEFormat.c
|
|
|
|
Abstract:
|
|
|
|
This module contains system wide formatting routines for all
|
|
windows that need to format and unformat supported types.
|
|
|
|
|
|
Author:
|
|
|
|
David J. Gilman (davegi) 21-Apr-1992
|
|
Griffith Wm. Kadnier (v-griffk) 27-Apr-1992
|
|
Miche Baker-Harvey (miche) 05-Mar-1993
|
|
|
|
Environment:
|
|
|
|
Win32, User Mode
|
|
|
|
--*/
|
|
|
|
|
|
|
|
typedef UINT FAR * LPUINT;
|
|
|
|
struct format {
|
|
uint cBits;
|
|
uint fmtType;
|
|
uint radix;
|
|
uint fTwoFields;
|
|
uint cchMax;
|
|
LPSTR lpszDescription;
|
|
} RgFormats[] = {
|
|
{8, fmtAscii, 0, FALSE, 1, "ASCII"},
|
|
{8, fmtInt, 16, TRUE, 2, "Byte"},
|
|
{16, fmtInt, 10, FALSE, 6, "Short"},
|
|
{16, fmtUInt, 16, FALSE, 4, "Short Hex"},
|
|
{16, fmtUInt, 10, FALSE, 5, "Short Unsigned"},
|
|
{32, fmtInt, 10, FALSE, 11, "Long"},
|
|
{32, fmtUInt, 16, FALSE, 8, "Long Hex"},
|
|
{32, fmtUInt, 10, FALSE, 10, "Long Unsigned"},
|
|
{64, fmtInt, 10, FALSE, 21, "Quad"},
|
|
{64, fmtUInt, 16, FALSE, 16, "Quad Hex"},
|
|
{64, fmtUInt, 10, FALSE, 20, "Quad Unsigned"},
|
|
{32, fmtFloat, 10, FALSE, 14, "Real (32-bit)"},
|
|
{64, fmtFloat, 10, FALSE, 23, "Real (64-bit)"},
|
|
{80, fmtFloat, 10, FALSE, 25, "Real (10-byte)"}
|
|
// {128,fmtFloat, 10, FALSE, 42, "Real (16-byte)"}
|
|
};
|
|
|
|
//
|
|
// range[i] is smallest value larger than that
|
|
// expressible in 'i' bits.
|
|
//
|
|
|
|
ULONG range[] = {
|
|
0x00000001, 0x00000003, 0x00000007, 0x0000000f,
|
|
0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
|
|
0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
|
|
0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
|
|
0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
|
|
0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
|
|
0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
|
|
0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
|
|
|
|
};
|
|
|
|
|
|
char FAR *
|
|
SkipWhitespace(char FAR * lpszIn)
|
|
{
|
|
while (*lpszIn == ' ' || *lpszIn == '\t') {
|
|
lpszIn++;
|
|
}
|
|
return( lpszIn );
|
|
} /* CPSkipWhiteSpace() */
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
LargeIntegerFormat.
|
|
|
|
This routine formats a large integer, signed or unsigned,
|
|
in radix 8, 10 or 16, into a string.
|
|
This works on any machine with a LARGE_INTEGER type; it
|
|
does not require LARGE_INTEGER support from sprintf.
|
|
|
|
Arguments:
|
|
|
|
li - the large integer value to be formatted
|
|
radix - the radix to use in formatting (8, 10, 16)
|
|
signed - whether the li is signed
|
|
buf - where to store the result
|
|
max - the buffer size.
|
|
|
|
Returns:
|
|
|
|
pointer into buf where string begins
|
|
|
|
--*/
|
|
|
|
char *
|
|
LargeIntegerFormat(LARGE_INTEGER li,
|
|
uint radix,
|
|
BOOLEAN signe,
|
|
char * buf,
|
|
unsigned long max
|
|
)
|
|
{
|
|
|
|
LARGE_INTEGER radixli, remain;
|
|
int digit;
|
|
BOOLEAN needsign = FALSE;
|
|
|
|
|
|
//
|
|
// make sure the radix is ok, and put in LARGE_INTEGER
|
|
//
|
|
|
|
DASSERT (radix == 8 || radix == 10 || radix == 16 );
|
|
|
|
radixli.LowPart = radix;
|
|
radixli.HighPart = 0;
|
|
|
|
remain.LowPart = remain.HighPart = 0;
|
|
|
|
//
|
|
// null-terminate the string
|
|
//
|
|
|
|
max--;
|
|
buf[max] = '\0';
|
|
digit = 1;
|
|
|
|
//
|
|
// If we are to do a signed operation, and the value is negative
|
|
// operate on its inverse, and prepend a '-' sign when complete.
|
|
//
|
|
|
|
if (signe && li.QuadPart < 0) {
|
|
li.QuadPart = li.QuadPart * -1;
|
|
needsign = TRUE;
|
|
}
|
|
|
|
if (li.HighPart)
|
|
sprintf(buf, "-%x%08x", li.HighPart, li.LowPart);
|
|
else
|
|
sprintf(buf, "-%x", li.LowPart);
|
|
|
|
if (needsign)
|
|
return buf;
|
|
else
|
|
return buf+1; // skip minus skip if not needed
|
|
|
|
#if 0
|
|
//
|
|
// Starting with LSD, pull the digits out
|
|
// and put them in the string at the right end.
|
|
//
|
|
do {
|
|
remain.QuadPart = li.QuadPart - (li.QuadPart / radixli.QuadPart);
|
|
li.QuadPart = li.QuadPart / radixli.QuadPart;
|
|
|
|
//
|
|
// If remainder is > 9, then radix was 16, and
|
|
// we need to print A-E, else print 0-9.
|
|
//
|
|
|
|
if (remain.LowPart > 9) {
|
|
buf[max - digit++] = (char)('A' + remain.LowPart - 10);
|
|
} else {
|
|
buf[max - digit++] = (char)('0' + remain.LowPart);
|
|
}
|
|
|
|
} while ( li.LowPart || li.HighPart );
|
|
|
|
if (needsign) {
|
|
buf[max-digit++] = '-';
|
|
}
|
|
|
|
return(&buf[max-digit+1]);
|
|
#endif
|
|
}
|
|
|
|
|
|
EESTATUS
|
|
EEFormatMemory(
|
|
LPCH lpchTarget,
|
|
uint cchTarget,
|
|
LPBYTE lpbSource,
|
|
uint cBits,
|
|
FMTTYPE fmtType,
|
|
uint radix
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
EEFormatMemory.
|
|
|
|
formats a value by template
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
long l;
|
|
long cb;
|
|
ULONG ul;
|
|
char rgch[512];
|
|
|
|
|
|
DASSERT (radix == 8 || radix == 10 || radix == 16 ||
|
|
(fmtType & fmtBasis) == fmtAscii ||
|
|
(fmtType & fmtBasis) == fmtUnicode);
|
|
DASSERT (cBits != 0);
|
|
DASSERT (cchTarget <= sizeof(rgch));
|
|
|
|
switch (fmtType & fmtBasis)
|
|
{
|
|
/*
|
|
** Format from memory bytes into an integer format number
|
|
*/
|
|
case fmtInt:
|
|
|
|
if (radix == 10) {
|
|
|
|
switch( (cBits + 7)/8 ) {
|
|
case 1:
|
|
l = *(signed char *)lpbSource;
|
|
if (fmtType & fmtZeroPad) {
|
|
sprintf(rgch, "%0*d", cchTarget-1, l);
|
|
} else {
|
|
sprintf(rgch, "% d", l);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
l = *(short *)lpbSource;
|
|
if (fmtType & fmtZeroPad) {
|
|
sprintf(rgch, "%0*d", cchTarget-1, l);
|
|
} else {
|
|
sprintf(rgch, "% d", l);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
l = *(long *)lpbSource;
|
|
if (fmtType & fmtZeroPad) {
|
|
sprintf(rgch, "%0*d", cchTarget-1, l);
|
|
} else {
|
|
sprintf(rgch, "% d", l);
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
{
|
|
|
|
char tbuf[100], *tbufp;
|
|
|
|
tbufp = LargeIntegerFormat(*(PLARGE_INTEGER)lpbSource,
|
|
radix,
|
|
TRUE,
|
|
tbuf,
|
|
100);
|
|
|
|
if (!(fmtType & fmtZeroPad)) {
|
|
sprintf(rgch, "%s", tbufp);
|
|
} else if (*tbufp == '-') {
|
|
sprintf(rgch, "%-0*s", cchTarget - 2, tbufp+1);
|
|
} else {
|
|
sprintf(rgch, "%0*s", cchTarget - 1, tbufp);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
return EEBADFORMAT;
|
|
}
|
|
|
|
|
|
if (strlen(rgch) >= cchTarget) {
|
|
return EEOVERRUN;
|
|
}
|
|
|
|
_fstrcpy(lpchTarget, rgch);
|
|
|
|
break;
|
|
}
|
|
/*
|
|
else
|
|
handle as UInt
|
|
*/
|
|
|
|
case fmtUInt:
|
|
|
|
cb = (cBits + 7)/8;
|
|
switch( cb ) {
|
|
case 1:
|
|
ul = *(BYTE FAR *) lpbSource;
|
|
break;
|
|
|
|
case 2:
|
|
ul = *(USHORT FAR *) lpbSource;
|
|
break;
|
|
|
|
case 4:
|
|
ul = *(ULONG FAR *) lpbSource;
|
|
break;
|
|
|
|
//
|
|
// MBH - bugbug - CENTAUR bug;
|
|
// putting contents of instead of address of structure
|
|
// for return value in a0.
|
|
//
|
|
|
|
case 8:
|
|
{
|
|
//
|
|
// Handle 64-bits out of band, since sprintf
|
|
// cannot handle it.
|
|
//
|
|
|
|
char tbuf[100], *tbufp;
|
|
|
|
tbufp = LargeIntegerFormat(*(PLARGE_INTEGER)lpbSource,
|
|
radix,
|
|
FALSE,
|
|
tbuf,
|
|
100);
|
|
|
|
if (fmtType & fmtZeroPad) {
|
|
sprintf(rgch, "%0*s", cchTarget - 1, tbufp);
|
|
} else {
|
|
sprintf(rgch, "%s", tbufp);
|
|
}
|
|
_strlwr(rgch);
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
if (radix != 16 || (fmtType & fmtZeroPad) == 0) {
|
|
return EEBADFORMAT;
|
|
}
|
|
}
|
|
|
|
if (cb != 8) {
|
|
|
|
|
|
if (fmtType & fmtZeroPad) {
|
|
switch (radix) {
|
|
case 8:
|
|
sprintf(rgch, "%0*.*o", cchTarget-1, cchTarget-1, ul);
|
|
break;
|
|
case 10:
|
|
sprintf(rgch, "%0*.*u", cchTarget-1, cchTarget-1, ul);
|
|
break;
|
|
case 16:
|
|
// handle any size:
|
|
// NOTENOTE a-kentf this is dependent on byte order
|
|
for (l = 0; l < cb; l++) {
|
|
sprintf(rgch+l+l, "%02.2x", lpbSource[cb - l - 1]);
|
|
}
|
|
//sprintf(rgch, "%0*.*x", cchTarget-1, cchTarget-1, ul);
|
|
break;
|
|
}
|
|
} else {
|
|
switch (radix) {
|
|
case 8:
|
|
sprintf(rgch, "%o", ul);
|
|
break;
|
|
case 10:
|
|
sprintf(rgch, "%u", ul);
|
|
break;
|
|
case 16:
|
|
sprintf(rgch, "%x", ul);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (strlen(rgch) >= cchTarget) {
|
|
return EEOVERRUN;
|
|
}
|
|
|
|
_fstrcpy(lpchTarget, rgch);
|
|
|
|
break;
|
|
|
|
|
|
case fmtAscii:
|
|
if ( cBits != 8 ) {
|
|
return EEBADFORMAT;
|
|
}
|
|
lpchTarget[0] = *(BYTE FAR *) lpbSource;
|
|
if ((lpchTarget[0] < ' ') || (lpchTarget[0] > 0x7e)) {
|
|
lpchTarget[0] = '.';
|
|
}
|
|
lpchTarget[1] = 0;
|
|
return EENOERROR;
|
|
|
|
case fmtUnicode:
|
|
if (cBits != 16) {
|
|
return EEBADFORMAT;
|
|
}
|
|
DASSERT((uint)MB_CUR_MAX <= cchTarget);
|
|
// DASSERT(cchTarget >= 2);
|
|
if ((wctomb(lpchTarget, *(LPWCH)lpbSource) == -1) ||
|
|
(lpchTarget[0] < ' ') ||
|
|
(lpchTarget[0] > 0x7e)) {
|
|
lpchTarget[0] = '.';
|
|
}
|
|
lpchTarget[1] = 0;
|
|
return EENOERROR;
|
|
|
|
case fmtFloat:
|
|
// NOTENOTE a-kentf doesn't currently handle fmtZeroPad
|
|
switch ( cBits ) {
|
|
case 4*8:
|
|
sprintf(rgch, "% 12.6e",*((float FAR *) lpbSource));
|
|
break;
|
|
|
|
case 8*8:
|
|
// sprintf(rgch, "% 17.11le", *((double FAR *) lpbSource));
|
|
sprintf(rgch, "% 21.14le", *((double FAR *) lpbSource));
|
|
break;
|
|
|
|
case 10*8:
|
|
if (_uldtoa((_ULDOUBLE *)lpbSource, 25, rgch) == NULL) {
|
|
return EEBADFORMAT;
|
|
}
|
|
break;
|
|
|
|
case 16*8:
|
|
//NOTENOTE mips long doubles revert to ????....for now
|
|
_fstrcpy (rgch,"??????????????????????????????????????????");
|
|
break;
|
|
|
|
default:
|
|
return EEBADFORMAT;
|
|
|
|
}
|
|
|
|
if (strlen(rgch) >= cchTarget) {
|
|
return EEOVERRUN;
|
|
}
|
|
|
|
_fstrncpy(lpchTarget, rgch, cchTarget-1);
|
|
lpchTarget[cchTarget-1] = 0;
|
|
return EENOERROR;
|
|
|
|
case fmtAddress:
|
|
return EEBADFORMAT;
|
|
|
|
case fmtZeroPad:
|
|
return EEBADFORMAT;
|
|
|
|
}
|
|
|
|
return EENOERROR;
|
|
} /* EEFormatMemory() */
|
|
|
|
|
|
EESTATUS
|
|
EEUnformatMemory(
|
|
LPBYTE lpbTarget,
|
|
LPSTR lpszSource,
|
|
uint cBits,
|
|
FMTTYPE fmtType,
|
|
uint radix
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
ULARGE_INTEGER largeint;
|
|
ULONG l;
|
|
char *ptr = lpszSource;
|
|
|
|
switch ( fmtType & fmtBasis ) {
|
|
case fmtInt:
|
|
case fmtUInt:
|
|
|
|
DASSERT (radix == 8 || radix == 10 || radix == 16);
|
|
|
|
l = 0;
|
|
|
|
ptr = SkipWhitespace(ptr);
|
|
|
|
if ((fmtType & fmtOverRide) == 0)
|
|
{
|
|
if (*ptr == '0') {
|
|
// force radix - is it hex or octal?
|
|
++ptr;
|
|
if (*ptr == 'x' || *ptr == 'X') {
|
|
++ptr;
|
|
radix = 16;
|
|
} else if ((*ptr == 'o') || (*ptr == 'O')) {
|
|
radix = 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
errno = 0;
|
|
largeint = (strtouli(ptr, &ptr, (int)radix));
|
|
l = largeint.LowPart;
|
|
|
|
if ((l == 0 || l == ULONG_MAX) && errno == ERANGE) {
|
|
return EEBADFORMAT;
|
|
}
|
|
|
|
if (cBits < 32 && l > range[cBits-1] ) {
|
|
return EEBADFORMAT;
|
|
}
|
|
|
|
if (*SkipWhitespace(ptr)) {
|
|
return EEBADFORMAT;
|
|
}
|
|
|
|
switch( (cBits + 7)/8 ) {
|
|
case 1:
|
|
*(BYTE FAR *) lpbTarget = (BYTE) l;
|
|
break;
|
|
|
|
case 2:
|
|
*(USHORT FAR *) lpbTarget = (USHORT) l;
|
|
break;
|
|
|
|
case 4:
|
|
*(ULONG FAR *) lpbTarget = l;
|
|
break;
|
|
|
|
case 8:
|
|
*(PULARGE_INTEGER)lpbTarget = largeint;
|
|
break;
|
|
|
|
|
|
default:
|
|
return EEBADFORMAT;
|
|
}
|
|
break;
|
|
|
|
case fmtFloat:
|
|
// radix is ALWAYS 10 in the world of floats
|
|
switch ( (cBits + 7)/8 ) {
|
|
|
|
case 4:
|
|
if (sscanf(lpszSource, "%f", (float *)lpbTarget) != 1) {
|
|
return EEBADFORMAT;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
if (sscanf(lpszSource, "%lf", (double *)lpbTarget) != 1) {
|
|
return EEBADFORMAT;
|
|
}
|
|
break;
|
|
|
|
case 10:
|
|
// i = sscanf(lpszSource, "%Lf", (long double *)lpbTarget);
|
|
_atoldbl( (_ULDOUBLE *)lpbTarget, lpszSource );
|
|
break;
|
|
|
|
default:
|
|
return EEBADFORMAT;
|
|
}
|
|
|
|
break;
|
|
|
|
case fmtAscii:
|
|
case fmtUnicode:
|
|
case fmtAddress:
|
|
// these aren't handled here.
|
|
return EEBADFORMAT;
|
|
}
|
|
return EENOERROR;
|
|
} /* EEUnformatMemory() */
|
|
|
|
|
|
/*** EEFormatEnumerate
|
|
**
|
|
** Synopsis:
|
|
**
|
|
** Entry:
|
|
**
|
|
** Returns:
|
|
**
|
|
** Description:
|
|
**
|
|
*/
|
|
|
|
EESTATUS
|
|
EEFormatEnumerate(
|
|
UINT iFmt,
|
|
LPUINT lpcBits,
|
|
LPUINT lpFmtType,
|
|
LPUINT lpRadix,
|
|
LPUINT lpFTwoFields,
|
|
LPUINT lpcchMax,
|
|
LPCH FAR * lplpszDesc
|
|
)
|
|
{
|
|
if (iFmt >= sizeof(RgFormats)/sizeof(struct format)) {
|
|
return (1); // M00BUG -- get an error code for here
|
|
}
|
|
|
|
*lpcBits = RgFormats[iFmt].cBits;
|
|
*lpFmtType = RgFormats[iFmt].fmtType;
|
|
*lpRadix = RgFormats[iFmt].radix;
|
|
*lpFTwoFields = RgFormats[iFmt].fTwoFields;
|
|
*lpcchMax = RgFormats[iFmt].cchMax;
|
|
if (lplpszDesc != NULL)
|
|
*lplpszDesc = &RgFormats[iFmt].lpszDescription[0];
|
|
|
|
return (EENOERROR);
|
|
} /* EEFormatEnumerate() */
|