466671953145e018e7bc457a0f9ee008971bd209
[reactos.git] / reactos / lib / sdk / crt / printf / _sxprintf.c
1 /*
2 * COPYRIGHT: GNU GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS crt library
4 * FILE: lib/sdk/crt/printf/swprintf.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
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 /* Check trivial case */
61 if ((buffer == NULL) && (count == 0) && (sizeOfBuffer == 0))
62 {
63 return 0;
64 }
65
66 #if IS_SECAPI
67 /* Validate parameters */
68 if (MSVCRT_CHECK_PMT(((buffer == NULL) || (format == NULL) || (sizeOfBuffer <= 0))))
69 {
70 errno = EINVAL;
71 return -1;
72 }
73
74 /* Limit output to count + 1 characters */
75 if (count != -1)
76 sizeOfBuffer = min(sizeOfBuffer, count + 1);
77 #endif
78
79 /* Setup the FILE structure */
80 stream._base = (char*)buffer;
81 stream._ptr = stream._base;
82 stream._charbuf = 0;
83 stream._cnt = (int)(sizeOfBuffer * sizeof(TCHAR));
84 stream._bufsiz = 0;
85 stream._flag = _IOSTRG | _IOWRT;
86 stream._tmpfname = 0;
87
88 #if !USE_VARARGS
89 va_start(argptr, format);
90 #endif
91 result = _tstreamout(&stream, format, argptr);
92 #if !USE_VARARGS
93 va_end(argptr);
94 #endif
95
96 #if IS_SECAPI
97 /* Check for failure or unterminated string */
98 if ((result < 0) || (result == sizeOfBuffer))
99 {
100 /* Null-terminate the buffer at the end */
101 buffer[sizeOfBuffer-1] = _T('\0');
102
103 /* Check if we can truncate */
104 if (count != _TRUNCATE)
105 {
106 /* We can't, invoke invalid parameter handler */
107 MSVCRT_INVALID_PMT("Buffer is too small", ERANGE);
108
109 /* If we came back, set the buffer to an empty string */
110 *buffer = 0;
111 }
112
113 /* Return failure */
114 return -1;
115 }
116
117 /* Null-terminate the buffer after the string */
118 buffer[result] = _T('\0');
119 #else
120 /* Only zero terminate if there is enough space left */
121 if (stream._cnt >= sizeof(TCHAR)) *(TCHAR*)stream._ptr = _T('\0');
122 #endif
123
124 return result;
125 }
126
127