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 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