xref: /reactos/sdk/lib/inflib/infhostrtl.c (revision 40462c92)
1 /*
2  * PROJECT:    .inf file parser
3  * LICENSE:    GPL - See COPYING in the top level directory
4  * PROGRAMMER: Royce Mitchell III
5  *             Eric Kohl
6  *             Ge van Geldorp <gvg@reactos.org>
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "inflib.h"
12 #include "infhost.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 NTSTATUS NTAPI
18 RtlMultiByteToUnicodeN(
19    IN PWCHAR UnicodeString,
20    IN ULONG UnicodeSize,
21    IN PULONG ResultSize,
22    IN PCSTR MbString,
23    IN ULONG MbSize)
24 {
25     ULONG Size = 0;
26     ULONG i;
27     PUCHAR WideString;
28 
29     /* single-byte code page */
30     if (MbSize > (UnicodeSize / sizeof(WCHAR)))
31         Size = UnicodeSize / sizeof(WCHAR);
32     else
33         Size = MbSize;
34 
35     if (ResultSize != NULL)
36         *ResultSize = Size * sizeof(WCHAR);
37 
38     WideString = (PUCHAR)UnicodeString;
39     for (i = 0; i < Size; i++)
40     {
41         WideString[2 * i + 0] = (UCHAR)MbString[i];
42         WideString[2 * i + 1] = 0;
43     }
44 
45     return STATUS_SUCCESS;
46 }
47 
48 
49 BOOLEAN
50 NTAPI
51 RtlIsTextUnicode( PVOID buf, INT len, INT *pf )
52 {
53     static const WCHAR std_control_chars[] = {'\r','\n','\t',' ',0x3000,0};
54     static const WCHAR byterev_control_chars[] = {0x0d00,0x0a00,0x0900,0x2000,0};
55     const WCHAR *s = buf;
56     int i;
57     unsigned int flags = MAXULONG, out_flags = 0;
58 
59     if (len < sizeof(WCHAR))
60     {
61         /* FIXME: MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing... */
62         if (pf) *pf = 0;
63         return FALSE;
64     }
65     if (pf)
66         flags = (unsigned int)*pf;
67     /*
68      * Apply various tests to the text string. According to the
69      * docs, each test "passed" sets the corresponding flag in
70      * the output flags. But some of the tests are mutually
71      * exclusive, so I don't see how you could pass all tests ...
72      */
73 
74     /* Check for an odd length ... pass if even. */
75     if (len & 1) out_flags |= IS_TEXT_UNICODE_ODD_LENGTH;
76 
77     if (((char *)buf)[len - 1] == 0)
78         len--;  /* Windows seems to do something like that to avoid e.g. false IS_TEXT_UNICODE_NULL_BYTES  */
79 
80     len /= (INT)sizeof(WCHAR);
81     /* Windows only checks the first 256 characters */
82     if (len > 256) len = 256;
83 
84     /* Check for the special byte order unicode marks. */
85     if (*s == 0xFEFF) out_flags |= IS_TEXT_UNICODE_SIGNATURE;
86     if (*s == 0xFFFE) out_flags |= IS_TEXT_UNICODE_REVERSE_SIGNATURE;
87 
88     /* apply some statistical analysis */
89     if (flags & IS_TEXT_UNICODE_STATISTICS)
90     {
91         int stats = 0;
92         /* FIXME: checks only for ASCII characters in the unicode stream */
93         for (i = 0; i < len; i++)
94         {
95             if (s[i] <= 255) stats++;
96         }
97         if (stats > len / 2)
98             out_flags |= IS_TEXT_UNICODE_STATISTICS;
99     }
100 
101     /* Check for unicode NULL chars */
102     if (flags & IS_TEXT_UNICODE_NULL_BYTES)
103     {
104         for (i = 0; i < len; i++)
105         {
106             if (!(s[i] & 0xff) || !(s[i] >> 8))
107             {
108                 out_flags |= IS_TEXT_UNICODE_NULL_BYTES;
109                 break;
110             }
111         }
112     }
113 
114     if (flags & IS_TEXT_UNICODE_CONTROLS)
115     {
116         for (i = 0; i < len; i++)
117         {
118             if (strchrW(std_control_chars, s[i]))
119             {
120                 out_flags |= IS_TEXT_UNICODE_CONTROLS;
121                 break;
122             }
123         }
124     }
125 
126     if (flags & IS_TEXT_UNICODE_REVERSE_CONTROLS)
127     {
128         for (i = 0; i < len; i++)
129         {
130             if (strchrW(byterev_control_chars, s[i]))
131             {
132                 out_flags |= IS_TEXT_UNICODE_REVERSE_CONTROLS;
133                 break;
134             }
135         }
136     }
137 
138     if (pf)
139     {
140         out_flags &= (unsigned int)*pf;
141         *pf = (INT)out_flags;
142     }
143     /* check for flags that indicate it's definitely not valid Unicode */
144     if (out_flags & (IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK)) return FALSE;
145     /* now check for invalid ASCII, and assume Unicode if so */
146     if (out_flags & IS_TEXT_UNICODE_NOT_ASCII_MASK) return TRUE;
147     /* now check for Unicode flags */
148     if (out_flags & IS_TEXT_UNICODE_UNICODE_MASK) return TRUE;
149     /* no flags set */
150     return FALSE;
151 }
152