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