hlink: Use ifaces instead of vtbl pointers in ExtensionService.
[wine] / dlls / msvcrt / tests / printf.c
1 /*
2  * Conformance tests for *printf functions.
3  *
4  * Copyright 2002 Uwe Bonnes
5  * Copyright 2004 Aneurin Price
6  * Copyright 2005 Mike McCormack
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 /* With Visual Studio >= 2005,  swprintf() takes an extra parameter unless
24  * the following macro is defined.
25  */
26 #define _CRT_NON_CONFORMING_SWPRINTFS
27  
28 #include <stdio.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winnls.h"
33
34 #include "wine/test.h"
35
36 static int (__cdecl *p__vscprintf)(const char *format, __ms_va_list valist);
37 static int (__cdecl *p__vscwprintf)(const wchar_t *format, __ms_va_list valist);
38 static int (__cdecl *p__vsnwprintf_s)(wchar_t *str, size_t sizeOfBuffer,
39                                       size_t count, const wchar_t *format,
40                                       __ms_va_list valist);
41 static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number,
42                                 int ndigits, int *decpt, int *sign);
43 static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number,
44                                 int ndigits, int *decpt, int *sign);
45
46 static void init( void )
47 {
48     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
49
50     p__vscprintf = (void *)GetProcAddress(hmod, "_vscprintf");
51     p__vscwprintf = (void *)GetProcAddress(hmod, "_vscwprintf");
52     p__vsnwprintf_s = (void *)GetProcAddress(hmod, "_vsnwprintf_s");
53     p__ecvt_s = (void *)GetProcAddress(hmod, "_ecvt_s");
54     p__fcvt_s = (void *)GetProcAddress(hmod, "_fcvt_s");
55 }
56
57 static void test_sprintf( void )
58 {
59     char buffer[100];
60     const char *format;
61     double pnumber=789456123;
62     int x, r;
63     WCHAR wide[] = { 'w','i','d','e',0};
64
65     format = "%+#23.15e";
66     r = sprintf(buffer,format,pnumber);
67     ok(!strcmp(buffer,"+7.894561230000000e+008"),"+#23.15e failed: '%s'\n", buffer);
68     ok( r==23, "return count wrong\n");
69
70     format = "%-#23.15e";
71     r = sprintf(buffer,format,pnumber);
72     ok(!strcmp(buffer,"7.894561230000000e+008 "),"-#23.15e failed: '%s'\n", buffer);
73     ok( r==23, "return count wrong\n");
74
75     format = "%#23.15e";
76     r = sprintf(buffer,format,pnumber);
77     ok(!strcmp(buffer," 7.894561230000000e+008"),"#23.15e failed: '%s'\n", buffer);
78     ok( r==23, "return count wrong\n");
79
80     format = "%#1.1g";
81     r = sprintf(buffer,format,pnumber);
82     ok(!strcmp(buffer,"8.e+008"),"#1.1g failed: '%s'\n", buffer);
83     ok( r==7, "return count wrong\n");
84
85     format = "%I64d";
86     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
87     ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n");
88     ok( r==11, "return count wrong\n");
89
90     format = "%+8I64d";
91     r = sprintf(buffer,format,(LONGLONG)100);
92     ok(!strcmp(buffer,"    +100") && r==8,"+8I64d failed: '%s'\n", buffer);
93
94     format = "%+.8I64d";
95     r = sprintf(buffer,format,(LONGLONG)100);
96     ok(!strcmp(buffer,"+00000100") && r==9,"+.8I64d failed: '%s'\n", buffer);
97
98     format = "%+10.8I64d";
99     r = sprintf(buffer,format,(LONGLONG)100);
100     ok(!strcmp(buffer," +00000100") && r==10,"+10.8I64d failed: '%s'\n", buffer);
101     format = "%_1I64d";
102     r = sprintf(buffer,format,(LONGLONG)100);
103     ok(!strcmp(buffer,"_1I64d") && r==6,"_1I64d failed\n");
104
105     format = "%-1.5I64d";
106     r = sprintf(buffer,format,(LONGLONG)-100);
107     ok(!strcmp(buffer,"-00100") && r==6,"-1.5I64d failed: '%s'\n", buffer);
108
109     format = "%5I64d";
110     r = sprintf(buffer,format,(LONGLONG)100);
111     ok(!strcmp(buffer,"  100") && r==5,"5I64d failed: '%s'\n", buffer);
112
113     format = "%5I64d";
114     r = sprintf(buffer,format,(LONGLONG)-100);
115     ok(!strcmp(buffer," -100") && r==5,"5I64d failed: '%s'\n", buffer);
116
117     format = "%-5I64d";
118     r = sprintf(buffer,format,(LONGLONG)100);
119     ok(!strcmp(buffer,"100  ") && r==5,"-5I64d failed: '%s'\n", buffer);
120
121     format = "%-5I64d";
122     r = sprintf(buffer,format,(LONGLONG)-100);
123     ok(!strcmp(buffer,"-100 ") && r==5,"-5I64d failed: '%s'\n", buffer);
124
125     format = "%-.5I64d";
126     r = sprintf(buffer,format,(LONGLONG)100);
127     ok(!strcmp(buffer,"00100") && r==5,"-.5I64d failed: '%s'\n", buffer);
128
129     format = "%-.5I64d";
130     r = sprintf(buffer,format,(LONGLONG)-100);
131     ok(!strcmp(buffer,"-00100") && r==6,"-.5I64d failed: '%s'\n", buffer);
132
133     format = "%-8.5I64d";
134     r = sprintf(buffer,format,(LONGLONG)100);
135     ok(!strcmp(buffer,"00100   ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
136
137     format = "%-8.5I64d";
138     r = sprintf(buffer,format,(LONGLONG)-100);
139     ok(!strcmp(buffer,"-00100  ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
140
141     format = "%05I64d";
142     r = sprintf(buffer,format,(LONGLONG)100);
143     ok(!strcmp(buffer,"00100") && r==5,"05I64d failed: '%s'\n", buffer);
144
145     format = "%05I64d";
146     r = sprintf(buffer,format,(LONGLONG)-100);
147     ok(!strcmp(buffer,"-0100") && r==5,"05I64d failed: '%s'\n", buffer);
148
149     format = "% I64d";
150     r = sprintf(buffer,format,(LONGLONG)100);
151     ok(!strcmp(buffer," 100") && r==4,"' I64d' failed: '%s'\n", buffer);
152
153     format = "% I64d";
154     r = sprintf(buffer,format,(LONGLONG)-100);
155     ok(!strcmp(buffer,"-100") && r==4,"' I64d' failed: '%s'\n", buffer);
156
157     format = "% 5I64d";
158     r = sprintf(buffer,format,(LONGLONG)100);
159     ok(!strcmp(buffer,"  100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
160
161     format = "% 5I64d";
162     r = sprintf(buffer,format,(LONGLONG)-100);
163     ok(!strcmp(buffer," -100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
164
165     format = "% .5I64d";
166     r = sprintf(buffer,format,(LONGLONG)100);
167     ok(!strcmp(buffer," 00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
168
169     format = "% .5I64d";
170     r = sprintf(buffer,format,(LONGLONG)-100);
171     ok(!strcmp(buffer,"-00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
172
173     format = "% 8.5I64d";
174     r = sprintf(buffer,format,(LONGLONG)100);
175     ok(!strcmp(buffer,"   00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
176
177     format = "% 8.5I64d";
178     r = sprintf(buffer,format,(LONGLONG)-100);
179     ok(!strcmp(buffer,"  -00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
180
181     format = "%.0I64d";
182     r = sprintf(buffer,format,(LONGLONG)0);
183     ok(r==0,".0I64d failed: '%s'\n", buffer);
184
185     format = "%#+21.18I64x";
186     r = sprintf(buffer,format,(LONGLONG)-100);
187     ok(!strcmp(buffer," 0x00ffffffffffffff9c") && r==21,"#+21.18I64x failed: '%s'\n", buffer);
188
189     format = "%#.25I64o";
190     r = sprintf(buffer,format,(LONGLONG)-100);
191     ok(!strcmp(buffer,"0001777777777777777777634") && r==25,"#.25I64o failed: '%s'\n", buffer);
192
193     format = "%#+24.20I64o";
194     r = sprintf(buffer,format,(LONGLONG)-100);
195     ok(!strcmp(buffer," 01777777777777777777634") && r==24,"#+24.20I64o failed: '%s'\n", buffer);
196
197     format = "%#+18.21I64X";
198     r = sprintf(buffer,format,(LONGLONG)-100);
199     ok(!strcmp(buffer,"0X00000FFFFFFFFFFFFFF9C") && r==23,"#+18.21I64X failed: '%s '\n", buffer);
200
201     format = "%#+20.24I64o";
202     r = sprintf(buffer,format,(LONGLONG)-100);
203     ok(!strcmp(buffer,"001777777777777777777634") && r==24,"#+20.24I64o failed: '%s'\n", buffer);
204
205     format = "%#+25.22I64u";
206     r = sprintf(buffer,format,(LONGLONG)-1);
207     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u conversion failed: '%s'\n", buffer);
208
209     format = "%#+25.22I64u";
210     r = sprintf(buffer,format,(LONGLONG)-1);
211     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u failed: '%s'\n", buffer);
212
213     format = "%#+30.25I64u";
214     r = sprintf(buffer,format,(LONGLONG)-1);
215     ok(!strcmp(buffer,"     0000018446744073709551615") && r==30,"#+30.25I64u failed: '%s'\n", buffer);
216
217     format = "%+#25.22I64d";
218     r = sprintf(buffer,format,(LONGLONG)-1);
219     ok(!strcmp(buffer,"  -0000000000000000000001") && r==25,"+#25.22I64d failed: '%s'\n", buffer);
220
221     format = "%#-8.5I64o";
222     r = sprintf(buffer,format,(LONGLONG)100);
223     ok(!strcmp(buffer,"00144   ") && r==8,"-8.5I64o failed: '%s'\n", buffer);
224
225     format = "%#-+ 08.5I64d";
226     r = sprintf(buffer,format,(LONGLONG)100);
227     ok(!strcmp(buffer,"+00100  ") && r==8,"'#-+ 08.5I64d failed: '%s'\n", buffer);
228
229     format = "%#-+ 08.5I64d";
230     r = sprintf(buffer,format,(LONGLONG)100);
231     ok(!strcmp(buffer,"+00100  ") && r==8,"#-+ 08.5I64d failed: '%s'\n", buffer);
232
233     format = "%.80I64d";
234     r = sprintf(buffer,format,(LONGLONG)1);
235     ok(r==80,"%s format failed\n", format);
236
237     format = "% .80I64d";
238     r = sprintf(buffer,format,(LONGLONG)1);
239     ok(r==81,"%s format failed\n", format);
240
241     format = "% .80d";
242     r = sprintf(buffer,format,1);
243     ok(r==81,"%s format failed\n", format);
244
245     format = "%lld";
246     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
247     ok( r == 1 || r == 11, "return count wrong %d\n", r);
248     if (r == 11)  /* %ll works on Vista */
249         ok(!strcmp(buffer, "-8589934591"), "Problem with \"ll\" interpretation '%s'\n", buffer);
250     else
251         ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation '%s'\n", buffer);
252
253     format = "%I";
254     r = sprintf(buffer,format,1);
255     ok(!strcmp(buffer, "I"), "Problem with \"I\" interpretation\n");
256     ok( r==1, "return count wrong\n");
257
258     format = "%I0d";
259     r = sprintf(buffer,format,1);
260     ok(!strcmp(buffer,"I0d"),"I0d failed\n");
261     ok( r==3, "return count wrong\n");
262
263     format = "%I32d";
264     r = sprintf(buffer,format,1);
265     if (r == 1)
266     {
267         ok(!strcmp(buffer,"1"),"I32d failed, got '%s'\n",buffer);
268     }
269     else
270     {
271         /* Older versions don't grok I32 format */
272         ok(r == 4 && !strcmp(buffer,"I32d"),"I32d failed, got '%s',%d\n",buffer,r);
273     }
274
275     format = "%I64D";
276     r = sprintf(buffer,format,(LONGLONG)-1);
277     ok(!strcmp(buffer,"D"),"I64D failed: %s\n",buffer);
278     ok( r==1, "return count wrong\n");
279
280     format = "% d";
281     r = sprintf(buffer,format,1);
282     ok(!strcmp(buffer, " 1"),"Problem with sign place-holder: '%s'\n",buffer);
283     ok( r==2, "return count wrong\n");
284
285     format = "%+ d";
286     r = sprintf(buffer,format,1);
287     ok(!strcmp(buffer, "+1"),"Problem with sign flags: '%s'\n",buffer);
288     ok( r==2, "return count wrong\n");
289
290     format = "%S";
291     r = sprintf(buffer,format,wide);
292     ok(!strcmp(buffer,"wide"),"Problem with wide string format\n");
293     ok( r==4, "return count wrong\n");
294
295     format = "%04c";
296     r = sprintf(buffer,format,'1');
297     ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
298     ok( r==4, "return count wrong\n");
299
300     format = "%-04c";
301     r = sprintf(buffer,format,'1');
302     ok(!strcmp(buffer,"1   "),"Character zero-padded and/or not left-adjusted \"%s\"\n",buffer);
303     ok( r==4, "return count wrong\n");
304
305     if (sizeof(void *) == 8)
306     {
307         format = "%p";
308         r = sprintf(buffer,format,(void *)57);
309         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
310         ok( r==16, "return count wrong\n");
311
312         format = "%#020p";
313         r = sprintf(buffer,format,(void *)57);
314         ok(!strcmp(buffer,"  0X0000000000000039"),"Pointer formatted incorrectly\n");
315         ok( r==20, "return count wrong\n");
316
317         format = "%Fp";
318         r = sprintf(buffer,format,(void *)57);
319         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
320         ok( r==16, "return count wrong\n");
321
322         format = "%#-020p";
323         r = sprintf(buffer,format,(void *)57);
324         ok(!strcmp(buffer,"0X0000000000000039  "),"Pointer formatted incorrectly\n");
325         ok( r==20, "return count wrong\n");
326     }
327     else
328     {
329         format = "%p";
330         r = sprintf(buffer,format,(void *)57);
331         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
332         ok( r==8, "return count wrong\n");
333
334         format = "%#012p";
335         r = sprintf(buffer,format,(void *)57);
336         ok(!strcmp(buffer,"  0X00000039"),"Pointer formatted incorrectly\n");
337         ok( r==12, "return count wrong\n");
338
339         format = "%Fp";
340         r = sprintf(buffer,format,(void *)57);
341         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
342         ok( r==8, "return count wrong\n");
343
344         format = "%#-012p";
345         r = sprintf(buffer,format,(void *)57);
346         ok(!strcmp(buffer,"0X00000039  "),"Pointer formatted incorrectly\n");
347         ok( r==12, "return count wrong\n");
348     }
349
350     format = "%04s";
351     r = sprintf(buffer,format,"foo");
352     ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
353     ok( r==4, "return count wrong\n");
354
355     format = "%.1s";
356     r = sprintf(buffer,format,"foo");
357     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
358     ok( r==1, "return count wrong\n");
359
360     format = "%.*s";
361     r = sprintf(buffer,format,1,"foo");
362     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
363     ok( r==1, "return count wrong\n");
364
365     format = "%*s";
366     r = sprintf(buffer,format,-5,"foo");
367     ok(!strcmp(buffer,"foo  "),"Negative field width ignored \"%s\"\n",buffer);
368     ok( r==5, "return count wrong\n");
369
370     format = "hello";
371     r = sprintf(buffer, format);
372     ok(!strcmp(buffer,"hello"), "failed\n");
373     ok( r==5, "return count wrong\n");
374
375     format = "%ws";
376     r = sprintf(buffer, format, wide);
377     ok(!strcmp(buffer,"wide"), "failed\n");
378     ok( r==4, "return count wrong\n");
379
380     format = "%-10ws";
381     r = sprintf(buffer, format, wide );
382     ok(!strcmp(buffer,"wide      "), "failed\n");
383     ok( r==10, "return count wrong\n");
384
385     format = "%10ws";
386     r = sprintf(buffer, format, wide );
387     ok(!strcmp(buffer,"      wide"), "failed\n");
388     ok( r==10, "return count wrong\n");
389
390     format = "%#+ -03whlls";
391     r = sprintf(buffer, format, wide );
392     ok(!strcmp(buffer,"wide"), "failed\n");
393     ok( r==4, "return count wrong\n");
394
395     format = "%w0s";
396     r = sprintf(buffer, format, wide );
397     ok(!strcmp(buffer,"0s"), "failed\n");
398     ok( r==2, "return count wrong\n");
399
400     format = "%w-s";
401     r = sprintf(buffer, format, wide );
402     ok(!strcmp(buffer,"-s"), "failed\n");
403     ok( r==2, "return count wrong\n");
404
405     format = "%ls";
406     r = sprintf(buffer, format, wide );
407     ok(!strcmp(buffer,"wide"), "failed\n");
408     ok( r==4, "return count wrong\n");
409
410     format = "%Ls";
411     r = sprintf(buffer, format, "not wide" );
412     ok(!strcmp(buffer,"not wide"), "failed\n");
413     ok( r==8, "return count wrong\n");
414
415     format = "%b";
416     r = sprintf(buffer, format);
417     ok(!strcmp(buffer,"b"), "failed\n");
418     ok( r==1, "return count wrong\n");
419
420     format = "%3c";
421     r = sprintf(buffer, format,'a');
422     ok(!strcmp(buffer,"  a"), "failed\n");
423     ok( r==3, "return count wrong\n");
424
425     format = "%3d";
426     r = sprintf(buffer, format,1234);
427     ok(!strcmp(buffer,"1234"), "failed\n");
428     ok( r==4, "return count wrong\n");
429
430     format = "%3h";
431     r = sprintf(buffer, format);
432     ok(!strcmp(buffer,""), "failed\n");
433     ok( r==0, "return count wrong\n");
434
435     format = "%j%k%m%q%r%t%v%y%z";
436     r = sprintf(buffer, format);
437     ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n");
438     ok( r==9, "return count wrong\n");
439
440     format = "asdf%n";
441     x = 0;
442     r = sprintf(buffer, format, &x );
443     if (r == -1)
444     {
445         /* %n format is disabled by default on vista */
446         /* FIXME: should test with _set_printf_count_output */
447         ok(x == 0, "should not write to x: %d\n", x);
448     }
449     else
450     {
451         ok(x == 4, "should write to x: %d\n", x);
452         ok(!strcmp(buffer,"asdf"), "failed\n");
453         ok( r==4, "return count wrong: %d\n", r);
454     }
455
456     format = "%-1d";
457     r = sprintf(buffer, format,2);
458     ok(!strcmp(buffer,"2"), "failed\n");
459     ok( r==1, "return count wrong\n");
460
461     format = "%2.4f";
462     r = sprintf(buffer, format,8.6);
463     ok(!strcmp(buffer,"8.6000"), "failed\n");
464     ok( r==6, "return count wrong\n");
465
466     format = "%0f";
467     r = sprintf(buffer, format,0.6);
468     ok(!strcmp(buffer,"0.600000"), "failed\n");
469     ok( r==8, "return count wrong\n");
470
471     format = "%.0f";
472     r = sprintf(buffer, format,0.6);
473     ok(!strcmp(buffer,"1"), "failed\n");
474     ok( r==1, "return count wrong\n");
475
476     format = "%2.4e";
477     r = sprintf(buffer, format,8.6);
478     ok(!strcmp(buffer,"8.6000e+000"), "failed\n");
479     ok( r==11, "return count wrong\n");
480
481     format = "%2.4g";
482     r = sprintf(buffer, format,8.6);
483     ok(!strcmp(buffer,"8.6"), "failed\n");
484     ok( r==3, "return count wrong\n");
485
486     format = "%-i";
487     r = sprintf(buffer, format,-1);
488     ok(!strcmp(buffer,"-1"), "failed\n");
489     ok( r==2, "return count wrong\n");
490
491     format = "%-i";
492     r = sprintf(buffer, format,1);
493     ok(!strcmp(buffer,"1"), "failed\n");
494     ok( r==1, "return count wrong\n");
495
496     format = "%+i";
497     r = sprintf(buffer, format,1);
498     ok(!strcmp(buffer,"+1"), "failed\n");
499     ok( r==2, "return count wrong\n");
500
501     format = "%o";
502     r = sprintf(buffer, format,10);
503     ok(!strcmp(buffer,"12"), "failed\n");
504     ok( r==2, "return count wrong\n");
505
506     format = "%p";
507     r = sprintf(buffer, format,0);
508     if (sizeof(void *) == 8)
509     {
510         ok(!strcmp(buffer,"0000000000000000"), "failed\n");
511         ok( r==16, "return count wrong\n");
512     }
513     else
514     {
515         ok(!strcmp(buffer,"00000000"), "failed\n");
516         ok( r==8, "return count wrong\n");
517     }
518
519     format = "%s";
520     r = sprintf(buffer, format,0);
521     ok(!strcmp(buffer,"(null)"), "failed\n");
522     ok( r==6, "return count wrong\n");
523
524     format = "%s";
525     r = sprintf(buffer, format,"%%%%");
526     ok(!strcmp(buffer,"%%%%"), "failed\n");
527     ok( r==4, "return count wrong\n");
528
529     format = "%u";
530     r = sprintf(buffer, format,-1);
531     ok(!strcmp(buffer,"4294967295"), "failed\n");
532     ok( r==10, "return count wrong\n");
533
534     format = "%w";
535     r = sprintf(buffer, format,-1);
536     ok(!strcmp(buffer,""), "failed\n");
537     ok( r==0, "return count wrong\n");
538
539     format = "%h";
540     r = sprintf(buffer, format,-1);
541     ok(!strcmp(buffer,""), "failed\n");
542     ok( r==0, "return count wrong\n");
543
544     format = "%z";
545     r = sprintf(buffer, format,-1);
546     ok(!strcmp(buffer,"z"), "failed\n");
547     ok( r==1, "return count wrong\n");
548
549     format = "%j";
550     r = sprintf(buffer, format,-1);
551     ok(!strcmp(buffer,"j"), "failed\n");
552     ok( r==1, "return count wrong\n");
553
554     format = "%F";
555     r = sprintf(buffer, format,-1);
556     ok(!strcmp(buffer,""), "failed\n");
557     ok( r==0, "return count wrong\n");
558
559     format = "%H";
560     r = sprintf(buffer, format,-1);
561     ok(!strcmp(buffer,"H"), "failed\n");
562     ok( r==1, "return count wrong\n");
563
564     format = "x%cx";
565     r = sprintf(buffer, format, 0x100+'X');
566     ok(!strcmp(buffer,"xXx"), "failed\n");
567     ok( r==3, "return count wrong\n");
568
569     format = "%%0";
570     r = sprintf(buffer, format);
571     ok(!strcmp(buffer,"%0"), "failed: \"%s\"\n", buffer);
572     ok( r==2, "return count wrong\n");
573 }
574
575 static void test_swprintf( void )
576 {
577     wchar_t buffer[100];
578     const wchar_t I64d[] = {'%','I','6','4','d',0};
579     double pnumber=789456123;
580     const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0};
581     const wchar_t e008[] = {'e','+','0','0','8',0};
582     const wchar_t string_w[] = {'s','t','r','i','n','g',0};
583     const char string[] = "string";
584     const wchar_t S[]={'%','S',0};
585     const wchar_t hs[] = {'%', 'h', 's', 0};
586
587     swprintf(buffer,TwentyThreePoint15e,pnumber);
588     ok(wcsstr(buffer,e008) != 0,"Sprintf different\n");
589     swprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
590       ok(wcslen(buffer) == 11,"Problem with long long\n");
591     swprintf(buffer,S,string);
592       ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n");
593    swprintf(buffer, hs, string);
594    ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n");
595 }
596
597 static void test_snprintf (void)
598 {
599     struct snprintf_test {
600         const char *format;
601         int expected;
602     };
603     /* Pre-2.1 libc behaviour, not C99 compliant. */
604     const struct snprintf_test tests[] = {{"short", 5},
605                                           {"justfit", 7},
606                                           {"justfits", 8},
607                                           {"muchlonger", -1}};
608     char buffer[8];
609     const int bufsiz = sizeof buffer;
610     unsigned int i;
611
612     for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
613         const char *fmt  = tests[i].format;
614         const int expect = tests[i].expected;
615         const int n      = _snprintf (buffer, bufsiz, fmt);
616         const int valid  = n < 0 ? bufsiz : (n == bufsiz ? n : n+1);
617
618         ok (n == expect, "\"%s\": expected %d, returned %d\n",
619             fmt, expect, n);
620         ok (!memcmp (fmt, buffer, valid),
621             "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer);
622     };
623 }
624
625 static void test_fcvt(void)
626 {
627     char *str;
628     int dec=100, sign=100;
629     
630     /* Numbers less than 1.0 with different precisions */
631     str = _fcvt(0.0001, 1, &dec, &sign );
632     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
633     ok( -3 == dec, "dec wrong %d\n", dec);
634     ok( 0 == sign, "sign wrong\n");
635
636     str = _fcvt(0.0001, -10, &dec, &sign );
637     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
638     ok( -3 == dec, "dec wrong %d\n", dec);
639     ok( 0 == sign, "sign wrong\n");
640
641     str = _fcvt(0.0001, 10, &dec, &sign );
642     ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str);
643     ok( -3 == dec, "dec wrong %d\n", dec);
644     ok( 0 == sign, "sign wrong\n");
645
646     /* Basic sign test */
647     str = _fcvt(-111.0001, 5, &dec, &sign );
648     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
649     ok( 3 == dec, "dec wrong %d\n", dec);
650     ok( 1 == sign, "sign wrong\n");
651
652     str = _fcvt(111.0001, 5, &dec, &sign );
653     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
654     ok( 3 == dec, "dec wrong\n");
655     ok( 0 == sign, "sign wrong\n");
656
657     /* 0.0 with different precisions */
658     str = _fcvt(0.0, 5, &dec, &sign );
659     ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str);
660     ok( 0 == dec, "dec wrong %d\n", dec);
661     ok( 0 == sign, "sign wrong\n");
662
663     str = _fcvt(0.0, 0, &dec, &sign );
664     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
665     ok( 0 == dec, "dec wrong %d\n", dec);
666     ok( 0 == sign, "sign wrong\n");
667
668     str = _fcvt(0.0, -1, &dec, &sign );
669     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
670     ok( 0 == dec, "dec wrong %d\n", dec);
671     ok( 0 == sign, "sign wrong\n");
672
673     /* Numbers > 1.0 with 0 or -ve precision */
674     str = _fcvt(-123.0001, 0, &dec, &sign );
675     ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str);
676     ok( 3 == dec, "dec wrong %d\n", dec);
677     ok( 1 == sign, "sign wrong\n");
678
679     str = _fcvt(-123.0001, -1, &dec, &sign );
680     ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str);
681     ok( 3 == dec, "dec wrong %d\n", dec);
682     ok( 1 == sign, "sign wrong\n");
683
684     str = _fcvt(-123.0001, -2, &dec, &sign );
685     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
686     ok( 3 == dec, "dec wrong %d\n", dec);
687     ok( 1 == sign, "sign wrong\n");
688
689     str = _fcvt(-123.0001, -3, &dec, &sign );
690     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
691     ok( 3 == dec, "dec wrong %d\n", dec);
692     ok( 1 == sign, "sign wrong\n");
693
694     /* Numbers > 1.0, but with rounding at the point of precision */
695     str = _fcvt(99.99, 1, &dec, &sign );
696     ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str);
697     ok( 3 == dec, "dec wrong %d\n", dec);
698     ok( 0 == sign, "sign wrong\n");
699
700     /* Numbers < 1.0 where rounding occurs at the point of precision */
701     str = _fcvt(0.00636, 2, &dec, &sign );
702     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
703     ok( -1 == dec, "dec wrong %d\n", dec);
704     ok( 0 == sign, "sign wrong\n");
705
706     str = _fcvt(0.00636, 3, &dec, &sign );
707     ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str);
708     ok( -2 == dec, "dec wrong %d\n", dec);
709     ok( 0 == sign, "sign wrong\n");
710
711     str = _fcvt(0.09999999996, 2, &dec, &sign );
712     ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str);
713     ok( 0 == dec, "dec wrong %d\n", dec);
714     ok( 0 == sign, "sign wrong\n");
715
716     str = _fcvt(0.6, 0, &dec, &sign );
717     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
718     ok( 1 == dec, "dec wrong %d\n", dec);
719     ok( 0 == sign, "sign wrong\n");
720 }
721
722 /* Don't test nrdigits < 0, msvcrt on Win9x and NT4 will corrupt memory by
723  * writing outside allocated memory */
724 static struct {
725     double value;
726     int nrdigits;
727     const char *expstr_e;
728     const char *expstr_f;
729     int expdecpt_e;
730     int expdecpt_f;
731     int expsign;
732 } test_cvt_testcases[] = {
733     {          45.0,   2,        "45",           "4500",          2,      2,      0 },
734     /* Numbers less than 1.0 with different precisions */
735     {        0.0001,   1,         "1",               "",         -3,     -3,     0 },
736     {        0.0001,  10,"1000000000",        "1000000",         -3,     -3,     0 },
737     /* Basic sign test */
738     {     -111.0001,   5,     "11100",       "11100010",          3,      3,     1 },
739     {      111.0001,   5,     "11100",       "11100010",          3,      3,     0 },
740     /* big numbers with low precision */
741     {        3333.3,   2,        "33",         "333330",          4,      4,     0 },
742     {999999999999.9,   3,       "100","999999999999900",         13,     12,     0 },
743     /* 0.0 with different precisions */
744     {           0.0,   5,     "00000",          "00000",          0,      0,     0 },
745     {           0.0,   0,          "",               "",          0,      0,     0 },
746     {           0.0,  -1,          "",               "",          0,      0,     0 },
747     /* Numbers > 1.0 with 0 or -ve precision */
748     {     -123.0001,   0,          "",            "123",          3,      3,     1 },
749     {     -123.0001,  -1,          "",             "12",          3,      3,     1 },
750     {     -123.0001,  -2,          "",              "1",          3,      3,     1 },
751     {     -123.0001,  -3,          "",               "",          3,      3,     1 },
752     /* Numbers > 1.0, but with rounding at the point of precision */
753     {         99.99,   1,         "1",           "1000",          3,      3,     0 },
754     /* Numbers < 1.0 where rounding occurs at the point of precision */
755     {        0.0063,   2,        "63",              "1",         -2,     -1,     0 },
756     {        0.0063,   3,        "630",             "6",         -2,     -2,     0 },
757     { 0.09999999996,   2,        "10",             "10",          0,      0,     0 },
758     {           0.6,   1,         "6",              "6",          0,      0,     0 },
759     {           0.6,   0,          "",              "1",          1,      1,     0 },
760     {           0.4,   0,          "",               "",          0,      0,     0 },
761     {          0.49,   0,          "",               "",          0,      0,     0 },
762     {          0.51,   0,          "",              "1",          1,      1,     0 },
763     /* ask ridiculous amunt of precision, ruin formatting this table */
764     {           1.0,  30, "100000000000000000000000000000",
765                       "1000000000000000000000000000000",          1,      1,      0},
766     {           123456789012345678901.0,  30, "123456789012345680000000000000",
767                       "123456789012345680000000000000000000000000000000000",         21,    21,      0},
768     /* end marker */
769     { 0, 0, "END"}
770 };
771
772 static void test_xcvt(void)
773 {
774     char *str;
775     int i, decpt, sign, err;
776     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
777         decpt = sign = 100;
778         str = _ecvt( test_cvt_testcases[i].value,
779                 test_cvt_testcases[i].nrdigits,
780                 &decpt,
781                 &sign);
782         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
783                "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str,
784               test_cvt_testcases[i].expstr_e);
785         ok( decpt == test_cvt_testcases[i].expdecpt_e,
786                 "_ecvt() decimal point wrong, got %d expected %d\n", decpt,
787                 test_cvt_testcases[i].expdecpt_e);
788         ok( sign == test_cvt_testcases[i].expsign,
789                 "_ecvt() sign wrong, got %d expected %d\n", sign,
790                 test_cvt_testcases[i].expsign);
791     }
792     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
793         decpt = sign = 100;
794         str = _fcvt( test_cvt_testcases[i].value,
795                 test_cvt_testcases[i].nrdigits,
796                 &decpt,
797                 &sign);
798         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
799                "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str,
800               test_cvt_testcases[i].expstr_f);
801         ok( decpt == test_cvt_testcases[i].expdecpt_f,
802                 "_fcvt() decimal point wrong, got %d expected %d\n", decpt,
803                 test_cvt_testcases[i].expdecpt_f);
804         ok( sign == test_cvt_testcases[i].expsign,
805                 "_fcvt() sign wrong, got %d expected %d\n", sign,
806                 test_cvt_testcases[i].expsign);
807     }
808
809     if (p__ecvt_s)
810     {
811         str = malloc(1024);
812         for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
813             decpt = sign = 100;
814             err = p__ecvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
815             ok(err == 0, "_ecvt_s() failed with error code %d\n", err);
816             ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
817                    "_ecvt_s() bad return, got \n'%s' expected \n'%s'\n", str,
818                   test_cvt_testcases[i].expstr_e);
819             ok( decpt == test_cvt_testcases[i].expdecpt_e,
820                     "_ecvt_s() decimal point wrong, got %d expected %d\n", decpt,
821                     test_cvt_testcases[i].expdecpt_e);
822             ok( sign == test_cvt_testcases[i].expsign,
823                     "_ecvt_s() sign wrong, got %d expected %d\n", sign,
824                     test_cvt_testcases[i].expsign);
825         }
826         free(str);
827     }
828     else
829         win_skip("_ecvt_s not available\n");
830
831     if (p__fcvt_s)
832     {
833         str = malloc(1024);
834         for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
835             decpt = sign = 100;
836             err = p__fcvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
837             ok(err == 0, "_fcvt_s() failed with error code %d", err);
838             ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
839                    "_fcvt_s() bad return, got \n'%s' expected \n'%s'\n", str,
840                   test_cvt_testcases[i].expstr_e);
841             ok( decpt == test_cvt_testcases[i].expdecpt_f,
842                     "_fcvt_s() decimal point wrong, got %d expected %d\n", decpt,
843                     test_cvt_testcases[i].expdecpt_e);
844             ok( sign == test_cvt_testcases[i].expsign,
845                     "_fcvt_s() sign wrong, got %d expected %d\n", sign,
846                     test_cvt_testcases[i].expsign);
847         }
848         free(str);
849     }
850     else
851         todo_wine win_skip("_fcvt_s not available\n");
852 }
853
854 static int __cdecl _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...)
855 {
856     int ret;
857     __ms_va_list valist;
858     __ms_va_start(valist, format);
859     ret = _vsnwprintf(str, len, format, valist);
860     __ms_va_end(valist);
861     return ret;
862 }
863
864 static void test_vsnwprintf(void)
865 {
866     const wchar_t format[] = {'%','w','s','%','w','s','%','w','s',0};
867     const wchar_t one[]    = {'o','n','e',0};
868     const wchar_t two[]    = {'t','w','o',0};
869     const wchar_t three[]  = {'t','h','r','e','e',0};
870
871     int ret;
872     wchar_t str[32];
873     char buf[32];
874
875     ret = _vsnwprintf_wrapper( str, sizeof(str)/sizeof(str[0]), format, one, two, three );
876
877     ok( ret == 11, "got %d expected 11\n", ret );
878     WideCharToMultiByte( CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL );
879     ok( !strcmp(buf, "onetwothree"), "got %s expected 'onetwothree'\n", buf );
880 }
881
882 static int __cdecl _vscprintf_wrapper(const char *format, ...)
883 {
884     int ret;
885     __ms_va_list valist;
886     __ms_va_start(valist, format);
887     ret = p__vscprintf(format, valist);
888     __ms_va_end(valist);
889     return ret;
890 }
891
892 static void test_vscprintf(void)
893 {
894     int ret;
895
896     if (!p__vscprintf)
897     {
898        win_skip("_vscprintf not available\n");
899        return;
900     }
901
902     ret = _vscprintf_wrapper( "%s %d", "number", 1 );
903     ok( ret == 8, "got %d expected 8\n", ret );
904 }
905
906 static int __cdecl _vscwprintf_wrapper(const wchar_t *format, ...)
907 {
908     int ret;
909     __ms_va_list valist;
910     __ms_va_start(valist, format);
911     ret = p__vscwprintf(format, valist);
912     __ms_va_end(valist);
913     return ret;
914 }
915
916 static void test_vscwprintf(void)
917 {
918     const wchar_t format[] = {'%','s',' ','%','d',0};
919     const wchar_t number[] = {'n','u','m','b','e','r',0};
920
921     int ret;
922
923     if (!p__vscwprintf)
924     {
925         win_skip("_vscwprintf not available\n");
926         return;
927     }
928
929     ret = _vscwprintf_wrapper( format, number, 1 );
930     ok( ret == 8, "got %d expected 8\n", ret );
931 }
932
933 static int __cdecl _vsnwprintf_s_wrapper(wchar_t *str, size_t sizeOfBuffer,
934                                  size_t count, const wchar_t *format, ...)
935 {
936     int ret;
937     __ms_va_list valist;
938     __ms_va_start(valist, format);
939     ret = p__vsnwprintf_s(str, sizeOfBuffer, count, format, valist);
940     __ms_va_end(valist);
941     return ret;
942 }
943
944 static void test_vsnwprintf_s(void)
945 {
946     const wchar_t format[] = { 'A','B','%','u','C',0 };
947     const wchar_t out7[] = { 'A','B','1','2','3','C',0 };
948     const wchar_t out6[] = { 'A','B','1','2','3',0 };
949     const wchar_t out2[] = { 'A',0 };
950     const wchar_t out1[] = { 0 };
951     wchar_t buffer[14] = { 0 };
952     int exp, got;
953
954     if (!p__vsnwprintf_s)
955     {
956         win_skip("_vsnwprintf_s not available\n");
957         return;
958     }
959
960     /* Enough room. */
961     exp = wcslen(out7);
962
963     got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123);
964     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
965     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
966
967     got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123);
968     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
969     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
970
971     got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123);
972     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
973     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
974
975     /* Not enough room. */
976     exp = -1;
977
978     got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123);
979     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
980     ok( !wcscmp(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
981
982     got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123);
983     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
984     ok( !wcscmp(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
985
986     got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123);
987     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
988     ok( !wcscmp(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
989 }
990
991 START_TEST(printf)
992 {
993     init();
994
995     test_sprintf();
996     test_swprintf();
997     test_snprintf();
998     test_fcvt();
999     test_xcvt();
1000     test_vsnwprintf();
1001     test_vscprintf();
1002     test_vscwprintf();
1003     test_vsnwprintf_s();
1004 }