windows-nt/Source/XPSP1/NT/base/efiutil/efilib/efisrc/efistrutil.cxx
2020-09-26 16:20:57 +08:00

649 lines
18 KiB
C++

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
efistrutil.cxx
--*/
#include "efiwintypes.hxx"
#include "pch.cxx"
void *memmove( void *dest, const void *src, size_t count )
{
// quick workaround for lack of memmove in EFI library
VOID * temp = AllocatePool(count);
memcpy( temp, src, count);
memcpy( dest, temp, count);
FreePool(temp);
return dest;
}
char *strcpy( char *strDestination, const char *strSource )
{
INT32 i;
i=0;
while(strSource[i] != NULL) {
strDestination[i] = strSource[i];
i++;
}
strDestination[i] = NULL; // null terminate.
return strDestination;
}
int iswspace( WCHAR c )
{
// BUGBUG this isn't a proper wide char test
// but will do for now.
if( ((0x09 <= c) && (c <= 0x0d)) || (c == 0x20) ) {
return TRUE;
} else {
return FALSE;
}
}
int isspace( CHAR c )
{
// BUGBUG this isn't a proper wide char test
// but will do for now.
if( ((0x09 <= c) && (c <= 0x0d)) || (c == 0x20) ) {
return TRUE;
} else {
return FALSE;
}
}
int isdigit( int c )
{
// BUGBUG again, this isn't a proper wide char test
// but it will do for now.
if( c >= '0' && c <= '9' ) {
return TRUE;
} else {
return FALSE;
}
}
int towupper( WCHAR c )
{
// BUGBUG, this is wrong too, but for now it must do.
return c;
}
int wcsncmp( const WCHAR *string1, const WCHAR *string2, size_t count )
{
for( unsigned int i=0; i<count; i++ ) {
if(string1[i] != string2[i] || string1[i] == UNICODE_NULL || string2[i] == UNICODE_NULL) {
break;
}
}
return string2[i]-string1[i];
}
long atol(const char *nptr) {
int c; /* current char */
long total; /* current total */
int sign; /* if '-', then negative, otherwise positive */
while (isspace((int)(unsigned char)*nptr))
nptr++;
c = (int)(unsigned char)*nptr++;
sign = c; /* save sign indication */
if (c == '-' || c == '+')
c = (int)(unsigned char)*nptr++; /* skip sign */
total = 0;
while ((c >= '0') && (c <= '9')) {
total = 10 * total + (c - '0'); /* accumulate digit */
c = (int)(unsigned char)*nptr++; /* get next char */
}
if (sign == '-')
return -total;
else
return total;
}
int atoi(const char *nptr) {
return (int)atol(nptr);
}
STATIC char *sprintf_buf;
STATIC count;
VOID
bzero(char *cp, int len)
{
while (len--) {
*(cp + len) = 0;
}
}
VOID
__cdecl
putbuf(char c)
{
*sprintf_buf++ = c;
count++;
}
VOID
__cdecl
doprnt(VOID (*func)(char c), const char *fmt, va_list args);
//
// BUGBUG this is a semi-sprintf hacked together just to get it to work
//
int
__cdecl
sprintf(char *buf, const char *fmt, ...)
{
va_list args;
sprintf_buf = buf;
va_start(args, fmt);
doprnt(putbuf, fmt, args);
va_end(args);
putbuf('\0');
return count--;
}
void
__cdecl
printbase(VOID (*func)(char), ULONG x, int base, int width)
{
static char itoa[] = "0123456789abcdef";
ULONG j;
LONG k;
char buf[32], *s = buf;
bzero(buf, 16);
while (x) {
j = x % base;
*s++ = itoa[j];
x -= j;
x /= base;
}
if( s-buf < width ) {
for( k = 0; k < width - (s-buf); k++ ) {
func('0');
}
}
for (--s; s >= buf; --s) {
func(*s);
}
}
void
__cdecl
doprnt(VOID (*func)( char c), const char *fmt, va_list args)
{
ULONG x;
LONG l;
LONG width;
char c, *s;
count = 0;
while (c = *fmt++) {
if (c != '%') {
func(c);
continue;
}
width=0;
c=*fmt++;
if(c == '0') {
while( c = *fmt++) {
if (!isdigit(c)) {
break;
}
width = width*10;
width = width+(c-48);
}
}
fmt--; // back it up one char
switch (c = *fmt++) {
case 'x':
x = va_arg(args, ULONG);
printbase(func, x, 16, width);
break;
case 'o':
x = va_arg(args, ULONG);
printbase(func, x, 8, width);
break;
case 'd':
l = va_arg(args, LONG);
if (l < 0) {
func('-');
l = -l;
}
printbase(func, (ULONG) l, 10, width);
break;
case 'u':
l = va_arg(args, ULONG);
printbase(func, (ULONG) l, 10, width);
break;
case 'c':
c = va_arg(args, char);
func(c);
break;
case 's':
s = va_arg(args, char *);
while (*s) {
func(*s++);
}
break;
default:
func(c);
break;
}
}
}
#define MAX_INSERTS 200
NTSTATUS
RtlFormatMessage(
IN PWSTR MessageFormat,
IN ULONG MaximumWidth OPTIONAL,
IN BOOLEAN IgnoreInserts,
IN BOOLEAN ArgumentsAreAnsi,
IN BOOLEAN ArgumentsAreAnArray,
IN va_list *Arguments,
OUT PWSTR Buffer,
IN ULONG Length,
OUT PULONG ReturnLength OPTIONAL
)
{
ULONG Column;
int cchRemaining, cchWritten;
PULONG_PTR ArgumentsArray = (PULONG_PTR)Arguments;
ULONG_PTR rgInserts[ MAX_INSERTS ];
ULONG cSpaces;
ULONG MaxInsert, CurInsert;
ULONG PrintParameterCount;
ULONG_PTR PrintParameter1;
ULONG_PTR PrintParameter2;
WCHAR PrintFormatString[ 32 ];
BOOLEAN DefaultedFormatString;
WCHAR c;
PWSTR s, s1;
PWSTR lpDst, lpDstBeg, lpDstLastSpace;
cchRemaining = Length / sizeof( WCHAR );
lpDst = Buffer;
MaxInsert = 0;
lpDstLastSpace = NULL;
Column = 0;
s = MessageFormat;
while (*s != UNICODE_NULL) {
if (*s == L'%') {
s++;
lpDstBeg = lpDst;
if (*s >= L'1' && *s <= L'9') {
CurInsert = *s++ - L'0';
if (*s >= L'0' && *s <= L'9') {
CurInsert = (CurInsert * 10) + (*s++ - L'0');
if (*s >= L'0' && *s <= L'9') {
CurInsert = (CurInsert * 10) + (*s++ - L'0');
if (*s >= L'0' && *s <= L'9') {
return( STATUS_INVALID_PARAMETER );
}
}
}
CurInsert -= 1;
PrintParameterCount = 0;
if (*s == L'!') {
DefaultedFormatString = FALSE;
s1 = PrintFormatString;
*s1++ = L'%';
s++;
while (*s != L'!') {
if (*s != UNICODE_NULL) {
if (s1 >= &PrintFormatString[ 31 ]) {
return( STATUS_INVALID_PARAMETER );
}
if (*s == L'*') {
if (PrintParameterCount++ > 1) {
return( STATUS_INVALID_PARAMETER );
}
}
*s1++ = *s++;
}
else {
return( STATUS_INVALID_PARAMETER );
}
}
s++;
*s1 = UNICODE_NULL;
}
else {
DefaultedFormatString = TRUE;
wcscpy( PrintFormatString, TEXT("%s") );
s1 = PrintFormatString + wcslen( PrintFormatString );
}
if (IgnoreInserts) {
if (!wcscmp( PrintFormatString, TEXT("%s") )) {
cchWritten = (int)SPrint( lpDst,
cchRemaining,
TEXT("%%%u"),
CurInsert+1
);
}
else {
cchWritten = (int)SPrint( lpDst,
cchRemaining,
TEXT("%%%u!%s!"),
CurInsert+1,
&PrintFormatString[ 1 ]
);
}
if (cchWritten == -1) {
return(STATUS_BUFFER_OVERFLOW);
}
}
else
if (ARGUMENT_PRESENT( Arguments )) {
if ((CurInsert+PrintParameterCount) >= MAX_INSERTS) {
return( STATUS_INVALID_PARAMETER );
}
if (ArgumentsAreAnsi) {
if (s1[ -1 ] == L'c' && s1[ -2 ] != L'h'
&& s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
wcscpy( &s1[ -1 ], TEXT("hc") );
}
else
if (s1[ -1 ] == L's' && s1[ -2 ] != L'h'
&& s1[ -2 ] != L'w' && s1[ -2 ] != L'l') {
wcscpy( &s1[ -1 ], TEXT("hs") );
}
else if (s1[ -1 ] == L'S') {
s1[ -1 ] = L's';
}
else if (s1[ -1 ] == L'C') {
s1[ -1 ] = L'c';
}
}
while (CurInsert >= MaxInsert) {
if (ArgumentsAreAnArray) {
PULONG_PTR aaa;
aaa = (PULONG_PTR)Arguments++;
PrintParameter2 = rgInserts[ MaxInsert++ ] = *(aaa);
}
else {
rgInserts[ MaxInsert++ ] = va_arg(*Arguments, ULONG_PTR);
}
}
s1 = (PWSTR)rgInserts[ CurInsert ];
PrintParameter1 = 0;
PrintParameter2 = 0;
if (PrintParameterCount > 0) {
if (ArgumentsAreAnArray) {
PULONG_PTR aaa;
aaa = (PULONG_PTR)Arguments;
PrintParameter2 = rgInserts[ MaxInsert++ ] = *(aaa)++;
}
else {
PrintParameter1 = rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
}
if (PrintParameterCount > 1) {
if (ArgumentsAreAnArray) {
PULONG_PTR aaa;
aaa = (PULONG_PTR)Arguments;
PrintParameter2 = rgInserts[ MaxInsert++ ] = *(aaa)++;
}
else {
PrintParameter2 = rgInserts[ MaxInsert++ ] = va_arg( *Arguments, ULONG_PTR );
}
}
}
cchWritten = (int)SPrint( lpDst,
cchRemaining,
PrintFormatString,
s1,
PrintParameter1,
PrintParameter2
);
if (cchWritten == -1) {
return(STATUS_BUFFER_OVERFLOW);
}
}
else {
return( STATUS_INVALID_PARAMETER );
}
if ((cchRemaining -= cchWritten) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
lpDst += cchWritten;
}
else
if (*s == L'0') {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'\0';
break;
}
else
if (!*s) {
return( STATUS_INVALID_PARAMETER );
}
else
if (*s == L'r') {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'\r';
s++;
lpDstBeg = NULL;
}
else
if (*s == L'n') {
if ((cchRemaining -= 2) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'\r';
*lpDst++ = L'\n';
s++;
lpDstBeg = NULL;
}
else
if (*s == L't') {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
if (Column % 8) {
Column = (Column + 7) & ~7;
}
else {
Column += 8;
}
lpDstLastSpace = lpDst;
*lpDst++ = L'\t';
s++;
}
else
if (*s == L'b') {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
lpDstLastSpace = lpDst;
*lpDst++ = L' ';
s++;
}
else
if (IgnoreInserts) {
if ((cchRemaining -= 2) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'%';
*lpDst++ = *s++;
}
else {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = *s++;
}
if (lpDstBeg == NULL) {
lpDstLastSpace = NULL;
Column = 0;
}
else {
Column += (ULONG)(lpDst - lpDstBeg);
}
}
else {
c = *s++;
if (c == L'\r' || c == L'\n') {
if ((c == L'\n' && *s == L'\r') ||
(c == L'\r' && *s == L'\n')
) {
s++;
}
if (MaximumWidth != 0) {
lpDstLastSpace = lpDst;
c = L' ';
}
else {
c = L'\n';
}
}
if (c == L'\n') {
if ((cchRemaining -= 2) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'\r';
*lpDst++ = L'\n';
lpDstLastSpace = NULL;
Column = 0;
}
else {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
if (c == L' ') {
lpDstLastSpace = lpDst;
}
*lpDst++ = c;
Column += 1;
}
}
if (MaximumWidth != 0 &&
MaximumWidth != 0xFFFFFFFF &&
Column >= MaximumWidth
) {
if (lpDstLastSpace != NULL) {
lpDstBeg = lpDstLastSpace;
while (*lpDstBeg == L' ' || *lpDstBeg == L'\t') {
lpDstBeg += 1;
if (lpDstBeg == lpDst) {
break;
}
}
while (lpDstLastSpace > Buffer) {
if (lpDstLastSpace[ -1 ] == L' ' || lpDstLastSpace[ -1 ] == L'\t') {
lpDstLastSpace -= 1;
}
else {
break;
}
}
cSpaces = (ULONG)(lpDstBeg - lpDstLastSpace);
if (cSpaces == 1) {
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
}
else
if (cSpaces > 2) {
cchRemaining += (cSpaces - 2);
}
memmove( lpDstLastSpace + 2,
lpDstBeg,
(ULONG) ((lpDst - lpDstBeg) * sizeof( WCHAR ))
);
*lpDstLastSpace++ = L'\r';
*lpDstLastSpace++ = L'\n';
Column = (ULONG)(lpDst - lpDstBeg);
lpDst = lpDstLastSpace + Column;
lpDstLastSpace = NULL;
}
else {
if ((cchRemaining -= 2) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = L'\r';
*lpDst++ = L'\n';
lpDstLastSpace = NULL;
Column = 0;
}
}
}
if ((cchRemaining -= 2) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = '\r';
*lpDst++ = '\n';
if ((cchRemaining -= 1) <= 0) {
return STATUS_BUFFER_OVERFLOW;
}
*lpDst++ = '\0';
if ( ARGUMENT_PRESENT(ReturnLength) ) {
*ReturnLength = (ULONG)(lpDst - Buffer) * sizeof( WCHAR );
}
return( STATUS_SUCCESS );
}