2 * Copyright 2010 Detlef Riekenberg
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/test.h"
28 #define DEFINE_EXPECT(func) \
29 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
31 #define SET_EXPECT(func) \
32 expect_ ## func = TRUE
34 #define CHECK_EXPECT2(func) \
36 ok(expect_ ##func, "unexpected call " #func "\n"); \
37 called_ ## func = TRUE; \
40 #define CHECK_EXPECT(func) \
42 CHECK_EXPECT2(func); \
43 expect_ ## func = FALSE; \
46 #define CHECK_CALLED(func) \
48 ok(called_ ## func, "expected " #func "\n"); \
49 expect_ ## func = called_ ## func = FALSE; \
52 DEFINE_EXPECT(invalid_parameter_handler);
54 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
55 typedef int (__cdecl *_INITTERM_E_FN)(void);
56 static int (__cdecl *p_initterm_e)(_INITTERM_E_FN *table, _INITTERM_E_FN *end);
57 static void* (__cdecl *p_encode_pointer)(void *);
58 static void* (__cdecl *p_decode_pointer)(void *);
59 static void* (__cdecl *p_encoded_null)(void);
60 static int *p_sys_nerr;
61 static int* (__cdecl *p__sys_nerr)(void);
62 static char **p_sys_errlist;
63 static char** (__cdecl *p__sys_errlist)(void);
64 static __int64 (__cdecl *p_strtoi64)(const char *, char **, int);
65 static unsigned __int64 (__cdecl *p_strtoui64)(const char *, char **, int);
66 static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
67 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
69 static void* (WINAPI *pEncodePointer)(void *);
71 static int cb_called[4];
75 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
76 const wchar_t *function, const wchar_t *file,
77 unsigned line, uintptr_t arg)
79 CHECK_EXPECT(invalid_parameter_handler);
80 ok(expression == NULL, "expression is not NULL\n");
81 ok(function == NULL, "function is not NULL\n");
82 ok(file == NULL, "file is not NULL\n");
83 ok(line == 0, "line = %u\n", line);
84 ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
87 static int __cdecl initterm_cb0(void)
93 static int __cdecl initterm_cb1(void)
99 static int __cdecl initterm_cb2(void)
106 static void test__initterm_e(void)
108 _INITTERM_E_FN table[4];
112 skip("_initterm_e not found\n");
116 memset(table, 0, sizeof(table));
118 memset(cb_called, 0, sizeof(cb_called));
120 res = p_initterm_e(table, table);
121 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
122 "got %d with 0x%x {%d, %d, %d}\n",
123 res, errno, cb_called[0], cb_called[1], cb_called[2]);
125 memset(cb_called, 0, sizeof(cb_called));
127 res = p_initterm_e(table, NULL);
128 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
129 "got %d with 0x%x {%d, %d, %d}\n",
130 res, errno, cb_called[0], cb_called[1], cb_called[2]);
133 /* this crash on Windows */
135 res = p_initterm_e(NULL, table);
136 trace("got %d with 0x%x\n", res, errno);
139 table[0] = initterm_cb0;
140 memset(cb_called, 0, sizeof(cb_called));
142 res = p_initterm_e(table, &table[1]);
143 ok( !res && (cb_called[0] == 1) && !cb_called[1] && !cb_called[2],
144 "got %d with 0x%x {%d, %d, %d}\n",
145 res, errno, cb_called[0], cb_called[1], cb_called[2]);
148 /* init-function returning failure */
149 table[1] = initterm_cb1;
150 memset(cb_called, 0, sizeof(cb_called));
152 res = p_initterm_e(table, &table[3]);
153 ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
154 "got %d with 0x%x {%d, %d, %d}\n",
155 res, errno, cb_called[0], cb_called[1], cb_called[2]);
157 /* init-function not called, when end < start */
158 memset(cb_called, 0, sizeof(cb_called));
160 res = p_initterm_e(&table[3], table);
161 ok( !res && !cb_called[0] && !cb_called[1] && !cb_called[2],
162 "got %d with 0x%x {%d, %d, %d}\n",
163 res, errno, cb_called[0], cb_called[1], cb_called[2]);
165 /* initialization stop after first non-zero result */
166 table[2] = initterm_cb0;
167 memset(cb_called, 0, sizeof(cb_called));
169 res = p_initterm_e(table, &table[3]);
170 ok( (res == 1) && (cb_called[0] == 1) && (cb_called[1] == 1) && !cb_called[2],
171 "got %d with 0x%x {%d, %d, %d}\n",
172 res, errno, cb_called[0], cb_called[1], cb_called[2]);
174 /* NULL pointer in the array are skipped */
176 table[2] = initterm_cb2;
177 memset(cb_called, 0, sizeof(cb_called));
179 res = p_initterm_e(table, &table[3]);
180 ok( (res == 2) && (cb_called[0] == 1) && !cb_called[1] && (cb_called[2] == 1),
181 "got %d with 0x%x {%d, %d, %d}\n",
182 res, errno, cb_called[0], cb_called[1], cb_called[2]);
186 /* Beware that _encode_pointer is a NOP before XP
187 (the parameter is returned unchanged) */
188 static void test__encode_pointer(void)
192 if(!p_encode_pointer || !p_decode_pointer || !p_encoded_null) {
193 win_skip("_encode_pointer, _decode_pointer or _encoded_null not found\n");
197 ptr = (void*)0xdeadbeef;
198 res = p_encode_pointer(ptr);
199 res = p_decode_pointer(res);
200 ok(res == ptr, "Pointers are different after encoding and decoding\n");
202 ok(p_encoded_null() == p_encode_pointer(NULL), "Error encoding null\n");
204 ptr = p_encode_pointer(p_encode_pointer);
205 ok(p_decode_pointer(ptr) == p_encode_pointer, "Error decoding pointer\n");
207 /* Not present before XP */
208 if (!pEncodePointer) {
209 win_skip("EncodePointer not found\n");
213 res = pEncodePointer(p_encode_pointer);
214 ok(ptr == res, "_encode_pointer produced different result than EncodePointer\n");
218 static void test_error_messages(void)
220 int *size, size_copy;
222 if(!p_sys_nerr || !p__sys_nerr || !p_sys_errlist || !p__sys_errlist) {
223 win_skip("Skipping test_error_messages tests\n");
227 size = p__sys_nerr();
229 ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
232 ok(*p_sys_nerr == *size, "_sys_nerr = %u, size = %u\n", *p_sys_nerr, *size);
236 ok(*p_sys_errlist == *(p__sys_errlist()), "p_sys_errlist != p__sys_errlist()\n");
239 static void test__strtoi64(void)
242 unsigned __int64 ures;
244 if(!p_strtoi64 || !p_strtoui64) {
245 win_skip("_strtoi64 or _strtoui64 not found\n");
249 if(!p_set_invalid_parameter_handler) {
250 win_skip("_set_invalid_parameter_handler not found\n");
255 SET_EXPECT(invalid_parameter_handler);
256 res = p_strtoi64(NULL, NULL, 10);
257 ok(res == 0, "res != 0\n");
258 CHECK_CALLED(invalid_parameter_handler);
260 SET_EXPECT(invalid_parameter_handler);
261 res = p_strtoi64("123", NULL, 1);
262 ok(res == 0, "res != 0\n");
263 CHECK_CALLED(invalid_parameter_handler);
265 SET_EXPECT(invalid_parameter_handler);
266 res = p_strtoi64("123", NULL, 37);
267 ok(res == 0, "res != 0\n");
268 CHECK_CALLED(invalid_parameter_handler);
270 SET_EXPECT(invalid_parameter_handler);
271 ures = p_strtoui64(NULL, NULL, 10);
272 ok(ures == 0, "res = %d\n", (int)ures);
273 CHECK_CALLED(invalid_parameter_handler);
275 SET_EXPECT(invalid_parameter_handler);
276 ures = p_strtoui64("123", NULL, 1);
277 ok(ures == 0, "res = %d\n", (int)ures);
278 CHECK_CALLED(invalid_parameter_handler);
280 SET_EXPECT(invalid_parameter_handler);
281 ures = p_strtoui64("123", NULL, 37);
282 ok(ures == 0, "res = %d\n", (int)ures);
283 CHECK_CALLED(invalid_parameter_handler);
284 ok(errno == 0xdeadbeef, "errno = %x\n", errno);
287 static void test__itoa_s(void)
294 win_skip("Skipping _itoa_s tests\n");
298 if(!p_set_invalid_parameter_handler) {
299 win_skip("_set_invalid_parameter_handler not found\n");
303 /* _itoa_s (on msvcr90) doesn't set errno (in case of errors) while msvcrt does
304 * as we always set errno in our msvcrt implementation, don't test here that errno
307 SET_EXPECT(invalid_parameter_handler);
308 ret = p_itoa_s(0, NULL, 0, 0);
309 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
310 CHECK_CALLED(invalid_parameter_handler);
312 memset(buffer, 'X', sizeof(buffer));
313 SET_EXPECT(invalid_parameter_handler);
314 ret = p_itoa_s(0, buffer, 0, 0);
315 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
316 ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
317 CHECK_CALLED(invalid_parameter_handler);
319 memset(buffer, 'X', sizeof(buffer));
320 SET_EXPECT(invalid_parameter_handler);
321 ret = p_itoa_s(0, buffer, sizeof(buffer), 0);
322 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
323 ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
324 CHECK_CALLED(invalid_parameter_handler);
326 memset(buffer, 'X', sizeof(buffer));
327 SET_EXPECT(invalid_parameter_handler);
328 ret = p_itoa_s(0, buffer, sizeof(buffer), 64);
329 ok(ret == EINVAL, "Expected _itoa_s to return EINVAL, got %d\n", ret);
330 ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
331 CHECK_CALLED(invalid_parameter_handler);
333 memset(buffer, 'X', sizeof(buffer));
334 SET_EXPECT(invalid_parameter_handler);
335 ret = p_itoa_s(12345678, buffer, 4, 10);
336 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
337 ok(!memcmp(buffer, "\000765", 4),
338 "Expected the output buffer to be null terminated with truncated output\n");
339 CHECK_CALLED(invalid_parameter_handler);
341 memset(buffer, 'X', sizeof(buffer));
342 SET_EXPECT(invalid_parameter_handler);
343 ret = p_itoa_s(12345678, buffer, 8, 10);
344 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
345 ok(!memcmp(buffer, "\0007654321", 8),
346 "Expected the output buffer to be null terminated with truncated output\n");
347 CHECK_CALLED(invalid_parameter_handler);
349 memset(buffer, 'X', sizeof(buffer));
350 SET_EXPECT(invalid_parameter_handler);
351 ret = p_itoa_s(-12345678, buffer, 9, 10);
352 ok(ret == ERANGE, "Expected _itoa_s to return ERANGE, got %d\n", ret);
353 ok(!memcmp(buffer, "\00087654321", 9),
354 "Expected the output buffer to be null terminated with truncated output\n");
355 CHECK_CALLED(invalid_parameter_handler);
357 ret = p_itoa_s(12345678, buffer, 9, 10);
358 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
359 ok(!strcmp(buffer, "12345678"),
360 "Expected output buffer string to be \"12345678\", got \"%s\"\n",
363 ret = p_itoa_s(43690, buffer, sizeof(buffer), 2);
364 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
365 ok(!strcmp(buffer, "1010101010101010"),
366 "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
369 ret = p_itoa_s(1092009, buffer, sizeof(buffer), 36);
370 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
371 ok(!strcmp(buffer, "nell"),
372 "Expected output buffer string to be \"nell\", got \"%s\"\n",
375 ret = p_itoa_s(5704, buffer, sizeof(buffer), 18);
376 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
377 ok(!strcmp(buffer, "hag"),
378 "Expected output buffer string to be \"hag\", got \"%s\"\n",
381 ret = p_itoa_s(-12345678, buffer, sizeof(buffer), 10);
382 ok(ret == 0, "Expected _itoa_s to return 0, got %d\n", ret);
383 ok(!strcmp(buffer, "-12345678"),
384 "Expected output buffer string to be \"-12345678\", got \"%s\"\n",
388 static void test_wcsncat_s(void)
390 static wchar_t abcW[] = {'a','b','c',0};
397 win_skip("skipping wcsncat_s tests\n");
401 if(!p_set_invalid_parameter_handler) {
402 win_skip("_set_invalid_parameter_handler not found\n");
406 memcpy(src, abcW, sizeof(abcW));
408 SET_EXPECT(invalid_parameter_handler);
409 ret = p_wcsncat_s(NULL, 4, src, 4);
410 ok(ret == EINVAL, "err = %d\n", ret);
411 CHECK_CALLED(invalid_parameter_handler);
413 SET_EXPECT(invalid_parameter_handler);
414 ret = p_wcsncat_s(dst, 0, src, 4);
415 ok(ret == EINVAL, "err = %d\n", ret);
416 CHECK_CALLED(invalid_parameter_handler);
418 SET_EXPECT(invalid_parameter_handler);
419 ret = p_wcsncat_s(dst, 0, src, _TRUNCATE);
420 ok(ret == EINVAL, "err = %d\n", ret);
421 CHECK_CALLED(invalid_parameter_handler);
423 ret = p_wcsncat_s(dst, 4, NULL, 0);
424 ok(ret == 0, "err = %d\n", ret);
427 SET_EXPECT(invalid_parameter_handler);
428 ret = p_wcsncat_s(dst, 2, src, 4);
429 ok(ret == ERANGE, "err = %d\n", ret);
430 CHECK_CALLED(invalid_parameter_handler);
433 ret = p_wcsncat_s(dst, 2, src, _TRUNCATE);
434 ok(ret == STRUNCATE, "err = %d\n", ret);
435 ok(dst[0] == 'a' && dst[1] == 0, "dst is %s\n", wine_dbgstr_w(dst));
437 memcpy(dst, abcW, sizeof(abcW));
439 SET_EXPECT(invalid_parameter_handler);
440 ret = p_wcsncat_s(dst, 4, src, 4);
441 ok(ret == EINVAL, "err = %d\n", ret);
442 CHECK_CALLED(invalid_parameter_handler);
452 SetLastError(0xdeadbeef);
453 hcrt = LoadLibraryA("msvcr90.dll");
455 win_skip("msvcr90.dll not installed (got %d)\n", GetLastError());
459 p_set_invalid_parameter_handler = (void *) GetProcAddress(hcrt, "_set_invalid_parameter_handler");
460 if(p_set_invalid_parameter_handler)
461 ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
462 "Invalid parameter handler was already set\n");
464 p_initterm_e = (void *) GetProcAddress(hcrt, "_initterm_e");
465 p_encode_pointer = (void *) GetProcAddress(hcrt, "_encode_pointer");
466 p_decode_pointer = (void *) GetProcAddress(hcrt, "_decode_pointer");
467 p_encoded_null = (void *) GetProcAddress(hcrt, "_encoded_null");
468 p_sys_nerr = (void *) GetProcAddress(hcrt, "_sys_nerr");
469 p__sys_nerr = (void *) GetProcAddress(hcrt, "__sys_nerr");
470 p_sys_errlist = (void *) GetProcAddress(hcrt, "_sys_errlist");
471 p__sys_errlist = (void *) GetProcAddress(hcrt, "__sys_errlist");
472 p_strtoi64 = (void *) GetProcAddress(hcrt, "_strtoi64");
473 p_strtoui64 = (void *) GetProcAddress(hcrt, "_strtoui64");
474 p_itoa_s = (void *)GetProcAddress(hcrt, "_itoa_s");
475 p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
477 hkernel32 = GetModuleHandleA("kernel32.dll");
478 pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
481 test__encode_pointer();
482 test_error_messages();