2
* Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program 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
12
* GNU General Public License for more details.
16
#include "ntoskernel.h"
17
#include "crt_exports.h"
20
/* Windows long is 32-bit, so strip single 'l' in integer formats */
21
static void strip_l_modifier(char *str)
30
/* Replace single 'l' inside integer formats with '\0' */
31
for (ptr = str; *ptr; ptr++) {
73
in_format = 1; /* ignore previous junk */
87
/* Purge zeroes from the resulting string */
90
for (ptr = str; ptr < end_ptr; ptr++)
97
* va_list on x86_64 Linux is designed to allow passing arguments in registers
98
* even to variadic functions. va_list is a structure holding pointers to the
99
* register save area, which holds the arguments passed in registers, and to
100
* the stack, which may have the arguments that did not fit the registers.
101
* va_list also holds offsets in the register save area for the next general
102
* purpose and floating point registers that the next va_arg() would fetch.
104
* Unlike Linux, the Windows va_list is just a pointer to the stack. No
105
* arguments are passed in the registers. That's why we construct the Linux
106
* va_list so that the register save area is never used. For that goal, we set
107
* the offsets to the maximal allowed values, meaning that the arguments passed
108
* in the registers have been exhausted. The values are 48 for general purpose
109
* registers (6 registers, 8 bytes each) and 304 for floating point registers
110
* (16 registers, 16 bytes each, on top of general purpose register).
113
struct x86_64_va_list {
116
void *overflow_arg_area;
120
#define VA_LIST_DECL(_args) \
121
va_list _args##new; \
122
struct x86_64_va_list *_args##x;
123
#define VA_LIST_PREP(_args) \
125
_args##x = (struct x86_64_va_list *)&_args##new; \
126
_args##x->gp_offset = 6 * 8; /* GP registers exhausted */ \
127
_args##x->fp_offset = 6 * 8 + 16 * 16; /* FP registers exhausted */ \
128
_args##x->overflow_arg_area = (void *)_args; \
129
_args##x->reg_save_area = NULL; \
131
#define VA_LIST_CONV(_args) (_args##new)
132
#define VA_LIST_FREE(_args)
133
#define FMT_DECL(_fmt) \
136
#define FMT_PREP(_fmt) \
138
_fmt##len = strlen(format) + 1; \
139
_fmt##copy = kmalloc(_fmt##len, GFP_KERNEL); \
141
memcpy(_fmt##copy, format, _fmt##len); \
142
strip_l_modifier(_fmt##copy); \
145
#define FMT_CONV(_fmt) (_fmt##copy ? _fmt##copy : format)
146
#define FMT_FREE(_fmt) kfree(_fmt##copy)
148
#else /* !CONFIG_X86_64 */
150
#define VA_LIST_DECL(_args)
151
#define VA_LIST_PREP(_args)
152
#define VA_LIST_CONV(_args) (_args)
153
#define VA_LIST_FREE(_args)
154
#define FMT_DECL(_fmt)
155
#define FMT_PREP(_fmt)
156
#define FMT_CONV(_fmt) (format)
157
#define FMT_FREE(_fmt)
159
#endif /* !CONFIG_X86_64 */
161
noregparm INT WIN_FUNC(_win_sprintf,12)
162
(char *buf, const char *format, ...)
169
va_start(args, format);
170
res = vsprintf(buf, FMT_CONV(format), args);
174
TRACE2("buf: %p: %s", buf, buf);
178
noregparm INT WIN_FUNC(swprintf,12)
179
(wchar_t *buf, const wchar_t *format, ...)
185
noregparm INT WIN_FUNC(_win_vsprintf,3)
186
(char *str, const char *format, va_list ap)
195
i = vsprintf(str, FMT_CONV(format), VA_LIST_CONV(ap));
196
TRACE2("str: %p: %s", str, str);
203
noregparm INT WIN_FUNC(_win_snprintf,12)
204
(char *buf, SIZE_T count, const char *format, ...)
211
va_start(args, format);
212
res = vsnprintf(buf, count, FMT_CONV(format), args);
214
TRACE2("buf: %p: %s", buf, buf);
220
noregparm INT WIN_FUNC(_win__snprintf,12)
221
(char *buf, SIZE_T count, const char *format, ...)
228
va_start(args, format);
229
res = vsnprintf(buf, count, FMT_CONV(format), args);
231
TRACE2("buf: %p: %s", buf, buf);
237
noregparm INT WIN_FUNC(_win_vsnprintf,4)
238
(char *str, SIZE_T size, const char *format, va_list ap)
247
i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
248
TRACE2("str: %p: %s", str, str);
255
noregparm INT WIN_FUNC(_win__vsnprintf,4)
256
(char *str, SIZE_T size, const char *format, va_list ap)
265
i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap));
266
TRACE2("str: %p: %s", str, str);
273
noregparm char *WIN_FUNC(_win_strncpy,3)
274
(char *dst, char *src, SIZE_T n)
276
return strncpy(dst, src, n);
279
noregparm SIZE_T WIN_FUNC(_win_strlen,1)
285
noregparm INT WIN_FUNC(_win_strncmp,3)
286
(const char *s1, const char *s2, SIZE_T n)
288
return strncmp(s1, s2, n);
291
noregparm INT WIN_FUNC(_win_strcmp,2)
292
(const char *s1, const char *s2)
294
return strcmp(s1, s2);
297
noregparm INT WIN_FUNC(_win_stricmp,2)
298
(const char *s1, const char *s2)
300
return stricmp(s1, s2);
303
noregparm char *WIN_FUNC(_win_strncat,3)
304
(char *dest, const char *src, SIZE_T n)
306
return strncat(dest, src, n);
309
noregparm INT WIN_FUNC(_win_wcscmp,2)
310
(const wchar_t *s1, const wchar_t *s2)
312
while (*s1 && *s1 == *s2) {
319
noregparm INT WIN_FUNC(_win_wcsicmp,2)
320
(const wchar_t *s1, const wchar_t *s2)
322
while (*s1 && tolower((char)*s1) == tolower((char)*s2)) {
326
return tolower((char)*s1) - tolower((char)*s2);
329
noregparm SIZE_T WIN_FUNC(_win_wcslen,1)
332
const wchar_t *t = s;
338
noregparm wchar_t *WIN_FUNC(_win_wcsncpy,3)
339
(wchar_t *dest, const wchar_t *src, SIZE_T n)
345
while (src < s && (*d++ = *src++))
348
memset(d, 0, (s - src) * sizeof(wchar_t));
352
noregparm wchar_t *WIN_FUNC(_win_wcscpy,2)
353
(wchar_t *dest, const wchar_t *src)
356
while ((*d++ = *src++))
361
noregparm wchar_t *WIN_FUNC(_win_wcscat,2)
362
(wchar_t *dest, const wchar_t *src)
368
while ((*d++ = *src++))
373
noregparm INT WIN_FUNC(_win_towupper,1)
379
noregparm INT WIN_FUNC(_win_towlower,1)
385
noregparm INT WIN_FUNC(_win_tolower,1)
391
noregparm INT WIN_FUNC(_win_toupper,1)
397
noregparm void *WIN_FUNC(_win_strcpy,2)
398
(void *to, const void *from)
400
return strcpy(to, from);
403
noregparm char *WIN_FUNC(_win_strstr,2)
404
(const char *s1, const char *s2)
406
return strstr(s1, s2);
409
noregparm char *WIN_FUNC(_win_strchr,2)
410
(const char *s, int c)
415
noregparm char *WIN_FUNC(_win_strrchr,2)
416
(const char *s, int c)
418
return strrchr(s, c);
421
noregparm void *WIN_FUNC(_win_memmove,3)
422
(void *to, void *from, SIZE_T count)
424
return memmove(to, from, count);
427
noregparm void *WIN_FUNC(_win_memchr,3)
428
(const void *s, INT c, SIZE_T n)
430
return memchr(s, c, n);
433
noregparm void *WIN_FUNC(_win_memcpy,3)
434
(void *to, const void *from, SIZE_T n)
436
return memcpy(to, from, n);
439
noregparm void *WIN_FUNC(_win_memset,3)
440
(void *s, char c, SIZE_T count)
442
return memset(s, c, count);
445
noregparm int WIN_FUNC(_win_memcmp,3)
446
(void *s1, void *s2, SIZE_T n)
448
return memcmp(s1, s2, n);
451
noregparm void WIN_FUNC(_win_srand,1)
457
noregparm int WIN_FUNC(rand,0)
463
get_random_bytes(buf, sizeof(buf));
464
for (n = i = 0; i < sizeof(buf) ; i++)
469
noregparm int WIN_FUNC(_win_atoi,1)
472
int i = simple_strtol(ptr, NULL, 10);
476
noregparm int WIN_FUNC(_win_isprint,1)
482
wstdcall s64 WIN_FUNC(_alldiv,2)
488
wstdcall u64 WIN_FUNC(_aulldiv,2)
494
wstdcall s64 WIN_FUNC(_allmul,2)
500
wstdcall u64 WIN_FUNC(_aullmul,2)
506
wstdcall s64 WIN_FUNC(_allrem,2)
512
wstdcall u64 WIN_FUNC(_aullrem,2)
518
__attribute__((regparm(3))) s64 WIN_FUNC(_allshl,2)
524
__attribute__((regparm(3))) u64 WIN_FUNC(_aullshl,2)
530
__attribute__((regparm(3))) s64 WIN_FUNC(_allshr,2)
536
__attribute__((regparm(3))) u64 WIN_FUNC(_aullshr,2)
542
int stricmp(const char *s1, const char *s2)
544
while (*s1 && tolower(*s1) == tolower(*s2)) {
551
void dump_bytes(const char *ctx, const u8 *from, int len)
556
buf = kmalloc(len * 3 + 1, irql_gfp());
558
ERROR("couldn't allocate memory");
561
for (i = j = 0; i < len; i++, j += 3) {
562
sprintf(&buf[j], "%02x ", from[i]);
565
printk(KERN_DEBUG "%s: %p: %s\n", ctx, from, buf);
574
/* called when module is being removed */