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.
 
 
 
 
 
 

875 lines
25 KiB

/*++
Copyright (c) 2001-2002 Microsoft Corporation
Module Name:
CmnMisc.c
Abstract:
Miscellaneous common routines
Author:
George V. Reilly (GeorgeRe) 06-Dec-2001
Revision History:
--*/
#include "precomp.h"
#if defined(ALLOC_PRAGMA) && defined(KERNEL_PRIV)
#pragma alloc_text( INIT, HttpCmnInitializeHttpCharsTable )
#endif // ALLOC_PRAGMA && KERNEL_PRIV
#if 0 // Non-Pageable Functions
NOT PAGEABLE -- strnchr
NOT PAGEABLE -- wcsnchr
NOT PAGEABLE -- HttpStringToULongLong
NOT PAGEABLE -- HttpStringToULong
NOT PAGEABLE -- HttpStringToUShort
NOT PAGEABLE -- HttpFillBufferTrap
NOT PAGEABLE -- HttpFillBuffer
NOT PAGEABLE -- HttpStatusToString
#endif // Non-Pageable Functions
DECLSPEC_ALIGN(UL_CACHE_LINE) ULONG HttpChars[256];
DECLSPEC_ALIGN(UL_CACHE_LINE) WCHAR FastPopChars[256];
DECLSPEC_ALIGN(UL_CACHE_LINE) WCHAR DummyPopChars[256];
DECLSPEC_ALIGN(UL_CACHE_LINE) WCHAR FastUpcaseChars[256];
DECLSPEC_ALIGN(UL_CACHE_LINE) WCHAR AnsiToUnicodeMap[256];
//
// Counted version of strchr()
//
char*
strnchr(
const char* string,
char c,
size_t count
)
{
const char* end = string + count;
const char* s;
for (s = string; s < end; ++s)
{
if (c == *s)
return (char*) s;
}
return NULL;
} // strnchr
//
// Counted version of wcschr()
//
wchar_t*
wcsnchr(
const wchar_t* string,
wint_t c,
size_t count
)
{
const wchar_t* end = string + count;
const wchar_t* s;
for (s = string; s < end; ++s)
{
if (c == *s)
return (wchar_t*) s;
}
return NULL;
} // wcsnchr
#define SET_HTTP_FLAGS(Set, Flags) \
HttppCmnInitHttpCharsBySet((PUCHAR) (Set), sizeof(Set) - 1, (Flags))
__inline
VOID
HttppCmnInitHttpCharsBySet(
PUCHAR Set,
ULONG SetSize,
ULONG Flags
)
{
ULONG i;
ASSERT(NULL != Set);
ASSERT(SetSize > 0);
ASSERT(0 != Flags);
ASSERT('\0' == Set[SetSize]);
for (i = 0; i < SetSize; ++i)
{
UCHAR Byte = Set[i];
ASSERT(0 == (HttpChars[Byte] & Flags));
HttpChars[Byte] |= Flags;
}
}
/*++
Routine Description:
Routine to initialize HttpChars[] and the other lookup tables.
See the declarations in HttpCmn.h
--*/
VOID
HttpCmnInitializeHttpCharsTable(
BOOLEAN EnableDBCS
)
{
ULONG i;
CHAR AnsiChar;
WCHAR WideChar;
NTSTATUS Status;
RtlZeroMemory(HttpChars, sizeof(HttpChars));
for (i = 0; i <= ASCII_MAX; ++i)
{
HttpChars[i] |= HTTP_CHAR;
}
SET_HTTP_FLAGS(HTTP_CTL_SET, HTTP_CTL);
SET_HTTP_FLAGS(HTTP_UPALPHA_SET, HTTP_UPCASE);
SET_HTTP_FLAGS(HTTP_LOALPHA_SET, HTTP_LOCASE);
SET_HTTP_FLAGS(HTTP_DIGITS_SET, HTTP_DIGIT);
SET_HTTP_FLAGS(HTTP_LWS_SET, HTTP_LWS);
SET_HTTP_FLAGS(HTTP_HEX_SET, HTTP_HEX);
SET_HTTP_FLAGS(HTTP_SEPARATORS_SET, HTTP_SEPARATOR);
SET_HTTP_FLAGS(HTTP_WS_TOKEN_SET, HTTP_WS_TOKEN);
SET_HTTP_FLAGS(HTTP_ISWHITE_SET, HTTP_ISWHITE);
for (i = 0; i <= ASCII_MAX; ++i)
{
if (!IS_HTTP_SEPARATOR(i) && !IS_HTTP_CTL(i))
{
HttpChars[i] |= HTTP_TOKEN;
}
}
for (i = 0; i <= ANSI_HIGH_MAX; ++i)
{
if (!IS_HTTP_CTL(i) || IS_HTTP_LWS(i))
{
HttpChars[i] |= HTTP_PRINT;
}
if (!IS_HTTP_CTL(i) || IS_HTTP_WS_TOKEN(i))
{
HttpChars[i] |= HTTP_TEXT;
}
}
// Used in URI canonicalizer to identify '.', '/', '?' and '#'
HttpChars['.'] |= HTTP_CHAR_DOT;
HttpChars['/'] |= HTTP_CHAR_SLASH;
HttpChars['?'] |= HTTP_CHAR_QM_HASH;
HttpChars['#'] |= HTTP_CHAR_QM_HASH;
// URL flags initialization
//
// These US-ASCII characters are "excluded"; i.e., not URL_LEGAL (see RFC):
// '<' | '>' | ' ' (0x20)
// In addition, control characters (0x00-0x1F and 0x7F) and
// non US-ASCII characters (0x80-0xFF) are not URL_LEGAL.
//
SET_HTTP_FLAGS(URL_UNRESERVED_SET, URL_LEGAL);
SET_HTTP_FLAGS(URL_RESERVED_SET, URL_LEGAL);
// For compatibility with IIS 5.0 and DAV, we must allow
// the "unwise" characters in URLs.
SET_HTTP_FLAGS(URL_UNWISE_SET, URL_LEGAL);
SET_HTTP_FLAGS("%", URL_LEGAL);
SET_HTTP_FLAGS(URL_DIRTY_SET, URL_DIRTY);
// All characters outside US-ASCII range are considered dirty
for (i = ANSI_HIGH_MIN; i <= ANSI_HIGH_MAX; ++i)
HttpChars[i] |= URL_DIRTY;
SET_HTTP_FLAGS(URL_HOSTNAME_LABEL_LDH_SET, URL_HOSTNAME_LABEL);
SET_HTTP_FLAGS(URL_INVALID_SET, URL_INVALID);
SET_HTTP_FLAGS(URL_ILLEGAL_COMPUTERNAME_SET, URL_ILLEGAL_COMPUTERNAME);
//
// In DBCS locales we need to explicitly accept lead bytes that
// we would normally reject.
//
if (EnableDBCS)
{
// By definition, lead bytes are in the range 0x80-0xFF
for (i = ANSI_HIGH_MIN; i <= ANSI_HIGH_MAX; ++i)
{
#if KERNEL_PRIV
// These are copied from RTL NLS routines.
extern PUSHORT NlsLeadByteInfo;
BOOLEAN IsLeadByte
= (BOOLEAN) (((*(PUSHORT *) NlsLeadByteInfo)[i]) != 0);
#else // !KERNEL_PRIV
BOOLEAN IsLeadByte = (BOOLEAN) IsDBCSLeadByte((BYTE) i);
#endif // !KERNEL_PRIV
if (IsLeadByte)
{
HttpChars[i] |= HTTP_DBCS_LEAD_BYTE;
if (IS_HIGH_ANSI(i))
HttpChars[i] |= URL_LEGAL;
UlTrace(PARSER, (
"http!InitializeHttpUtil, "
"marking %x (%c) as a valid lead byte.\n",
i, i
));
}
else
{
// For the DBCS locales, almost all bytes above 128 are
// either lead bytes or valid single-byte characters.
AnsiChar = (CHAR) i;
Status = RtlMultiByteToUnicodeN(
&WideChar,
sizeof(WCHAR),
NULL,
(PCHAR) &AnsiChar,
1
);
if (NT_SUCCESS(Status))
{
HttpChars[i] |= URL_LEGAL;
UlTrace(PARSER, (
"http!InitializeHttpUtil, "
"marking %x (%c) as a legal DBCS character, %s.\n",
i, i,
HttpStatusToString(Status)
));
}
else
{
UlTrace(PARSER, (
"http!InitializeHttpUtil, "
"%x (%c) is not a legal DBCS character.\n",
i, i
));
}
}
}
}
// Build a lookup table that maps the 256 possible ANSI characters
// in the system code page to Unicode
for (i = 0; i <= ANSI_HIGH_MAX; ++i)
{
AnsiChar = (CHAR) i;
Status = RtlMultiByteToUnicodeN(
&WideChar,
sizeof(WCHAR),
NULL,
(PCHAR) &AnsiChar,
1
);
AnsiToUnicodeMap[i] = (NT_SUCCESS(Status) ? WideChar : 0);
// Also, handle upcasing the first 256 chars
FastUpcaseChars[i] = RtlUpcaseUnicodeChar((WCHAR) i);
}
//
// Fast path for PopChar. 0 => special handling.
//
RtlZeroMemory(FastPopChars, sizeof(FastPopChars));
RtlZeroMemory(DummyPopChars, sizeof(DummyPopChars));
for (i = 0; i <= ASCII_MAX; ++i)
{
UCHAR c = (UCHAR)i;
// (ALPHA | DIGIT | URL_LEGAL) && !IS_URL_DIRTY
if (IS_URL_TOKEN(c) && !IS_URL_DIRTY(c))
FastPopChars[i] = c;
}
// These characters are in the dirty set, so we need to set them explicitly
FastPopChars['.'] = L'.';
FastPopChars['/'] = L'/';
//
// Finally, initialize the UTF-8 data
//
HttpInitializeUtf8();
} // HttpCmnInitializeHttpCharsTable
#define MAX_ULONGLONG 18446744073709551615ui64
C_ASSERT(~0ui64 == MAX_ULONGLONG);
#define MAX_ULONG 0xFFFFFFFF
#define MAX_USHORT 0xFFFF
/***************************************************************************++
Routine Description:
Converts an ANSI or Unicode string to a ULONGLONG.
Fails on negative numbers, and assumes no preceding spaces.
Arguments:
IsUnicode Non-zero => pString is Unicode, otherwise it's ANSI.
pString The string to convert. Must point to the first digit.
StringLength Number of characters (ANSI or Unicode) in pString.
If zero, then the string must be NUL-terminated and
there may be non-digit characters before the
terminating NUL. Otherwise (counted string),
only digit characters may be present.
LeadingZerosAllowed String can/cannot start with leading zeros
Base The base of the string; must be 10 or 16
ppTerminator Pointer to the end of the numeric string. May be NULL.
pValue The return value of the converted ULONGLONG
Return Value:
STATUS_SUCCESS Valid number
STATUS_INVALID_PARAMETER Bad digit
STATUS_SECTION_TOO_BIG Numeric overflow
*ppTerminator always points to the string terminator, if it wasn't NULL
on entry. *pValue is valid only for STATUS_SUCCESS.
--***************************************************************************/
NTSTATUS
HttpStringToULongLong(
IN BOOLEAN IsUnicode,
IN PCVOID pString,
IN SIZE_T StringLength,
IN BOOLEAN LeadingZerosAllowed,
IN ULONG Base,
OUT PVOID* ppTerminator,
OUT PULONGLONG pValue
)
{
ULONGLONG Value = 0;
BOOLEAN ZeroTerminated = (BOOLEAN) (0 == StringLength);
BOOLEAN Decimal = (BOOLEAN) (10 == Base);
ULONG Mask = (Decimal ? HTTP_DIGIT : HTTP_HEX);
PCUCHAR pAnsiString = (PCUCHAR) pString;
PCWSTR pWideString = (PCWSTR) pString;
PVOID pLocalTerminator;
ULONGLONG OverflowLimit;
ULONG MaxLastDigit;
ULONG Index;
ULONG Char;
// If you've failed to call HttpCmnInitializeHttpCharsTable(),
// you'll hit this assertion
ASSERT(IS_HTTP_DIGIT('0'));
// If the caller doesn't care about the string terminator, just
// make ppTerminator point to something valid, so that we don't have
// to test it everywhere before assigning to it.
if (NULL == ppTerminator)
ppTerminator = &pLocalTerminator;
// Initialize ppTerminator to the beginning of the string
*ppTerminator = (PVOID) pString;
// Check for obviously invalid data
if (NULL == pString || NULL == pValue || (10 != Base && 16 != Base))
{
UlTraceError(PARSER, ("Invalid parameters\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
// First character must be a valid digit
Char = (IsUnicode ? pWideString[0] : pAnsiString[0]);
if (!IS_ASCII(Char) || !IS_CHAR_TYPE(Char, Mask))
{
UlTraceError(PARSER, ("No digits\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
// Check for leading zeros
if (!LeadingZerosAllowed && '0' == Char)
{
// If leading zeros are not allowed and the first character is zero,
// then it must be the only digit in the string.
if (ZeroTerminated)
{
// Check second digit
Char = (IsUnicode ? pWideString[1] : pAnsiString[1]);
if (IS_ASCII(Char) && IS_CHAR_TYPE(Char, Mask))
{
UlTraceError(PARSER, ("Second digit forbidden\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
}
else
{
// A counted string must have exactly one digit (the zero)
// in this case
if (StringLength != 1)
{
UlTraceError(PARSER, ("Second digit forbidden\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
}
}
// The calculations are done this way in the hope that the compiler
// will use compile-time constants
if (Decimal)
{
OverflowLimit = (MAX_ULONGLONG / 10);
MaxLastDigit = MAX_ULONGLONG % 10;
}
else
{
ASSERT(16 == Base);
OverflowLimit = (MAX_ULONGLONG >> 4);
MaxLastDigit = MAX_ULONGLONG & 0xF;
ASSERT(0xF == MaxLastDigit);
}
ASSERT(OverflowLimit < Base * OverflowLimit);
ASSERT(Base * OverflowLimit + MaxLastDigit == MAX_ULONGLONG);
// Loop through the string
for (Index = 0; ZeroTerminated || Index < StringLength; ++Index)
{
ULONGLONG NewValue;
ULONG Digit;
// Update ppTerminator first, in case of error
if (IsUnicode)
{
*ppTerminator = (PVOID) &pWideString[Index];
Char = pWideString[Index];
}
else
{
*ppTerminator = (PVOID) &pAnsiString[Index];
Char = pAnsiString[Index];
}
// Is Char is a valid digit?
if (!IS_ASCII(Char) || ! IS_CHAR_TYPE(Char, Mask))
{
if (ZeroTerminated)
{
// If the string is ultimately zero-terminated, but there
// are some non-digit characters after the number, that is
// not an error. Note: '\0' will fail the IS_CHAR_TYPE test.
break;
}
else
{
// For counted strings, only digits may be present
UlTraceError(PARSER, ("Invalid digit\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
}
if (IS_HTTP_ALPHA(Char))
{
ASSERT(('A' <= Char && Char <= 'F')
|| ('a' <= Char && Char <= 'f'));
if (Decimal)
{
// Chars in the range [A-Fa-f] are invalid in decimal numbers
if (ZeroTerminated)
{
// Anything outside the range [0-9] terminates the loop
break;
}
else
{
// For counted decimal strings, only decimal digits
// may be present
UlTraceError(PARSER, ("Non-decimal digit\n"));
RETURN(STATUS_INVALID_PARAMETER);
}
}
Digit = 0xA + (UPCASE_CHAR(Char) - 'A');
ASSERT(0xA <= Digit && Digit <= 0xF);
}
else
{
ASSERT('0' <= Char && Char <= '9');
Digit = Char - '0';
}
ASSERT(Digit < Base);
//
// Guard against arithmetic overflow. We just got a valid digit,
// but Value will (likely) overflow if we shift in another digit
//
if (Value >= OverflowLimit)
{
// Definite overflow
if (Value > OverflowLimit)
{
UlTraceError(PARSER, ("Numeric overflow\n"));
RETURN(STATUS_SECTION_TOO_BIG);
}
ASSERT(Value == OverflowLimit);
// May be able to accommodate the last digit
if (Digit > MaxLastDigit)
{
UlTraceError(PARSER, ("Numeric overflow\n"));
RETURN(STATUS_SECTION_TOO_BIG);
}
}
ASSERT(Value * Base <= MAX_ULONGLONG - Digit);
ASSERT(Value < Value * Base || 0 == Value);
if (Decimal)
NewValue = (10 * Value) + Digit;
else
NewValue = (Value << 4) | Digit;
ASSERT(NewValue > Value
|| (0 == Value && 0 == Digit
&& (LeadingZerosAllowed || (0 == Index))));
Value = NewValue;
}
// Must be a valid number if reached here
ASSERT(ZeroTerminated ? Index > 0 : Index == StringLength);
// Make ppTerminator point to the end of the string
if (IsUnicode)
*ppTerminator = (PVOID) &pWideString[Index];
else
*ppTerminator = (PVOID) &pAnsiString[Index];
*pValue = Value;
return STATUS_SUCCESS;
} // HttpStringToULongLong
NTSTATUS
HttpStringToULong(
IN BOOLEAN IsUnicode,
IN PCVOID pString,
IN SIZE_T StringLength,
IN BOOLEAN LeadingZerosAllowed,
IN ULONG Base,
OUT PVOID* ppTerminator,
OUT PULONG pValue
)
{
ULONGLONG Value;
NTSTATUS Status;
Status = HttpStringToULongLong(
IsUnicode,
pString,
StringLength,
LeadingZerosAllowed,
Base,
ppTerminator,
&Value
);
if (NT_SUCCESS(Status))
{
if (Value > MAX_ULONG)
{
UlTraceError(PARSER, ("Numeric overflow\n"));
RETURN(STATUS_SECTION_TOO_BIG);
}
else
{
*pValue = (ULONG) Value;
}
}
return Status;
} // HttpStringToULong
NTSTATUS
HttpStringToUShort(
IN BOOLEAN IsUnicode,
IN PCVOID pString,
IN SIZE_T StringLength,
IN BOOLEAN LeadingZerosAllowed,
IN ULONG Base,
OUT PVOID* ppTerminator,
OUT PUSHORT pValue
)
{
ULONGLONG Value;
NTSTATUS Status;
Status = HttpStringToULongLong(
IsUnicode,
pString,
StringLength,
LeadingZerosAllowed,
Base,
ppTerminator,
&Value
);
if (NT_SUCCESS(Status))
{
if (Value > MAX_USHORT)
{
UlTraceError(PARSER, ("Numeric overflow\n"));
RETURN(STATUS_SECTION_TOO_BIG);
}
else
{
*pValue = (USHORT) Value;
}
}
return Status;
} // HttpStringToUShort
#if DBG
VOID
HttpFillBufferTrap(
VOID
)
{
ASSERT(! "HttpFillBufferTrap");
}
//
// Fill an output buffer with a known pattern. Helps detect buffer overruns.
//
VOID
HttpFillBuffer(
PUCHAR pBuffer,
SIZE_T BufferLength
)
{
union
{
ULONG_PTR UlongPtr;
UCHAR Bytes[sizeof(ULONG_PTR)];
} FillPattern;
const ULONG_PTR Mask = sizeof(ULONG_PTR) - 1;
ULONG_PTR i;
ULONG_PTR OriginalBufferLength = BufferLength;
PUCHAR pOriginalBuffer = pBuffer;
PULONG_PTR pAlignedBuffer;
ASSERT(NULL != pBuffer);
ASSERT(BufferLength > 0);
FillPattern.UlongPtr = (ULONG_PTR) &HttpFillBufferTrap;
// Fill any unaligned bytes at the beginning of the buffer
for (i = (ULONG_PTR) pBuffer;
(i & Mask) != 0 && BufferLength > 0;
++i, --BufferLength
)
{
*pBuffer++ = FillPattern.Bytes[i & Mask];
}
ASSERT(((ULONG_PTR) pBuffer & Mask) == 0);
// Fill as much as possible of the buffer with ULONG_PTRs
pAlignedBuffer = (PULONG_PTR) pBuffer;
for (i = (BufferLength & ~Mask); i > 0; i -= sizeof(ULONG_PTR))
{
ASSERT((i & Mask) == 0);
*pAlignedBuffer++ = FillPattern.UlongPtr;
}
// Fill any unaligned bytes at the tail of the buffer
pBuffer = (PUCHAR) pAlignedBuffer;
ASSERT(((ULONG_PTR) pBuffer & Mask) == 0);
for (i = 0; i != (BufferLength & Mask); ++i)
{
*pBuffer++ = FillPattern.Bytes[i & Mask];
}
ASSERT(pOriginalBuffer + OriginalBufferLength == pBuffer);
} // HttpFillBuffer
#endif // DBG
//
// Convert an NTSTATUS to a string, for use in debug spew.
//
PCSTR
HttpStatusToString(
NTSTATUS Status
)
{
static NTSTATUS s_KnownUnhandledStatus = 0;
PCSTR String;
switch (Status)
{
default:
// If you hit this, add the newly used status code below
WriteGlobalStringLog("Unhandled NTSTATUS, 0x%08lX\n", Status);
// Only assert once. If you've got two new NTSTATUSes, well, tough.
if (Status != s_KnownUnhandledStatus)
{
ASSERT(! "Unhandled NTSTATUS");
s_KnownUnhandledStatus = Status;
}
String = "<STATUS_???>";
break;
#define STATUS_CASE(n, s) \
case s: \
{ \
C_ASSERT((NTSTATUS) n == s);\
String = #s; \
break; \
}
STATUS_CASE( 0xC0000022, STATUS_ACCESS_DENIED );
STATUS_CASE( 0xC0000005, STATUS_ACCESS_VIOLATION );
STATUS_CASE( 0xC000020A, STATUS_ADDRESS_ALREADY_EXISTS );
STATUS_CASE( 0xC0000099, STATUS_ALLOTTED_SPACE_EXCEEDED );
STATUS_CASE( 0x80000005, STATUS_BUFFER_OVERFLOW );
STATUS_CASE( 0xC0000023, STATUS_BUFFER_TOO_SMALL );
STATUS_CASE( 0xC0000120, STATUS_CANCELLED );
STATUS_CASE( 0xC0000018, STATUS_CONFLICTING_ADDRESSES );
STATUS_CASE( 0xC0000241, STATUS_CONNECTION_ABORTED );
STATUS_CASE( 0xC000023B, STATUS_CONNECTION_ACTIVE );
STATUS_CASE( 0xC000020C, STATUS_CONNECTION_DISCONNECTED );
STATUS_CASE( 0xC000023A, STATUS_CONNECTION_INVALID );
STATUS_CASE( 0xC0000236, STATUS_CONNECTION_REFUSED );
STATUS_CASE( 0xC000020D, STATUS_CONNECTION_RESET );
STATUS_CASE( 0xC00002C5, STATUS_DATATYPE_MISALIGNMENT_ERROR );
STATUS_CASE( 0xC000021B, STATUS_DATA_NOT_ACCEPTED );
STATUS_CASE( 0xC000003C, STATUS_DATA_OVERRUN );
STATUS_CASE( 0xC000007F, STATUS_DISK_FULL );
STATUS_CASE( 0xC00000BD, STATUS_DUPLICATE_NAME );
STATUS_CASE( 0xC0000011, STATUS_END_OF_FILE );
STATUS_CASE( 0xC0000098, STATUS_FILE_INVALID );
STATUS_CASE( 0xC0000004, STATUS_INFO_LENGTH_MISMATCH );
STATUS_CASE( 0xC000009A, STATUS_INSUFFICIENT_RESOURCES );
STATUS_CASE( 0xC0000095, STATUS_INTEGER_OVERFLOW );
STATUS_CASE( 0xC0000141, STATUS_INVALID_ADDRESS );
STATUS_CASE( 0xC0000010, STATUS_INVALID_DEVICE_REQUEST );
STATUS_CASE( 0xC0000184, STATUS_INVALID_DEVICE_STATE );
STATUS_CASE( 0xC0000008, STATUS_INVALID_HANDLE );
STATUS_CASE( 0xC0000084, STATUS_INVALID_ID_AUTHORITY );
STATUS_CASE( 0xC00000C3, STATUS_INVALID_NETWORK_RESPONSE );
STATUS_CASE( 0xC000005A, STATUS_INVALID_OWNER );
STATUS_CASE( 0xC000000D, STATUS_INVALID_PARAMETER );
STATUS_CASE( 0xC00000B5, STATUS_IO_TIMEOUT );
STATUS_CASE( 0xC0000016, STATUS_MORE_PROCESSING_REQUIRED );
STATUS_CASE( 0xC0000106, STATUS_NAME_TOO_LONG );
STATUS_CASE( 0xC0000225, STATUS_NOT_FOUND );
STATUS_CASE( 0xC0000002, STATUS_NOT_IMPLEMENTED );
STATUS_CASE( 0xC00000BB, STATUS_NOT_SUPPORTED );
STATUS_CASE( 0xC00002F1, STATUS_NO_IP_ADDRESSES );
STATUS_CASE( 0xC0000017, STATUS_NO_MEMORY );
STATUS_CASE( 0x8000001A, STATUS_NO_MORE_ENTRIES );
STATUS_CASE( 0x80000006, STATUS_NO_MORE_FILES );
STATUS_CASE( 0xC000000F, STATUS_NO_SUCH_FILE );
STATUS_CASE( 0xC000029F, STATUS_NO_TRACKING_SERVICE );
STATUS_CASE( 0xC000022B, STATUS_OBJECTID_EXISTS );
STATUS_CASE( 0xC0000035, STATUS_OBJECT_NAME_COLLISION );
STATUS_CASE( 0xC0000033, STATUS_OBJECT_NAME_INVALID );
STATUS_CASE( 0xC0000034, STATUS_OBJECT_NAME_NOT_FOUND );
STATUS_CASE( 0xC0000039, STATUS_OBJECT_PATH_INVALID );
STATUS_CASE( 0xC000003A, STATUS_OBJECT_PATH_NOT_FOUND );
STATUS_CASE( 0xC000003B, STATUS_OBJECT_PATH_SYNTAX_BAD );
STATUS_CASE( 0x00000103, STATUS_PENDING );
STATUS_CASE( 0xC00000D9, STATUS_PIPE_EMPTY );
STATUS_CASE( 0xC0000037, STATUS_PORT_DISCONNECTED );
STATUS_CASE( 0xC000022D, STATUS_RETRY );
STATUS_CASE( 0xC0000059, STATUS_REVISION_MISMATCH );
STATUS_CASE( 0xC0000040, STATUS_SECTION_TOO_BIG );
STATUS_CASE( 0xC0000043, STATUS_SHARING_VIOLATION );
STATUS_CASE( 0x00000000, STATUS_SUCCESS );
STATUS_CASE( 0xC0000001, STATUS_UNSUCCESSFUL );
STATUS_CASE( 0xC0000295, STATUS_WMI_GUID_NOT_FOUND );
}
return String;
} // HttpStatusToString