ReactOS  0.4.14-dev-98-gb0d4763
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 
25 static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)( LPWSTR dst, DWORD dstlen, LPDWORD reslen,
27 static NTSTATUS (WINAPI *pRtlCreateEnvironment)(BOOLEAN, PWSTR*);
28 static NTSTATUS (WINAPI *pRtlDestroyEnvironment)(PWSTR);
29 static NTSTATUS (WINAPI *pRtlQueryEnvironmentVariable_U)(PWSTR, PUNICODE_STRING, PUNICODE_STRING);
30 static void (WINAPI *pRtlSetCurrentEnvironment)(PWSTR, PWSTR*);
31 static NTSTATUS (WINAPI *pRtlSetEnvironmentVariable)(PWSTR*, PUNICODE_STRING, PUNICODE_STRING);
32 static NTSTATUS (WINAPI *pRtlExpandEnvironmentStrings_U)(LPWSTR, PUNICODE_STRING, PUNICODE_STRING, PULONG);
33 
34 static 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 
52 static 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"},
74  {"f", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
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"},
80  {"", 256, STATUS_VARIABLE_NOT_FOUND, NULL},
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 
127 static 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 
170 static 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);
198  testSetHelper(&env, tmp, NULL, STATUS_SUCCESS, 0);
199  }
200  testSetHelper(&env, "fOo", NULL, STATUS_SUCCESS, 0);
201 
202  ok(pRtlDestroyEnvironment(env) == STATUS_SUCCESS, "Destroying environment\n");
203 }
204 
205 static 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 }
struct param_test tests[]
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
USHORT MaximumLength
Definition: env_spec_w32.h:370
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static PULONG
Definition: env.c:32
uint16_t * PWSTR
Definition: typedefs.h:54
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static void testExpand(void)
Definition: env.c:205
LONG NTSTATUS
Definition: precomp.h:26
START_TEST(env)
Definition: env.c:1243
#define test
Definition: rosglue.h:37
static PUNICODE_STRING
Definition: env.c:29
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
void(WINAPI *pSdbReleaseDatabase)(HSDB hsdb)
#define sprintf(buf, format,...)
Definition: sprintf.c:55
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 void testQuery(void)
Definition: env.c:52
smooth NULL
Definition: ftsmooth.c:416
const char * LPCSTR
Definition: xmlstorage.h:183
static DWORD LPDWORD LPCSTR src
Definition: env.c:25
GLuint GLfloat * val
Definition: glext.h:7180
static void testSetHelper(LPWSTR *env, const char *var, const char *val, NTSTATUS ret, NTSTATUS alt)
Definition: env.c:127
__wchar_t WCHAR
Definition: xmlstorage.h:180
static WCHAR small_env[]
Definition: env.c:34
#define WINAPI
Definition: msvc.h:8
static void testSet(void)
Definition: env.c:170
unsigned long DWORD
Definition: ntddk_ex.h:95
static DWORD LPDWORD reslen
Definition: env.c:25
static DWORD LPDWORD LPCSTR DWORD srclen
Definition: env.c:25
int ret
#define STATUS_VARIABLE_NOT_FOUND
Definition: ntstatus.h:478
GLenum GLsizei len
Definition: glext.h:6722
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
GLenum src
Definition: glext.h:6340
GLsizei const GLfloat * value
Definition: glext.h:6069
#define broken(x)
Definition: _sntprintf.h:21
#define ok(value,...)
Definition: atltest.h:57
GLenum GLenum dst
Definition: glext.h:6340
static DWORD dstlen
Definition: env.c:25
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:168
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static NTSTATUS(WINAPI *pRtlMultiByteToUnicodeN)(LPWSTR dst
Definition: name.c:36
#define BOOLEAN
Definition: pedump.c:73
uint32_t * LPDWORD
Definition: typedefs.h:57
unsigned int ULONG
Definition: retypes.h:1
#define GetProcAddress(x, y)
Definition: compat.h:410
WCHAR * LPWSTR
Definition: xmlstorage.h:184
return STATUS_SUCCESS
Definition: btrfs.c:2966
static SERVICE_STATUS status
Definition: service.c:31
#define win_skip
Definition: test.h:141
static int mod
Definition: i386-dis.c:1273
GLuint const GLchar * name
Definition: glext.h:6031