win-pvdrivers

changeset 349:5c7eb92ed13c

add files to do basic snprintf-type stuff, taken from Linux. Centralize MinGW-specific hacks here. Yay GPL.
author Andy Grover <andy.grover@oracle.com>
date Tue Jul 01 15:24:36 2008 -0700 (2008-07-01)
parents 6c1d86fffcd2
children 6b41ede6aec5
files xenpci/mingw_extras.c xenpci/mingw_extras.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xenpci/mingw_extras.c	Tue Jul 01 15:24:36 2008 -0700
     1.3 @@ -0,0 +1,568 @@
     1.4 +/*
     1.5 + * Provide missing std functions needed by the driver but not provided by
     1.6 + * MinGW. Code mostly taken from Linux or as noted.
     1.7 + *
     1.8 + * Remaining code is
     1.9 + * Copyright Andy Grover <andy.grover@oracle.com> 
    1.10 + * and licensed under the GPLv2.
    1.11 + */
    1.12 +
    1.13 +#include "xenpci.h"
    1.14 +
    1.15 +NTSTATUS
    1.16 +RtlStringCbPrintfW(
    1.17 +  win_wchar_t *dest_str,
    1.18 +  size_t dest_size,
    1.19 +  win_wchar_t *format,
    1.20 +  ...)
    1.21 +{
    1.22 +  /* TODO: fixme */
    1.23 +  return STATUS_SUCCESS;
    1.24 +}
    1.25 +
    1.26 +/* ----- BEGIN Other people's code --------- */
    1.27 +
    1.28 +/* from arch/x86/boot/string.c, used under GPLv2 */
    1.29 +/* Copyright (C) 1991, 1992 Linus Torvalds
    1.30 + * Copyright 2007 rPath, Inc. - All Rights Reserved
    1.31 + */
    1.32 +size_t strnlen(const char *s, size_t maxlen)
    1.33 +{
    1.34 +  const char *es = s;
    1.35 +  while (*es && maxlen) {
    1.36 +    es++;
    1.37 +    maxlen--;
    1.38 +  }
    1.39 +
    1.40 +  return (es - s);
    1.41 +}
    1.42 +
    1.43 +/* from arch/x86/boot/boot.h, used under GPLv2 */
    1.44 +/* Copyright (C) 1991, 1992 Linus Torvalds
    1.45 + * Copyright 2007 rPath, Inc. - All Rights Reserved
    1.46 + */
    1.47 +static int isdigit(int ch)
    1.48 +{
    1.49 +        return (ch >= '0') && (ch <= '9');
    1.50 +}
    1.51 +
    1.52 +/* from K&Rv2 p. 43 */
    1.53 +int atoi(const char s[])
    1.54 +{
    1.55 +  int i, n;
    1.56 +
    1.57 +  n = 0;
    1.58 +  for(i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
    1.59 +    n = 10 * n + (s[i] - '0');
    1.60 +  return n;
    1.61 +}
    1.62 +
    1.63 +/* from linux/lib/vsprintf.c, used under GPLv2 */
    1.64 +/* Copyright (C) 1991, 1992  Linus Torvalds
    1.65 + * Wirzenius wrote this portably, Torvalds fucked it up :-)
    1.66 + */
    1.67 +static int skip_atoi(const char **s)
    1.68 +{
    1.69 +	int i=0;
    1.70 +
    1.71 +	while (isdigit(**s))
    1.72 +		i = i*10 + *((*s)++) - '0';
    1.73 +	return i;
    1.74 +}
    1.75 +
    1.76 +int snprintf(char * buf, size_t size, const char *fmt, ...)
    1.77 +{
    1.78 +  va_list args;
    1.79 +  int i;
    1.80 +
    1.81 +  va_start(args, fmt);
    1.82 +  i = vsnprintf(buf,size,fmt,args);
    1.83 +  va_end(args);
    1.84 +  return i;
    1.85 +}
    1.86 +
    1.87 +#define do_div(n,base) ({ \
    1.88 +int __res; \
    1.89 +__res = ((unsigned long) n) % (unsigned) base; \
    1.90 +n = ((unsigned long) n) / (unsigned) base; \
    1.91 +__res; })
    1.92 +
    1.93 +
    1.94 +/* Decimal conversion is by far the most typical, and is used
    1.95 + * for /proc and /sys data. This directly impacts e.g. top performance
    1.96 + * with many processes running. We optimize it for speed
    1.97 + * using code from
    1.98 + * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
    1.99 + * (with permission from the author, Douglas W. Jones). */
   1.100 +
   1.101 +/* Formats correctly any integer in [0,99999].
   1.102 + * Outputs from one to five digits depending on input.
   1.103 + * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
   1.104 +static char* put_dec_trunc(char *buf, unsigned q)
   1.105 +{
   1.106 +	unsigned d3, d2, d1, d0;
   1.107 +	d1 = (q>>4) & 0xf;
   1.108 +	d2 = (q>>8) & 0xf;
   1.109 +	d3 = (q>>12);
   1.110 +
   1.111 +	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
   1.112 +	q = (d0 * 0xcd) >> 11;
   1.113 +	d0 = d0 - 10*q;
   1.114 +	*buf++ = d0 + '0'; /* least significant digit */
   1.115 +	d1 = q + 9*d3 + 5*d2 + d1;
   1.116 +	if (d1 != 0) {
   1.117 +		q = (d1 * 0xcd) >> 11;
   1.118 +		d1 = d1 - 10*q;
   1.119 +		*buf++ = d1 + '0'; /* next digit */
   1.120 +
   1.121 +		d2 = q + 2*d2;
   1.122 +		if ((d2 != 0) || (d3 != 0)) {
   1.123 +			q = (d2 * 0xd) >> 7;
   1.124 +			d2 = d2 - 10*q;
   1.125 +			*buf++ = d2 + '0'; /* next digit */
   1.126 +
   1.127 +			d3 = q + 4*d3;
   1.128 +			if (d3 != 0) {
   1.129 +				q = (d3 * 0xcd) >> 11;
   1.130 +				d3 = d3 - 10*q;
   1.131 +				*buf++ = d3 + '0';  /* next digit */
   1.132 +				if (q != 0)
   1.133 +					*buf++ = q + '0';  /* most sign. digit */
   1.134 +			}
   1.135 +		}
   1.136 +	}
   1.137 +	return buf;
   1.138 +}
   1.139 +/* Same with if's removed. Always emits five digits */
   1.140 +static char* put_dec_full(char *buf, unsigned q)
   1.141 +{
   1.142 +	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
   1.143 +	/* but anyway, gcc produces better code with full-sized ints */
   1.144 +	unsigned d3, d2, d1, d0;
   1.145 +	d1 = (q>>4) & 0xf;
   1.146 +	d2 = (q>>8) & 0xf;
   1.147 +	d3 = (q>>12);
   1.148 +
   1.149 +	/* Possible ways to approx. divide by 10 */
   1.150 +	/* gcc -O2 replaces multiply with shifts and adds */
   1.151 +	// (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
   1.152 +	// (x * 0x67) >> 10:  1100111
   1.153 +	// (x * 0x34) >> 9:    110100 - same
   1.154 +	// (x * 0x1a) >> 8:     11010 - same
   1.155 +	// (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
   1.156 +
   1.157 +	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
   1.158 +	q = (d0 * 0xcd) >> 11;
   1.159 +	d0 = d0 - 10*q;
   1.160 +	*buf++ = d0 + '0';
   1.161 +	d1 = q + 9*d3 + 5*d2 + d1;
   1.162 +		q = (d1 * 0xcd) >> 11;
   1.163 +		d1 = d1 - 10*q;
   1.164 +		*buf++ = d1 + '0';
   1.165 +
   1.166 +		d2 = q + 2*d2;
   1.167 +			q = (d2 * 0xd) >> 7;
   1.168 +			d2 = d2 - 10*q;
   1.169 +			*buf++ = d2 + '0';
   1.170 +
   1.171 +			d3 = q + 4*d3;
   1.172 +				q = (d3 * 0xcd) >> 11; /* - shorter code */
   1.173 +				/* q = (d3 * 0x67) >> 10; - would also work */
   1.174 +				d3 = d3 - 10*q;
   1.175 +				*buf++ = d3 + '0';
   1.176 +					*buf++ = q + '0';
   1.177 +	return buf;
   1.178 +}
   1.179 +
   1.180 +static char* put_dec(char *buf, unsigned long long num)
   1.181 +{
   1.182 +	while (1) {
   1.183 +		unsigned rem;
   1.184 +		if (num < 100000)
   1.185 +			return put_dec_trunc(buf, num);
   1.186 +		rem = do_div(num, 100000);
   1.187 +		buf = put_dec_full(buf, rem);
   1.188 +	}
   1.189 +}
   1.190 +
   1.191 +
   1.192 +#define ZEROPAD	1		/* pad with zero */
   1.193 +#define SIGN	2		/* unsigned/signed long */
   1.194 +#define PLUS	4		/* show plus */
   1.195 +#define SPACE	8		/* space if plus */
   1.196 +#define LEFT	16		/* left justified */
   1.197 +#define SMALL	32		/* Must be 32 == 0x20 */
   1.198 +#define SPECIAL	64		/* 0x */
   1.199 +
   1.200 +static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
   1.201 +{
   1.202 +	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
   1.203 +	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
   1.204 +
   1.205 +	char tmp[66];
   1.206 +	char sign;
   1.207 +	char locase;
   1.208 +	int need_pfx = ((type & SPECIAL) && base != 10);
   1.209 +	int i;
   1.210 +
   1.211 +	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
   1.212 +	 * produces same digits or (maybe lowercased) letters */
   1.213 +	locase = (type & SMALL);
   1.214 +	if (type & LEFT)
   1.215 +		type &= ~ZEROPAD;
   1.216 +	sign = 0;
   1.217 +	if (type & SIGN) {
   1.218 +		if ((signed long long) num < 0) {
   1.219 +			sign = '-';
   1.220 +			num = - (signed long long) num;
   1.221 +			size--;
   1.222 +		} else if (type & PLUS) {
   1.223 +			sign = '+';
   1.224 +			size--;
   1.225 +		} else if (type & SPACE) {
   1.226 +			sign = ' ';
   1.227 +			size--;
   1.228 +		}
   1.229 +	}
   1.230 +	if (need_pfx) {
   1.231 +		size--;
   1.232 +		if (base == 16)
   1.233 +			size--;
   1.234 +	}
   1.235 +
   1.236 +	/* generate full string in tmp[], in reverse order */
   1.237 +	i = 0;
   1.238 +	if (num == 0)
   1.239 +		tmp[i++] = '0';
   1.240 +	/* Generic code, for any base:
   1.241 +	else do {
   1.242 +		tmp[i++] = (digits[do_div(num,base)] | locase);
   1.243 +	} while (num != 0);
   1.244 +	*/
   1.245 +	else if (base != 10) { /* 8 or 16 */
   1.246 +		int mask = base - 1;
   1.247 +		int shift = 3;
   1.248 +		if (base == 16) shift = 4;
   1.249 +		do {
   1.250 +			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
   1.251 +			num >>= shift;
   1.252 +		} while (num);
   1.253 +	} else { /* base 10 */
   1.254 +		i = put_dec(tmp, num) - tmp;
   1.255 +	}
   1.256 +
   1.257 +	/* printing 100 using %2d gives "100", not "00" */
   1.258 +	if (i > precision)
   1.259 +		precision = i;
   1.260 +	/* leading space padding */
   1.261 +	size -= precision;
   1.262 +	if (!(type & (ZEROPAD+LEFT))) {
   1.263 +		while(--size >= 0) {
   1.264 +			if (buf < end)
   1.265 +				*buf = ' ';
   1.266 +			++buf;
   1.267 +		}
   1.268 +	}
   1.269 +	/* sign */
   1.270 +	if (sign) {
   1.271 +		if (buf < end)
   1.272 +			*buf = sign;
   1.273 +		++buf;
   1.274 +	}
   1.275 +	/* "0x" / "0" prefix */
   1.276 +	if (need_pfx) {
   1.277 +		if (buf < end)
   1.278 +			*buf = '0';
   1.279 +		++buf;
   1.280 +		if (base == 16) {
   1.281 +			if (buf < end)
   1.282 +				*buf = ('X' | locase);
   1.283 +			++buf;
   1.284 +		}
   1.285 +	}
   1.286 +	/* zero or space padding */
   1.287 +	if (!(type & LEFT)) {
   1.288 +		char c = (type & ZEROPAD) ? '0' : ' ';
   1.289 +		while (--size >= 0) {
   1.290 +			if (buf < end)
   1.291 +				*buf = c;
   1.292 +			++buf;
   1.293 +		}
   1.294 +	}
   1.295 +	/* hmm even more zero padding? */
   1.296 +	while (i <= --precision) {
   1.297 +		if (buf < end)
   1.298 +			*buf = '0';
   1.299 +		++buf;
   1.300 +	}
   1.301 +	/* actual digits of result */
   1.302 +	while (--i >= 0) {
   1.303 +		if (buf < end)
   1.304 +			*buf = tmp[i];
   1.305 +		++buf;
   1.306 +	}
   1.307 +	/* trailing space padding */
   1.308 +	while (--size >= 0) {
   1.309 +		if (buf < end)
   1.310 +			*buf = ' ';
   1.311 +		++buf;
   1.312 +	}
   1.313 +	return buf;
   1.314 +}
   1.315 +
   1.316 +/**
   1.317 + * vsnprintf - Format a string and place it in a buffer
   1.318 + * @buf: The buffer to place the result into
   1.319 + * @size: The size of the buffer, including the trailing null space
   1.320 + * @fmt: The format string to use
   1.321 + * @args: Arguments for the format string
   1.322 + *
   1.323 + * The return value is the number of characters which would
   1.324 + * be generated for the given input, excluding the trailing
   1.325 + * '\0', as per ISO C99. If you want to have the exact
   1.326 + * number of characters written into @buf as return value
   1.327 + * (not including the trailing '\0'), use vscnprintf(). If the
   1.328 + * return is greater than or equal to @size, the resulting
   1.329 + * string is truncated.
   1.330 + *
   1.331 + * Call this function if you are already dealing with a va_list.
   1.332 + * You probably want snprintf() instead.
   1.333 + */
   1.334 +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
   1.335 +{
   1.336 +	int len;
   1.337 +	unsigned long long num;
   1.338 +	int i, base;
   1.339 +	char *str, *end, c;
   1.340 +	const char *s;
   1.341 +
   1.342 +	int flags;		/* flags to number() */
   1.343 +
   1.344 +	int field_width;	/* width of output field */
   1.345 +	int precision;		/* min. # of digits for integers; max
   1.346 +				   number of chars for from string */
   1.347 +	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
   1.348 +				/* 'z' support added 23/7/1999 S.H.    */
   1.349 +				/* 'z' changed to 'Z' --davidm 1/25/99 */
   1.350 +				/* 't' added for ptrdiff_t */
   1.351 +
   1.352 +	/* Reject out-of-range values early.  Large positive sizes are
   1.353 +	   used for unknown buffer sizes. */
   1.354 +	if ((int) size < 0)
   1.355 +		return 0;
   1.356 +
   1.357 +	str = buf;
   1.358 +	end = buf + size;
   1.359 +
   1.360 +	/* Make sure end is always >= buf */
   1.361 +	if (end < buf) {
   1.362 +		end = ((void *)-1);
   1.363 +		size = end - buf;
   1.364 +	}
   1.365 +
   1.366 +	for (; *fmt ; ++fmt) {
   1.367 +		if (*fmt != '%') {
   1.368 +			if (str < end)
   1.369 +				*str = *fmt;
   1.370 +			++str;
   1.371 +			continue;
   1.372 +		}
   1.373 +
   1.374 +		/* process flags */
   1.375 +		flags = 0;
   1.376 +		repeat:
   1.377 +			++fmt;		/* this also skips first '%' */
   1.378 +			switch (*fmt) {
   1.379 +				case '-': flags |= LEFT; goto repeat;
   1.380 +				case '+': flags |= PLUS; goto repeat;
   1.381 +				case ' ': flags |= SPACE; goto repeat;
   1.382 +				case '#': flags |= SPECIAL; goto repeat;
   1.383 +				case '0': flags |= ZEROPAD; goto repeat;
   1.384 +			}
   1.385 +
   1.386 +		/* get field width */
   1.387 +		field_width = -1;
   1.388 +		if (isdigit(*fmt))
   1.389 +			field_width = skip_atoi(&fmt);
   1.390 +		else if (*fmt == '*') {
   1.391 +			++fmt;
   1.392 +			/* it's the next argument */
   1.393 +			field_width = va_arg(args, int);
   1.394 +			if (field_width < 0) {
   1.395 +				field_width = -field_width;
   1.396 +				flags |= LEFT;
   1.397 +			}
   1.398 +		}
   1.399 +
   1.400 +		/* get the precision */
   1.401 +		precision = -1;
   1.402 +		if (*fmt == '.') {
   1.403 +			++fmt;	
   1.404 +			if (isdigit(*fmt))
   1.405 +				precision = skip_atoi(&fmt);
   1.406 +			else if (*fmt == '*') {
   1.407 +				++fmt;
   1.408 +				/* it's the next argument */
   1.409 +				precision = va_arg(args, int);
   1.410 +			}
   1.411 +			if (precision < 0)
   1.412 +				precision = 0;
   1.413 +		}
   1.414 +
   1.415 +		/* get the conversion qualifier */
   1.416 +		qualifier = -1;
   1.417 +		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
   1.418 +		    *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
   1.419 +			qualifier = *fmt;
   1.420 +			++fmt;
   1.421 +			if (qualifier == 'l' && *fmt == 'l') {
   1.422 +				qualifier = 'L';
   1.423 +				++fmt;
   1.424 +			}
   1.425 +		}
   1.426 +
   1.427 +		/* default base */
   1.428 +		base = 10;
   1.429 +
   1.430 +		switch (*fmt) {
   1.431 +			case 'c':
   1.432 +				if (!(flags & LEFT)) {
   1.433 +					while (--field_width > 0) {
   1.434 +						if (str < end)
   1.435 +							*str = ' ';
   1.436 +						++str;
   1.437 +					}
   1.438 +				}
   1.439 +				c = (unsigned char) va_arg(args, int);
   1.440 +				if (str < end)
   1.441 +					*str = c;
   1.442 +				++str;
   1.443 +				while (--field_width > 0) {
   1.444 +					if (str < end)
   1.445 +						*str = ' ';
   1.446 +					++str;
   1.447 +				}
   1.448 +				continue;
   1.449 +
   1.450 +			case 's':
   1.451 +				s = va_arg(args, char *);
   1.452 +				if ((unsigned long)s < PAGE_SIZE)
   1.453 +					s = "<NULL>";
   1.454 +
   1.455 +				len = strnlen(s, precision);
   1.456 +
   1.457 +				if (!(flags & LEFT)) {
   1.458 +					while (len < field_width--) {
   1.459 +						if (str < end)
   1.460 +							*str = ' ';
   1.461 +						++str;
   1.462 +					}
   1.463 +				}
   1.464 +				for (i = 0; i < len; ++i) {
   1.465 +					if (str < end)
   1.466 +						*str = *s;
   1.467 +					++str; ++s;
   1.468 +				}
   1.469 +				while (len < field_width--) {
   1.470 +					if (str < end)
   1.471 +						*str = ' ';
   1.472 +					++str;
   1.473 +				}
   1.474 +				continue;
   1.475 +
   1.476 +			case 'p':
   1.477 +				flags |= SMALL;
   1.478 +				if (field_width == -1) {
   1.479 +					field_width = 2*sizeof(void *);
   1.480 +					flags |= ZEROPAD;
   1.481 +				}
   1.482 +				str = number(str, end,
   1.483 +						(unsigned long) va_arg(args, void *),
   1.484 +						16, field_width, precision, flags);
   1.485 +				continue;
   1.486 +
   1.487 +
   1.488 +			case 'n':
   1.489 +				/* FIXME:
   1.490 +				* What does C99 say about the overflow case here? */
   1.491 +				if (qualifier == 'l') {
   1.492 +					long * ip = va_arg(args, long *);
   1.493 +					*ip = (str - buf);
   1.494 +				} else if (qualifier == 'Z' || qualifier == 'z') {
   1.495 +					size_t * ip = va_arg(args, size_t *);
   1.496 +					*ip = (str - buf);
   1.497 +				} else {
   1.498 +					int * ip = va_arg(args, int *);
   1.499 +					*ip = (str - buf);
   1.500 +				}
   1.501 +				continue;
   1.502 +
   1.503 +			case '%':
   1.504 +				if (str < end)
   1.505 +					*str = '%';
   1.506 +				++str;
   1.507 +				continue;
   1.508 +
   1.509 +				/* integer number formats - set up the flags and "break" */
   1.510 +			case 'o':
   1.511 +				base = 8;
   1.512 +				break;
   1.513 +
   1.514 +			case 'x':
   1.515 +				flags |= SMALL;
   1.516 +			case 'X':
   1.517 +				base = 16;
   1.518 +				break;
   1.519 +
   1.520 +			case 'd':
   1.521 +			case 'i':
   1.522 +				flags |= SIGN;
   1.523 +			case 'u':
   1.524 +				break;
   1.525 +
   1.526 +			default:
   1.527 +				if (str < end)
   1.528 +					*str = '%';
   1.529 +				++str;
   1.530 +				if (*fmt) {
   1.531 +					if (str < end)
   1.532 +						*str = *fmt;
   1.533 +					++str;
   1.534 +				} else {
   1.535 +					--fmt;
   1.536 +				}
   1.537 +				continue;
   1.538 +		}
   1.539 +		if (qualifier == 'L')
   1.540 +			num = va_arg(args, long long);
   1.541 +		else if (qualifier == 'l') {
   1.542 +			num = va_arg(args, unsigned long);
   1.543 +			if (flags & SIGN)
   1.544 +				num = (signed long) num;
   1.545 +		} else if (qualifier == 'Z' || qualifier == 'z') {
   1.546 +			num = va_arg(args, size_t);
   1.547 +		} else if (qualifier == 't') {
   1.548 +			num = va_arg(args, ptrdiff_t);
   1.549 +		} else if (qualifier == 'h') {
   1.550 +			num = (unsigned short) va_arg(args, int);
   1.551 +			if (flags & SIGN)
   1.552 +				num = (signed short) num;
   1.553 +		} else {
   1.554 +			num = va_arg(args, unsigned int);
   1.555 +			if (flags & SIGN)
   1.556 +				num = (signed int) num;
   1.557 +		}
   1.558 +		str = number(str, end, num, base,
   1.559 +				field_width, precision, flags);
   1.560 +	}
   1.561 +	if (size > 0) {
   1.562 +		if (str < end)
   1.563 +			*str = '\0';
   1.564 +		else
   1.565 +			end[-1] = '\0';
   1.566 +	}
   1.567 +	/* the trailing null byte doesn't count towards the total */
   1.568 +	return str-buf;
   1.569 +}
   1.570 +/* ----- END Other people's code --------- */
   1.571 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xenpci/mingw_extras.h	Tue Jul 01 15:24:36 2008 -0700
     2.3 @@ -0,0 +1,38 @@
     2.4 +#include <stdio.h>
     2.5 +#include <stdlib.h>
     2.6 +
     2.7 +#define KeMemoryBarrier() asm("mfence;")
     2.8 +/* mingw-runtime 3.13 is buggy #1 */
     2.9 +#undef KeGetCurrentProcessorNumber
    2.10 +#define KeGetCurrentProcessorNumber() \
    2.11 +  ((ULONG)KeGetCurrentKPCR()->Number)
    2.12 +
    2.13 +/* mingw-runtime 3.13 is buggy #2 */
    2.14 +#undef KeRaiseIrql
    2.15 +#undef KeLowerIrql
    2.16 +
    2.17 +NTOSAPI
    2.18 +VOID
    2.19 +DDKAPI
    2.20 +KeRaiseIrql(IN KIRQL new_irql, OUT PKIRQL old_irql);
    2.21 +
    2.22 +NTOSAPI
    2.23 +VOID
    2.24 +DDKAPI
    2.25 +KeLowerIrql(IN KIRQL irql);
    2.26 +
    2.27 +extern NTOSAPI CCHAR KeNumberProcessors;
    2.28 +
    2.29 +#define RtlStringCbCopyA(dst, dst_len, src) strncpy(dst, src, dst_len)
    2.30 +#define RtlStringCbPrintfA(args...) snprintf(args)
    2.31 +#define RtlStringCbVPrintfA(args...) vsnprintf(args)
    2.32 +
    2.33 +/* windows wchar 2 bytes, Linux's is 4! */
    2.34 +typedef unsigned short win_wchar_t;
    2.35 +
    2.36 +NTSTATUS
    2.37 +RtlStringCbPrintfW(
    2.38 +  win_wchar_t *dest_str,
    2.39 +  size_t dest_size,
    2.40 +  win_wchar_t *format,
    2.41 +  ...);