2011-01-03 01:07:54 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: GNU GPL, see COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS crt library
|
2015-09-19 13:50:57 +00:00
|
|
|
* FILE: lib/sdk/crt/printf/_sxprintf.c
|
2011-01-03 01:07:54 +00:00
|
|
|
* PURPOSE: Implementation of swprintf
|
|
|
|
* PROGRAMMER: Timo Kreuzer
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <tchar.h>
|
2013-03-16 13:40:28 +00:00
|
|
|
#if IS_SECAPI
|
|
|
|
#include <internal/safecrt.h>
|
|
|
|
#endif
|
2011-01-03 01:07:54 +00:00
|
|
|
|
|
|
|
#ifdef _UNICODE
|
|
|
|
#define _tstreamout wstreamout
|
|
|
|
#else
|
|
|
|
#define _tstreamout streamout
|
|
|
|
#endif
|
|
|
|
|
2013-03-16 13:40:28 +00:00
|
|
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
|
|
|
2013-09-14 10:28:30 +00:00
|
|
|
int __cdecl _tstreamout(FILE *stream, const TCHAR *format, va_list argptr);
|
2011-01-03 01:07:54 +00:00
|
|
|
|
|
|
|
int
|
2011-01-11 19:09:48 +00:00
|
|
|
#if defined(USER32_WSPRINTF) && defined(_M_IX86)
|
2013-09-14 10:28:30 +00:00
|
|
|
__stdcall
|
2011-01-11 19:09:48 +00:00
|
|
|
#else
|
2013-09-14 10:28:30 +00:00
|
|
|
__cdecl
|
2011-01-11 19:09:48 +00:00
|
|
|
#endif
|
2011-01-03 01:07:54 +00:00
|
|
|
_sxprintf(
|
|
|
|
TCHAR *buffer,
|
2013-03-16 13:40:28 +00:00
|
|
|
#if IS_SECAPI
|
|
|
|
size_t sizeOfBuffer,
|
|
|
|
#endif
|
2011-01-03 01:07:54 +00:00
|
|
|
#if USE_COUNT
|
|
|
|
size_t count,
|
|
|
|
#endif
|
|
|
|
const TCHAR *format,
|
|
|
|
#if USE_VARARGS
|
|
|
|
va_list argptr)
|
|
|
|
#else
|
|
|
|
...)
|
|
|
|
#endif
|
|
|
|
{
|
2013-03-16 13:40:28 +00:00
|
|
|
#if !USE_COUNT
|
|
|
|
const size_t count = INT_MAX;
|
|
|
|
#endif
|
|
|
|
#if !IS_SECAPI
|
|
|
|
const size_t sizeOfBuffer = count;
|
|
|
|
#endif
|
2011-01-03 01:07:54 +00:00
|
|
|
#if !USE_VARARGS
|
|
|
|
va_list argptr;
|
|
|
|
#endif
|
|
|
|
int result;
|
|
|
|
FILE stream;
|
|
|
|
|
2013-03-16 13:40:28 +00:00
|
|
|
#if IS_SECAPI
|
|
|
|
/* Validate parameters */
|
|
|
|
if (MSVCRT_CHECK_PMT(((buffer == NULL) || (format == NULL) || (sizeOfBuffer <= 0))))
|
|
|
|
{
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Limit output to count + 1 characters */
|
|
|
|
if (count != -1)
|
|
|
|
sizeOfBuffer = min(sizeOfBuffer, count + 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Setup the FILE structure */
|
2011-01-03 01:07:54 +00:00
|
|
|
stream._base = (char*)buffer;
|
|
|
|
stream._ptr = stream._base;
|
|
|
|
stream._charbuf = 0;
|
2013-03-16 13:40:28 +00:00
|
|
|
stream._cnt = (int)(sizeOfBuffer * sizeof(TCHAR));
|
2011-01-03 01:07:54 +00:00
|
|
|
stream._bufsiz = 0;
|
|
|
|
stream._flag = _IOSTRG | _IOWRT;
|
|
|
|
stream._tmpfname = 0;
|
|
|
|
|
|
|
|
#if !USE_VARARGS
|
|
|
|
va_start(argptr, format);
|
|
|
|
#endif
|
|
|
|
result = _tstreamout(&stream, format, argptr);
|
|
|
|
#if !USE_VARARGS
|
|
|
|
va_end(argptr);
|
|
|
|
#endif
|
|
|
|
|
2013-03-16 13:40:28 +00:00
|
|
|
#if IS_SECAPI
|
|
|
|
/* Check for failure or unterminated string */
|
|
|
|
if ((result < 0) || (result == sizeOfBuffer))
|
|
|
|
{
|
|
|
|
/* Null-terminate the buffer at the end */
|
|
|
|
buffer[sizeOfBuffer-1] = _T('\0');
|
|
|
|
|
|
|
|
/* Check if we can truncate */
|
|
|
|
if (count != _TRUNCATE)
|
|
|
|
{
|
|
|
|
/* We can't, invoke invalid parameter handler */
|
2014-05-10 20:38:26 +00:00
|
|
|
MSVCRT_INVALID_PMT("Buffer is too small", ERANGE);
|
2013-03-16 13:40:28 +00:00
|
|
|
|
|
|
|
/* If we came back, set the buffer to an empty string */
|
|
|
|
*buffer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return failure */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Null-terminate the buffer after the string */
|
|
|
|
buffer[result] = _T('\0');
|
|
|
|
#else
|
2011-01-03 01:07:54 +00:00
|
|
|
/* Only zero terminate if there is enough space left */
|
2014-09-07 10:34:17 +00:00
|
|
|
if ((stream._cnt >= sizeof(TCHAR)) && (stream._ptr))
|
|
|
|
*(TCHAR*)stream._ptr = _T('\0');
|
2013-03-16 13:40:28 +00:00
|
|
|
#endif
|
2011-01-03 01:07:54 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|