source: trunk/src/user32/wsprintf.cpp@ 10348

Last change on this file since 10348 was 10348, checked in by sandervl, 22 years ago

KOM: wvsnprintfA/W: fixed ascii and unicode conversion

File size: 20.4 KB
Line 
1/*
2 * wsprintf functions
3 *
4 * Copyright 1996 Alexandre Julliard
5 */
6
7#ifdef __WIN32OS2__
8#include <odin.h>
9#include <odinwrap.h>
10#include <os2sel.h>
11#include <os2win.h>
12
13#include <misc.h>
14
15#include <winnls.h>
16
17#define DBG_LOCALLOG DBG_wsprintf
18#include "dbglocal.h"
19
20ODINDEBUGCHANNEL(USER32-WSPRINTF)
21#endif
22
23#include <stdarg.h>
24#include <string.h>
25#include <stdio.h>
26#include "wine/winbase16.h"
27#include "windef.h"
28#include "wingdi.h"
29#include "winuser.h"
30#include "stackframe.h"
31#include "debugtools.h"
32
33DEFAULT_DEBUG_CHANNEL(string);
34
35
36#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
37#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
38#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
39#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
40#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
41#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
42#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
43
44typedef enum
45{
46 WPR_UNKNOWN,
47 WPR_CHAR,
48 WPR_WCHAR,
49 WPR_STRING,
50 WPR_WSTRING,
51 WPR_SIGNED,
52 WPR_UNSIGNED,
53 WPR_HEXA
54} WPRINTF_TYPE;
55
56typedef struct
57{
58 UINT flags;
59 UINT width;
60 UINT precision;
61 WPRINTF_TYPE type;
62} WPRINTF_FORMAT;
63
64typedef union {
65 WCHAR wchar_view;
66 CHAR char_view;
67 LPCSTR lpcstr_view;
68 LPCWSTR lpcwstr_view;
69 INT int_view;
70} WPRINTF_DATA;
71
72static const CHAR null_stringA[] = "(null)";
73static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
74
75/***********************************************************************
76 * WPRINTF_ParseFormatA
77 *
78 * Parse a format specification. A format specification has the form:
79 *
80 * [-][#][0][width][.precision]type
81 *
82 * Return value is the length of the format specification in characters.
83 */
84static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
85{
86 LPCSTR p = format;
87
88 res->flags = 0;
89 res->width = 0;
90 res->precision = 0;
91 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
92 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
93 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
94 while ((*p >= '0') && (*p <= '9')) /* width field */
95 {
96 res->width = res->width * 10 + *p - '0';
97 p++;
98 }
99 if (*p == '.') /* precision field */
100 {
101 p++;
102 while ((*p >= '0') && (*p <= '9'))
103 {
104 res->precision = res->precision * 10 + *p - '0';
105 p++;
106 }
107 }
108 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
109 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
110 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
111 switch(*p)
112 {
113 case 'c':
114 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
115 break;
116 case 'C':
117 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
118 break;
119 case 'd':
120 case 'i':
121 res->type = WPR_SIGNED;
122 break;
123 case 's':
124 res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
125 break;
126 case 'S':
127 res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
128 break;
129 case 'u':
130 res->type = WPR_UNSIGNED;
131 break;
132 case 'X':
133 res->flags |= WPRINTF_UPPER_HEX;
134 /* fall through */
135 case 'x':
136 res->type = WPR_HEXA;
137 break;
138 default: /* unknown format char */
139 res->type = WPR_UNKNOWN;
140 p--; /* print format as normal char */
141 break;
142 }
143 return (INT)(p - format) + 1;
144}
145
146
147/***********************************************************************
148 * WPRINTF_ParseFormatW
149 *
150 * Parse a format specification. A format specification has the form:
151 *
152 * [-][#][0][width][.precision]type
153 *
154 * Return value is the length of the format specification in characters.
155 */
156static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
157{
158 LPCWSTR p = format;
159
160 res->flags = 0;
161 res->width = 0;
162 res->precision = 0;
163 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
164 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
165 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
166 while ((*p >= '0') && (*p <= '9')) /* width field */
167 {
168 res->width = res->width * 10 + *p - '0';
169 p++;
170 }
171 if (*p == '.') /* precision field */
172 {
173 p++;
174 while ((*p >= '0') && (*p <= '9'))
175 {
176 res->precision = res->precision * 10 + *p - '0';
177 p++;
178 }
179 }
180 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
181 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
182 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
183 switch((CHAR)*p)
184 {
185 case 'c':
186 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
187 break;
188 case 'C':
189 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
190 break;
191 case 'd':
192 case 'i':
193 res->type = WPR_SIGNED;
194 break;
195 case 's':
196 res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
197 break;
198 case 'S':
199 res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
200 break;
201 case 'u':
202 res->type = WPR_UNSIGNED;
203 break;
204 case 'X':
205 res->flags |= WPRINTF_UPPER_HEX;
206 /* fall through */
207 case 'x':
208 res->type = WPR_HEXA;
209 break;
210 default:
211 res->type = WPR_UNKNOWN;
212 p--; /* print format as normal char */
213 break;
214 }
215 return (INT)(p - format) + 1;
216}
217
218
219/***********************************************************************
220 * WPRINTF_GetLen
221 */
222static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
223 LPSTR number, UINT maxlen )
224{
225 UINT len;
226
227 if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
228 if (format->width > maxlen) format->width = maxlen;
229 switch(format->type)
230 {
231 case WPR_CHAR:
232 case WPR_WCHAR:
233 return (format->precision = 1);
234 case WPR_STRING:
235 if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
236 for (len = 0; !format->precision || (len < format->precision); len++)
237 if (!*(arg->lpcstr_view + len)) break;
238 if (len > maxlen) len = maxlen;
239 return (format->precision = len);
240 case WPR_WSTRING:
241 if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
242 for (len = 0; !format->precision || (len < format->precision); len++)
243 if (!*(arg->lpcwstr_view + len)) break;
244 if (len > maxlen) len = maxlen;
245 return (format->precision = len);
246 case WPR_SIGNED:
247 len = sprintf( number, "%d", arg->int_view );
248 break;
249 case WPR_UNSIGNED:
250 len = sprintf( number, "%u", (UINT)arg->int_view );
251 break;
252 case WPR_HEXA:
253 len = sprintf( number,
254 (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
255 (UINT)arg->int_view);
256 break;
257 default:
258 return 0;
259 }
260 if (len > maxlen) len = maxlen;
261 if (format->precision < len) format->precision = len;
262 if (format->precision > maxlen) format->precision = maxlen;
263 if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
264 format->precision = format->width;
265 if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
266 return len;
267}
268
269
270#ifndef __WIN32OS2__
271/***********************************************************************
272 * wvsnprintf16 (Not a Windows API)
273 */
274static INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec,
275 LPCVOID args )
276{
277 WPRINTF_FORMAT format;
278 LPSTR p = buffer;
279 UINT i, len;
280 CHAR number[20];
281 WPRINTF_DATA cur_arg;
282 SEGPTR seg_str;
283
284 while (*spec && (maxlen > 1))
285 {
286 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
287 spec++;
288 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
289 spec += WPRINTF_ParseFormatA( spec, &format );
290 switch(format.type)
291 {
292 case WPR_WCHAR: /* No Unicode in Win16 */
293 case WPR_CHAR:
294 cur_arg.char_view = VA_ARG16( args, CHAR );
295 break;
296 case WPR_WSTRING: /* No Unicode in Win16 */
297 case WPR_STRING:
298 seg_str = VA_ARG16( args, SEGPTR );
299 if (IsBadReadPtr16(seg_str, 1 )) cur_arg.lpcstr_view = "";
300 else cur_arg.lpcstr_view = MapSL( seg_str );
301 break;
302 case WPR_SIGNED:
303 if (!(format.flags & WPRINTF_LONG))
304 {
305 cur_arg.int_view = VA_ARG16( args, INT16 );
306 break;
307 }
308 /* fall through */
309 case WPR_HEXA:
310 case WPR_UNSIGNED:
311 if (format.flags & WPRINTF_LONG)
312 cur_arg.int_view = VA_ARG16( args, UINT );
313 else
314 cur_arg.int_view = VA_ARG16( args, UINT16 );
315 break;
316 case WPR_UNKNOWN:
317 continue;
318 }
319 len = WPRINTF_GetLen( &format, &cur_arg, number, maxlen - 1 );
320 if (!(format.flags & WPRINTF_LEFTALIGN))
321 for (i = format.precision; i < format.width; i++, maxlen--)
322 *p++ = ' ';
323 switch(format.type)
324 {
325 case WPR_WCHAR: /* No Unicode in Win16 */
326 case WPR_CHAR:
327 *p= cur_arg.char_view;
328 if (*p != '\0') p++;
329 else if (format.width > 1) *p++ = ' ';
330 else len = 0;
331 break;
332 case WPR_WSTRING: /* No Unicode in Win16 */
333 case WPR_STRING:
334 if (len) memcpy( p, cur_arg.lpcstr_view, len );
335 p += len;
336 break;
337 case WPR_HEXA:
338 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
339 {
340 *p++ = '0';
341 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
342 maxlen -= 2;
343 len -= 2;
344 }
345 /* fall through */
346 case WPR_SIGNED:
347 case WPR_UNSIGNED:
348 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
349 if (len) memcpy( p, number, len );
350 p += len;
351 break;
352 case WPR_UNKNOWN:
353 continue;
354 }
355 if (format.flags & WPRINTF_LEFTALIGN)
356 for (i = format.precision; i < format.width; i++, maxlen--)
357 *p++ = ' ';
358 maxlen -= len;
359 }
360 *p = 0;
361 return (maxlen > 1) ? (INT)(p - buffer) : -1;
362}
363#endif //!__WIN32OS2__
364
365
366/***********************************************************************
367 * wvsnprintfA (USER32.@) (Not a Windows API, but we export it from USER32 anyway)
368 */
369INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args )
370{
371 WPRINTF_FORMAT format;
372 LPSTR p = buffer;
373 UINT i, len;
374 CHAR number[20];
375 WPRINTF_DATA argData;
376
377#ifdef __WIN32OS2__
378 TRACE("wvsnprintfA : %p %u %s\n", buffer, maxlen, debugstr_a(spec));
379#else
380 TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
381#endif
382
383 while (*spec && (maxlen > 1))
384 {
385 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
386 spec++;
387 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
388 spec += WPRINTF_ParseFormatA( spec, &format );
389
390 switch(format.type)
391 {
392 case WPR_WCHAR:
393 argData.wchar_view = (WCHAR)va_arg( args, int );
394 break;
395 case WPR_CHAR:
396 argData.char_view = (CHAR)va_arg( args, int );
397 break;
398 case WPR_STRING:
399 argData.lpcstr_view = va_arg( args, LPCSTR );
400 break;
401 case WPR_WSTRING:
402 argData.lpcwstr_view = va_arg( args, LPCWSTR );
403 break;
404 case WPR_HEXA:
405 case WPR_SIGNED:
406 case WPR_UNSIGNED:
407 argData.int_view = va_arg( args, INT );
408 break;
409 default:
410 argData.wchar_view = 0;
411 break;
412 }
413
414 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
415 if (!(format.flags & WPRINTF_LEFTALIGN))
416 for (i = format.precision; i < format.width; i++, maxlen--)
417 *p++ = ' ';
418 switch(format.type)
419 {
420 case WPR_WCHAR:
421#ifdef __WIN32OS2__
422 i = WideCharToMultiByte( CP_ACP, 0, &argData.wchar_view, 1, p, maxlen, 0, NULL );
423 if( i )
424 {
425 p += i - 1;
426 len = i;
427 }
428#else
429 *p = argData.wchar_view;
430#endif
431 if (*p != '\0') p++;
432 else if (format.width > 1) *p++ = ' ';
433 else len = 0;
434 break;
435 case WPR_CHAR:
436 *p = argData.char_view;
437 if (*p != '\0') p++;
438 else if (format.width > 1) *p++ = ' ';
439 else len = 0;
440 break;
441 case WPR_STRING:
442 memcpy( p, argData.lpcstr_view, len );
443 p += len;
444 break;
445 case WPR_WSTRING:
446 {
447 LPCWSTR ptr = argData.lpcwstr_view;
448#ifdef __WIN32OS2__
449 i = WideCharToMultiByte( CP_ACP, 0, ptr, len, p, maxlen, 0, 0 );
450 if( i )
451 {
452 p += i;
453 len = i;
454 }
455#else
456 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
457#endif
458 }
459 break;
460 case WPR_HEXA:
461 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
462 {
463 *p++ = '0';
464 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
465 maxlen -= 2;
466 len -= 2;
467 }
468 /* fall through */
469 case WPR_SIGNED:
470 case WPR_UNSIGNED:
471 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
472 memcpy( p, number, len );
473 p += len;
474 break;
475 case WPR_UNKNOWN:
476 continue;
477 }
478 if (format.flags & WPRINTF_LEFTALIGN)
479 for (i = format.precision; i < format.width; i++, maxlen--)
480 *p++ = ' ';
481 maxlen -= len;
482 }
483 *p = 0;
484#ifdef __WIN32OS2__
485 TRACE("%s\n",buffer);
486#else
487 TRACE("%s\n",debugstr_a(buffer));
488#endif
489 return (maxlen > 1) ? (INT)(p - buffer) : -1;
490}
491
492
493/***********************************************************************
494 * wvsnprintfW (USER32.@) (Not a Windows API, but we export it from USER32 anyway)
495 */
496INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args )
497{
498 WPRINTF_FORMAT format;
499 LPWSTR p = buffer;
500 UINT i, len;
501 CHAR number[20];
502 WPRINTF_DATA argData;
503
504 TRACE("wvsnprintfW : %p %u %s\n", buffer, maxlen, debugstr_w(spec));
505
506 while (*spec && (maxlen > 1))
507 {
508 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
509 spec++;
510 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
511 spec += WPRINTF_ParseFormatW( spec, &format );
512
513 switch(format.type)
514 {
515 case WPR_WCHAR:
516 argData.wchar_view = (WCHAR)va_arg( args, int );
517 break;
518 case WPR_CHAR:
519 argData.char_view = (CHAR)va_arg( args, int );
520 break;
521 case WPR_STRING:
522 argData.lpcstr_view = va_arg( args, LPCSTR );
523 break;
524 case WPR_WSTRING:
525 argData.lpcwstr_view = va_arg( args, LPCWSTR );
526 break;
527 case WPR_HEXA:
528 case WPR_SIGNED:
529 case WPR_UNSIGNED:
530 argData.int_view = va_arg( args, INT );
531 break;
532 default:
533 argData.wchar_view = 0;
534 break;
535 }
536
537 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
538 if (!(format.flags & WPRINTF_LEFTALIGN))
539 for (i = format.precision; i < format.width; i++, maxlen--)
540 *p++ = ' ';
541 switch(format.type)
542 {
543 case WPR_WCHAR:
544 *p = argData.wchar_view;
545 if (*p != '\0') p++;
546 else if (format.width > 1) *p++ = ' ';
547 else len = 0;
548 break;
549 case WPR_CHAR:
550#ifdef __WIN32OS2__
551 MultiByteToWideChar( CP_ACP, 0, &argData.char_view, 1, p, maxlen );
552#else
553 *p = argData.char_view;
554#endif
555 if (*p != '\0') p++;
556 else if (format.width > 1) *p++ = ' ';
557 else len = 0;
558 break;
559 case WPR_STRING:
560 {
561 LPCSTR ptr = argData.lpcstr_view;
562#ifdef __WIN32OS2__
563 i = MultiByteToWideChar( CP_ACP, 0, ptr, len, p, maxlen );
564 if( i )
565 {
566 p += i;
567 len = i;
568 }
569#else
570 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
571#endif
572 }
573 break;
574 case WPR_WSTRING:
575 if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
576 p += len;
577 break;
578 case WPR_HEXA:
579 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
580 {
581 *p++ = '0';
582 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
583 maxlen -= 2;
584 len -= 2;
585 }
586 /* fall through */
587 case WPR_SIGNED:
588 case WPR_UNSIGNED:
589 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
590 for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
591 break;
592 case WPR_UNKNOWN:
593 continue;
594 }
595 if (format.flags & WPRINTF_LEFTALIGN)
596 for (i = format.precision; i < format.width; i++, maxlen--)
597 *p++ = ' ';
598 maxlen -= len;
599 }
600 *p = 0;
601 TRACE("%s\n",debugstr_w(buffer));
602 return (maxlen > 1) ? (INT)(p - buffer) : -1;
603}
604
605
606#ifndef __WIN32OS2__
607/***********************************************************************
608 * wvsprintf16 (USER.421)
609 */
610INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, LPCVOID args )
611{
612 INT16 res;
613
614 TRACE("for %p got:\n",buffer);
615 res = wvsnprintf16( buffer, 1024, spec, args );
616 return ( res == -1 ) ? 1024 : res;
617}
618#endif //!__WIN32OS2__
619
620
621/***********************************************************************
622 * wvsprintfA (USER32.@)
623 */
624INT WINAPI wvsprintfA( LPSTR buffer, LPCSTR spec, va_list args )
625{
626 INT res = wvsnprintfA( buffer, 1024, spec, args );
627 return ( res == -1 ) ? 1024 : res;
628}
629
630
631/***********************************************************************
632 * wvsprintfW (USER32.@)
633 */
634INT WINAPI wvsprintfW( LPWSTR buffer, LPCWSTR spec, va_list args )
635{
636 INT res = wvsnprintfW( buffer, 1024, spec, args );
637 return ( res == -1 ) ? 1024 : res;
638}
639
640#ifndef __WIN32OS2__
641/***********************************************************************
642 * wsprintf16 (USER.420)
643 */
644INT16 WINAPIV wsprintf16(void)
645{
646 VA_LIST16 valist;
647 INT16 res;
648 SEGPTR buffer, spec;
649
650 VA_START16( valist );
651 buffer = VA_ARG16( valist, SEGPTR );
652 spec = VA_ARG16( valist, SEGPTR );
653 res = wvsnprintf16( MapSL(buffer), 1024, MapSL(spec), valist );
654 VA_END16( valist );
655 return ( res == -1 ) ? 1024 : res;
656}
657#endif //!__WIN32OS2__
658
659
660/***********************************************************************
661 * wsprintfA (USER32.@)
662 */
663INT WINAPIV wsprintfA( LPSTR buffer, LPCSTR spec, ... )
664{
665 va_list valist;
666 INT res;
667
668 va_start( valist, spec );
669 res = wvsnprintfA( buffer, 1024, spec, valist );
670 va_end( valist );
671 return ( res == -1 ) ? 1024 : res;
672}
673
674
675/***********************************************************************
676 * wsprintfW (USER32.@)
677 */
678INT WINAPIV wsprintfW( LPWSTR buffer, LPCWSTR spec, ... )
679{
680 va_list valist;
681 INT res;
682
683 va_start( valist, spec );
684 res = wvsnprintfW( buffer, 1024, spec, valist );
685 va_end( valist );
686 return ( res == -1 ) ? 1024 : res;
687}
688
689/***********************************************************************
690 * wsnprintfA (Not a Windows API)
691 */
692INT WINAPIV wsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, ... )
693{
694 va_list valist;
695 INT res;
696
697 va_start( valist, spec );
698 res = wvsnprintfA( buffer, maxlen, spec, valist );
699 va_end( valist );
700 return res;
701}
702
703/***********************************************************************
704 * wsnprintfW (Not a Windows API)
705 */
706INT WINAPIV wsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, ... )
707{
708 va_list valist;
709 INT res;
710
711 va_start( valist, spec );
712 res = wvsnprintfW( buffer, maxlen, spec, valist );
713 va_end( valist );
714 return res;
715}
Note: See TracBrowser for help on using the repository browser.