/* * PROJECT: .inf file parser * LICENSE: GPL - See COPYING in the top level directory * PROGRAMMER: Royce Mitchell III * Eric Kohl * Ge van Geldorp */ /* INCLUDES *****************************************************************/ #include "inflib.h" #include "infhost.h" #define NDEBUG #include NTSTATUS NTAPI RtlMultiByteToUnicodeN( IN PWCHAR UnicodeString, IN ULONG UnicodeSize, IN PULONG ResultSize, IN PCSTR MbString, IN ULONG MbSize) { ULONG Size = 0; ULONG i; PUCHAR WideString; /* single-byte code page */ if (MbSize > (UnicodeSize / sizeof(WCHAR))) Size = UnicodeSize / sizeof(WCHAR); else Size = MbSize; if (ResultSize != NULL) *ResultSize = Size * sizeof(WCHAR); WideString = (PUCHAR)UnicodeString; for (i = 0; i < Size; i++) { WideString[2 * i + 0] = (UCHAR)MbString[i]; WideString[2 * i + 1] = 0; } return STATUS_SUCCESS; } BOOLEAN NTAPI RtlIsTextUnicode( PVOID buf, INT len, INT *pf ) { static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0}; static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0}; const WCHAR *s = buf; int i; unsigned int flags = MAXULONG, out_flags = 0; if (len < sizeof(WCHAR)) { /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */ if (pf) *pf = 0; return FALSE; } if (pf) flags = (unsigned int)*pf; /* * Apply various tests to the text string. According to the * docs, each test "passed" sets the corresponding flag in * the output flags. But some of the tests are mutually * exclusive, so I don't see how you could pass all tests ... */ /* Check for an odd length ... pass if even. */ if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH; if (((char *)buf)[len - 1] == 0) len--; /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES */ len /= (INT)sizeof(WCHAR); /* Windows only checks the first 256 characters */ if (len > 256) len = 256; /* Check for the special byte order unicode marks. */ if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE; if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE; /* apply some statistical analysis */ if (flags & IS_TEXT_UNICODE_STATISTICS) { int stats = 0; /* FIXME: checks only for ASCII characters in the unicode stream */ for (i = 0; i < len; i++) { if (s[i] <= 255) stats++; } if (stats > len / 2) out_flags |= IS_TEXT_UNICODE_STATISTICS; } /* Check for unicode NULL chars */ if (flags & IS_TEXT_UNICODE_NULL_BYTES) { for (i = 0; i < len; i++) { if (!(s[i] & 0xff) || !(s[i] >> 8)) { out_flags |= IS_TEXT_UNICODE_NULL_BYTES; break; } } } if (flags & IS_TEXT_UNICODE_CONTROLS) { for (i = 0; i < len; i++) { if (strchrW(std_control_chars, s[i])) { out_flags |= IS_TEXT_UNICODE_CONTROLS; break; } } } if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS) { for (i = 0; i < len; i++) { if (strchrW(byterev_control_chars, s[i])) { out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS; break; } } } if (pf) { out_flags &= (unsigned int)*pf; *pf = (INT)out_flags; } /* check for flags that indicate it's definitely not valid Unicode */ if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE; /* now check for invalid ASCII, and assume Unicode if so */ if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE; /* now check for Unicode flags */ if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE; /* no flags set */ return FALSE; }