|
|
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" { #endif
#ifndef DIMA
#define DIMAT(Array, EltType) (sizeof(Array) / sizeof(EltType))
#define DIMA(Array) DIMAT(Array, (Array)[0])
#endif
BOOL CopyNString(PSTR To, PCSTR From, ULONG FromChars, ULONG ToChars); BOOL CatNString(PSTR To, PCSTR From, ULONG FromChars, ULONG ToChars);
#ifndef COPYSTR_NO_PRINTSTRING
BOOL __cdecl PrintString(PSTR To, ULONG ToChars, PCSTR Format, ...); #endif
#define CopyString(To, From, ToChars) CopyNString(To, From, (ULONG)-1, ToChars)
#define CatString(To, From, ToChars) CatNString(To, From, (ULONG)-1, ToChars)
#define CopyNStrArray(To, From, FromChars) CopyNString(To, From, FromChars, DIMA(To))
#define CopyStrArray(To, From) CopyString(To, From, DIMA(To))
#define CatStrArray(To, From) CatString(To, From, DIMA(To))
#ifndef COPYSTR_NO_WCHAR
BOOL CopyNStringW(PWSTR To, PCWSTR From, ULONG FromChars, ULONG ToChars); BOOL CatNStringW(PWSTR To, PCWSTR From, ULONG FromChars, ULONG ToChars);
#ifndef COPYSTR_NO_PRINTSTRING
BOOL __cdecl PrintStringW(PWSTR To, ULONG ToChars, PCWSTR Format, ...); #endif
#define CopyStringW(To, From, ToChars) CopyNStringW(To, From, (ULONG)-1, ToChars)
#define CatStringW(To, From, ToChars) CatNStringW(To, From, (ULONG)-1, ToChars)
#define CopyNStrArrayW(To, From, FromChars) CopyNStringW(To, From, FromChars, DIMA(To))
#define CopyStrArrayW(To, From) CopyStringW(To, From, DIMA(To))
#define CatStrArrayW(To, From) CatStringW(To, From, DIMA(To))
#endif // #ifndef COPYSTR_NO_WCHAR
#ifdef COPYSTR_MOD
BOOL CopyNString(PSTR To, PCSTR From, ULONG FromChars, ULONG ToChars) { //
// The CRT str'n'cpy doesn't guarantee termination of the
// resulting string, so define a new function that does.
// Returns TRUE for a full copy with terminator.
//
if (ToChars == 0) { return FALSE; }
BOOL Succ = TRUE; ULONG Len = strlen(From);
if (FromChars == (ULONG)-1) { // This is a regular strcpy. Don't fool with the length.
} else if (FromChars > Len) { // The source string is smaller than the amount of characters
// we were asked to copy. Do it anyway, but return FALSE;
Succ = FALSE; } else { // Set amount of characters to copy as in a normal strncpy.
Len = FromChars; }
if (Len >= ToChars) { Len = ToChars - 1; Succ = FALSE; }
memcpy(To, From, Len); To[Len] = 0;
return Succ; }
BOOL CatNString(PSTR To, PCSTR From, ULONG FromChars, ULONG ToChars) { //
// The CRT str'n'cat works with the number of characters to
// append, which is usually inconvenient when filling
// fixed-length buffers as you need to make sure to
// subtract off the size of any existing content to
// prevent buffer overflows. Define a new function that
// works with the absolute buffer size.
// Returns TRUE for a full copy with terminator.
//
if (ToChars == 0) { return FALSE; }
ULONG ToLen = strlen(To);
if (ToLen >= ToChars) { ULONG i;
// To string is garbage. Copy in a special
// marker string.
if (ToChars > 8) { ToChars = 8; } for (i = 0; i < ToChars - 1; i++) { To[i] = 'G'; } To[i] = 0; return FALSE; }
ToChars -= ToLen;
BOOL Succ = TRUE; ULONG FromLen = strlen(From);
if (FromChars != (ULONG)-1) { FromLen = min(FromLen, FromChars); } if (FromLen >= ToChars) { FromLen = ToChars - 1; Succ = FALSE; }
memcpy(To + ToLen, From, FromLen); To[ToLen + FromLen] = 0;
return Succ; }
#ifndef COPYSTR_NO_PRINTSTRING
BOOL __cdecl PrintString(PSTR To, ULONG ToChars, PCSTR Format, ...) { va_list Args; int PrintChars;
//
// _snprintf leaves strings unterminated on overflow.
// This wrapper guarantees termination.
//
if (ToChars == 0) { return FALSE; }
va_start(Args, Format); PrintChars = _vsnprintf(To, ToChars, Format, Args); if (PrintChars < 0 || PrintChars == ToChars) { va_end(Args); // Overflow, force termination.
To[ToChars - 1] = 0; return FALSE; } else { va_end(Args); return TRUE; } }
#endif // #ifndef COPYSTR_NO_PRINTSTRING
#ifndef COPYSTR_NO_WCHAR
BOOL CopyNStringW(PWSTR To, PCWSTR From, ULONG FromChars, ULONG ToChars) { //
// The CRT str'n'cpy doesn't guarantee termination of the
// resulting string, so define a new function that does.
// Returns TRUE for a full copy with terminator.
//
if (ToChars == 0) { return FALSE; }
BOOL Succ = TRUE; ULONG Len = wcslen(From);
if (FromChars == (ULONG)-1) { // This is a regular strcpy. Don't fool with the length.
} else if (FromChars > Len) { // The source string is smaller than the amount of characters
// we were asked to copy. Do it anyway, but return FALSE;
Succ = FALSE; } else { // Set amount of characters to copy as in a normal strncpy.
Len = FromChars; }
if (Len >= ToChars) { Len = ToChars - 1; Succ = FALSE; }
memcpy(To, From, Len * sizeof(WCHAR)); To[Len] = 0;
return Succ; }
BOOL CatNStringW(PWSTR To, PCWSTR From, ULONG FromChars, ULONG ToChars) { //
// The CRT str'n'cat works with the number of characters to
// append, which is usually inconvenient when filling
// fixed-length buffers as you need to make sure to
// subtract off the size of any existing content to
// prevent buffer overflows. Define a new function that
// works with the absolute buffer size.
// Returns TRUE for a full copy with terminator.
//
if (ToChars == 0) { return FALSE; }
ULONG ToLen = wcslen(To);
if (ToLen >= ToChars) { ULONG i;
// To string is garbage. Copy in a special
// marker string.
if (ToChars > 8) { ToChars = 8; } for (i = 0; i < ToChars - 1; i++) { To[i] = L'G'; } To[i] = 0; return FALSE; }
ToChars -= ToLen;
BOOL Succ = TRUE; ULONG FromLen = wcslen(From);
if (FromChars != (ULONG)-1) { FromLen = min(FromLen, FromChars); } if (FromLen >= ToChars) { FromLen = ToChars - 1; Succ = FALSE; }
memcpy(To + ToLen, From, FromLen * sizeof(WCHAR)); To[ToLen + FromLen] = 0;
return Succ; }
#ifndef COPYSTR_NO_PRINTSTRING
BOOL __cdecl PrintStringW(PWSTR To, ULONG ToChars, PCWSTR Format, ...) { va_list Args; int PrintChars;
//
// _snprintf leaves strings unterminated on overflow.
// This wrapper guarantees termination.
//
if (ToChars == 0) { return FALSE; }
va_start(Args, Format); PrintChars = _vsnwprintf(To, ToChars, Format, Args); if (PrintChars < 0 || PrintChars == ToChars) { va_end(Args); // Overflow, force termination.
To[ToChars - 1] = 0; return FALSE; } else { va_end(Args); return TRUE; } }
#endif // #ifndef COPYSTR_NO_PRINTSTRING
#endif // #ifndef COPYSTR_NO_WCHAR
#endif // #ifdef COPYSTR_MOD
#ifdef __cplusplus
} #endif
|