xref: /reactos/sdk/lib/crt/printf/_sxprintf.c (revision b707be90)
1 /*
2  * COPYRIGHT:       GNU GPL, see COPYING in the top level directory
3  * PROJECT:         ReactOS crt library
4  * FILE:            lib/sdk/crt/printf/_sxprintf.c
5  * PURPOSE:         Implementation of swprintf
6  * PROGRAMMER:      Timo Kreuzer
7  */
8 
9 #include <stdio.h>
10 #include <stdarg.h>
11 #include <limits.h>
12 #include <tchar.h>
13 #if IS_SECAPI
14 #include <internal/safecrt.h>
15 #endif
16 
17 #ifdef _UNICODE
18 #define _tstreamout wstreamout
19 #else
20 #define _tstreamout streamout
21 #endif
22 
23 #define min(a,b) (((a) < (b)) ? (a) : (b))
24 
25 int __cdecl _tstreamout(FILE *stream, const _TCHAR *format, va_list argptr);
26 
27 int
28 #if defined(USER32_WSPRINTF) && defined(_M_IX86)
29 __stdcall
30 #else
31 __cdecl
32 #endif
_sxprintf(_TCHAR * buffer,size_t sizeOfBuffer,size_t count,const _TCHAR * format,va_list argptr)33 _sxprintf(
34     _TCHAR *buffer,
35 #if IS_SECAPI
36     size_t sizeOfBuffer,
37 #endif
38 #if USE_COUNT
39    size_t count,
40 #endif
41     const _TCHAR *format,
42 #if USE_VARARGS
43     va_list argptr)
44 #else
45     ...)
46 #endif
47 {
48 #if !USE_COUNT
49     const size_t count = INT_MAX;
50 #endif
51 #if !IS_SECAPI
52     const size_t sizeOfBuffer = count;
53 #endif
54 #if !USE_VARARGS
55     va_list argptr;
56 #endif
57     int result;
58     FILE stream;
59 
60 #if IS_SECAPI
61     /* Validate parameters */
62     if (MSVCRT_CHECK_PMT(((buffer == NULL) || (format == NULL) || (sizeOfBuffer <= 0))))
63     {
64         errno = EINVAL;
65         return -1;
66     }
67 
68     /* Limit output to count + 1 characters */
69     if (count != -1)
70         sizeOfBuffer = min(sizeOfBuffer, count + 1);
71 #endif
72 
73     /* Setup the FILE structure */
74     stream._base = (char*)buffer;
75     stream._ptr = stream._base;
76     stream._charbuf = 0;
77     stream._cnt = (int)(sizeOfBuffer * sizeof(_TCHAR));
78     stream._bufsiz = 0;
79     stream._flag = _IOSTRG | _IOWRT;
80     stream._tmpfname = 0;
81 
82 #if !USE_VARARGS
83     va_start(argptr, format);
84 #endif
85     result = _tstreamout(&stream, format, argptr);
86 #if !USE_VARARGS
87     va_end(argptr);
88 #endif
89 
90 #if IS_SECAPI
91     /* Check for failure or unterminated string */
92     if ((result < 0) || (result == sizeOfBuffer))
93     {
94         /* Null-terminate the buffer at the end */
95         buffer[sizeOfBuffer-1] = _T('\0');
96 
97         /* Check if we can truncate */
98         if (count != _TRUNCATE)
99         {
100             /* We can't, invoke invalid parameter handler */
101             MSVCRT_INVALID_PMT("Buffer is too small", ERANGE);
102 
103             /* If we came back, set the buffer to an empty string */
104             *buffer = 0;
105         }
106 
107         /* Return failure */
108         return -1;
109     }
110 
111     /* Null-terminate the buffer after the string */
112     buffer[result] = _T('\0');
113 #else
114     /* Only zero terminate if there is enough space left */
115     if ((stream._cnt >= sizeof(_TCHAR)) && (stream._ptr))
116         *(_TCHAR*)stream._ptr = _T('\0');
117 #endif
118 
119     return result;
120 }
121 
122 
123