ReactOS 0.4.15-dev-7659-ga55345b
env.c
Go to the documentation of this file.
1/*
2 * Unit test suite for ntdll path functions
3 *
4 * Copyright 2003 Eric Pouech
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdio.h>
22
23#include "ntdll_test.h"
24
25static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
27static NTSTATUS (WINAPI *pRtlCreateEnvironment)(BOOLEAN, PWSTR*);
28static NTSTATUS (WINAPI *pRtlDestroyEnvironment)(PWSTR);
29static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING);
30static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*);
31static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING);
32static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG);
33
34static WCHAR small_env[] = {'f','o','o','=','t','o','t','o',0,
35 'f','o','=','t','i','t','i',0,
36 'f','o','o','o','=','t','u','t','u',0,
37 's','r','=','a','n','=','o','u','o',0,
38 'g','=','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
39 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
40 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
41 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
42 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
43 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
44 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
45 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
46 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
47 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0,
48 '=','o','O','H','=','I','I','I',0,
49 'n','u','l','=',0,
50 0};
51
52static void testQuery(void)
53{
54 struct test
55 {
56 const char *var;
57 int len;
59 const char *val;
60 NTSTATUS alt;
61 };
62
63 static const struct test tests[] =
64 {
65 {"foo", 256, STATUS_SUCCESS, "toto"},
66 {"FoO", 256, STATUS_SUCCESS, "toto"},
67 {"foo=", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
68 {"foo ", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
69 {"foo", 1, STATUS_BUFFER_TOO_SMALL, "toto"},
70 {"foo", 3, STATUS_BUFFER_TOO_SMALL, "toto"},
71 {"foo", 4, STATUS_SUCCESS, "toto", STATUS_BUFFER_TOO_SMALL},
72 {"foo", 5, STATUS_SUCCESS, "toto"},
73 {"fooo", 256, STATUS_SUCCESS, "tutu"},
75 {"g", 256, STATUS_SUCCESS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
76"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
77 {"sr=an", 256, STATUS_SUCCESS, "ouo", STATUS_VARIABLE_NOT_FOUND},
78 {"sr", 256, STATUS_SUCCESS, "an=ouo"},
79 {"=oOH", 256, STATUS_SUCCESS, "III"},
81 {"nul", 256, STATUS_SUCCESS, ""},
82 {NULL, 0, 0, NULL}
83 };
84
85 WCHAR bn[257];
86 WCHAR bv[257];
89 NTSTATUS nts;
90 unsigned int i;
91
92 for (i = 0; tests[i].var; i++)
93 {
94 const struct test *test = &tests[i];
95 name.Length = strlen(test->var) * 2;
96 name.MaximumLength = name.Length + 2;
97 name.Buffer = bn;
98 value.Length = 0;
99 value.MaximumLength = test->len * 2;
100 value.Buffer = bv;
101 bv[test->len] = '@';
102
103 pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->var, strlen(test->var)+1 );
104 nts = pRtlQueryEnvironmentVariable_U(small_env, &name, &value);
105 ok( nts == test->status || (test->alt && nts == test->alt),
106 "[%d]: Wrong status for '%s', expecting %x got %x\n",
107 i, test->var, test->status, nts );
108 if (nts == test->status) switch (nts)
109 {
110 case STATUS_SUCCESS:
111 pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->val, strlen(test->val)+1 );
112 ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d for %s\n",
113 value.Length, test->var );
114 ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, value.Length) == 0) ||
115 lstrcmpW(bv, bn) == 0,
116 "Wrong result for %s/%d\n", test->var, test->len);
117 ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len);
118 break;
120 ok( value.Length == strlen(test->val) * sizeof(WCHAR),
121 "Wrong returned length %d (too small buffer) for %s\n", value.Length, test->var );
122 break;
123 }
124 }
125}
126
127static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret, NTSTATUS alt)
128{
129 WCHAR bvar[256], bval1[256], bval2[256];
130 UNICODE_STRING uvar;
131 UNICODE_STRING uval;
132 NTSTATUS nts;
133
134 uvar.Length = strlen(var) * sizeof(WCHAR);
135 uvar.MaximumLength = uvar.Length + sizeof(WCHAR);
136 uvar.Buffer = bvar;
137 pRtlMultiByteToUnicodeN( bvar, sizeof(bvar), NULL, var, strlen(var)+1 );
138 if (val)
139 {
140 uval.Length = strlen(val) * sizeof(WCHAR);
141 uval.MaximumLength = uval.Length + sizeof(WCHAR);
142 uval.Buffer = bval1;
143 pRtlMultiByteToUnicodeN( bval1, sizeof(bval1), NULL, val, strlen(val)+1 );
144 }
145 nts = pRtlSetEnvironmentVariable(env, &uvar, val ? &uval : NULL);
146 ok(nts == ret || (alt && nts == alt), "Setting var %s=%s (%x/%x)\n", var, val, nts, ret);
147 if (nts == STATUS_SUCCESS)
148 {
149 uval.Length = 0;
150 uval.MaximumLength = sizeof(bval2);
151 uval.Buffer = bval2;
152 nts = pRtlQueryEnvironmentVariable_U(*env, &uvar, &uval);
153 switch (nts)
154 {
155 case STATUS_SUCCESS:
156 ok(lstrcmpW(bval1, bval2) == 0, "Cannot get value written to environment\n");
157 break;
159 ok(val == NULL ||
160 broken(strchr(var,'=') != NULL), /* variable containing '=' may be set but not found again on NT4 */
161 "Couldn't find variable, but didn't delete it. val = %s\n", val);
162 break;
163 default:
164 ok(0, "Wrong ret %u for %s\n", nts, var);
165 break;
166 }
167 }
168}
169
170static void testSet(void)
171{
172 LPWSTR env;
173 char tmp[16];
174 int i;
175
176 ok(pRtlCreateEnvironment(FALSE, &env) == STATUS_SUCCESS, "Creating environment\n");
177
178 testSetHelper(&env, "cat", "dog", STATUS_SUCCESS, 0);
179 testSetHelper(&env, "cat", "horse", STATUS_SUCCESS, 0);
180 testSetHelper(&env, "cat", "zz", STATUS_SUCCESS, 0);
181 testSetHelper(&env, "cat", NULL, STATUS_SUCCESS, 0);
183 testSetHelper(&env, "foo", "meouw", STATUS_SUCCESS, 0);
185 testSetHelper(&env, "me", "too=also", STATUS_SUCCESS, 0);
186 testSetHelper(&env, "=too", "also", STATUS_SUCCESS, 0);
187 testSetHelper(&env, "=", "also", STATUS_SUCCESS, 0);
188
189 for (i = 0; i < 128; i++)
190 {
191 sprintf(tmp, "zork%03d", i);
192 testSetHelper(&env, tmp, "is alive", STATUS_SUCCESS, 0);
193 }
194
195 for (i = 0; i < 128; i++)
196 {
197 sprintf(tmp, "zork%03d", i);
199 }
200 testSetHelper(&env, "fOo", NULL, STATUS_SUCCESS, 0);
201
202 ok(pRtlDestroyEnvironment(env) == STATUS_SUCCESS, "Destroying environment\n");
203}
204
205static void testExpand(void)
206{
207 static const struct test
208 {
209 const char *src;
210 const char *dst;
211 } tests[] =
212 {
213 {"hello%foo%world", "hellototoworld"},
214 {"hello%=oOH%world", "helloIIIworld"},
215 {"hello%foo", "hello%foo"},
216 {"hello%bar%world", "hello%bar%world"},
217 /*
218 * {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"},
219 * Interestingly enough, with a 8 WCHAR buffers, we get on 2k:
220 * helloIII
221 * so it seems like strings overflowing the buffer are written
222 * (truncated) but the write cursor is not advanced :-/
223 */
224 {NULL, NULL}
225 };
226
227 const struct test* test;
228 NTSTATUS nts;
229 UNICODE_STRING us_src, us_dst;
230 WCHAR src[256], dst[256], rst[256];
231 ULONG ul;
232
233 for (test = tests; test->src; test++)
234 {
235 pRtlMultiByteToUnicodeN(src, sizeof(src), NULL, test->src, strlen(test->src)+1);
236 pRtlMultiByteToUnicodeN(rst, sizeof(rst), NULL, test->dst, strlen(test->dst)+1);
237
238 us_src.Length = strlen(test->src) * sizeof(WCHAR);
239 us_src.MaximumLength = us_src.Length + 2;
240 us_src.Buffer = src;
241
242 us_dst.Length = 0;
243 us_dst.MaximumLength = 0;
244 us_dst.Buffer = NULL;
245
246 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
247 ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
248 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
249 "Wrong returned length for %s: %u\n", test->src, ul );
250
251 us_dst.Length = 0;
252 us_dst.MaximumLength = sizeof(dst);
253 us_dst.Buffer = dst;
254
255 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
256 ok(nts == STATUS_SUCCESS, "Call failed (%u)\n", nts);
257 ok(ul == us_dst.Length + sizeof(WCHAR),
258 "Wrong returned length for %s: %u\n", test->src, ul);
259 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
260 "Wrong returned length for %s: %u\n", test->src, ul);
261 ok(lstrcmpW(dst, rst) == 0, "Wrong result for %s: expecting %s\n",
262 test->src, test->dst);
263
264 us_dst.Length = 0;
265 us_dst.MaximumLength = 8 * sizeof(WCHAR);
266 us_dst.Buffer = dst;
267 dst[8] = '-';
268 nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul);
269 ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts);
270 ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR),
271 "Wrong returned length for %s (with buffer too small): %u\n", test->src, ul);
272 ok(dst[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst[8], dst[8]);
273 }
274
275}
276
278{
279 HMODULE mod = GetModuleHandleA("ntdll.dll");
280 if (!mod)
281 {
282 win_skip("Not running on NT, skipping tests\n");
283 return;
284 }
285
286 pRtlMultiByteToUnicodeN = (void *)GetProcAddress(mod,"RtlMultiByteToUnicodeN");
287 pRtlCreateEnvironment = (void*)GetProcAddress(mod, "RtlCreateEnvironment");
288 pRtlDestroyEnvironment = (void*)GetProcAddress(mod, "RtlDestroyEnvironment");
289 pRtlQueryEnvironmentVariable_U = (void*)GetProcAddress(mod, "RtlQueryEnvironmentVariable_U");
290 pRtlSetCurrentEnvironment = (void*)GetProcAddress(mod, "RtlSetCurrentEnvironment");
291 pRtlSetEnvironmentVariable = (void*)GetProcAddress(mod, "RtlSetEnvironmentVariable");
292 pRtlExpandEnvironmentStrings_U = (void*)GetProcAddress(mod, "RtlExpandEnvironmentStrings_U");
293
294 if (pRtlQueryEnvironmentVariable_U)
295 testQuery();
296 if (pRtlSetEnvironmentVariable)
297 testSet();
298 if (pRtlExpandEnvironmentStrings_U)
299 testExpand();
300}
#define broken(x)
Definition: _sntprintf.h:21
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:21
#define GetProcAddress(x, y)
Definition: compat.h:753
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static int mod
Definition: i386-dis.c:1288
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static struct test_info tests[]
#define sprintf(buf, format,...)
Definition: sprintf.c:55
const char * var
Definition: shader.c:5666
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: env.c:26
static DWORD LPDWORD reslen
Definition: env.c:25
static void testExpand(void)
Definition: env.c:205
static void testSet(void)
Definition: env.c:170
static PUNICODE_STRING
Definition: env.c:29
static DWORD dstlen
Definition: env.c:25
static WCHAR small_env[]
Definition: env.c:34
static DWORD LPDWORD LPCSTR src
Definition: env.c:26
static void testSetHelper(LPWSTR *env, const char *var, const char *val, NTSTATUS ret, NTSTATUS alt)
Definition: env.c:127
static void testQuery(void)
Definition: env.c:52
static PULONG
Definition: env.c:32
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:492
#define BOOLEAN
Definition: pedump.c:73
#define test
Definition: rosglue.h:37
#define win_skip
Definition: test.h:160
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: name.c:39
Definition: ps.c:97
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * LPDWORD
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
Definition: pdh_main.c:94
int ret
#define WINAPI
Definition: msvc.h:6
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184