mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
3342 lines
94 KiB
C
3342 lines
94 KiB
C
/**
|
|
* This file has no copyright assigned and is placed in the Public Domain.
|
|
* This file is part of the w64 mingw-runtime package.
|
|
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
|
|
*/
|
|
#ifndef _NTSTRSAFE_H_INCLUDED_
|
|
#define _NTSTRSAFE_H_INCLUDED_
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(push)
|
|
#pragma warning(disable:28719) /* disable banned api usage warning */
|
|
#endif /* _MSC_VER */
|
|
|
|
#define NTSTRSAFEAPI static __inline NTSTATUS NTAPI
|
|
#define NTSTRSAFEVAPI static __inline NTSTATUS __cdecl
|
|
#define NTSTRSAFE_INLINE_API static __inline NTSTATUS NTAPI
|
|
|
|
#ifndef NTSTRSAFE_MAX_CCH
|
|
#define NTSTRSAFE_MAX_CCH 2147483647
|
|
#endif
|
|
|
|
#ifndef NTSTRSAFE_UNICODE_STRING_MAX_CCH
|
|
#define NTSTRSAFE_UNICODE_STRING_MAX_CCH 32767
|
|
#endif
|
|
|
|
#ifndef _STRSAFE_H_INCLUDED_
|
|
#define STRSAFE_IGNORE_NULLS 0x00000100
|
|
#define STRSAFE_FILL_BEHIND_NULL 0x00000200
|
|
#define STRSAFE_FILL_ON_FAILURE 0x00000400
|
|
#define STRSAFE_NULL_ON_FAILURE 0x00000800
|
|
#define STRSAFE_NO_TRUNCATION 0x00001000
|
|
#define STRSAFE_IGNORE_NULL_UNICODE_STRINGS 0x00010000
|
|
#define STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED 0x00020000
|
|
|
|
#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
|
|
#define STRSAFE_UNICODE_STRING_VALID_FLAGS (STRSAFE_VALID_FLAGS | STRSAFE_IGNORE_NULL_UNICODE_STRINGS | STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED)
|
|
|
|
#define STRSAFE_FILL_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
|
|
#define STRSAFE_FAILURE_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
|
|
|
|
#define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)((dwFlags) & 0x000000FF))
|
|
#endif
|
|
|
|
#define STRSAFE_FILL_BEHIND STRSAFE_FILL_BEHIND_NULL
|
|
#define STRSAFE_ZERO_LENGTH_ON_FAILURE STRSAFE_NULL_ON_FAILURE
|
|
|
|
typedef char *STRSAFE_LPSTR;
|
|
typedef const char *STRSAFE_LPCSTR;
|
|
typedef wchar_t *STRSAFE_LPWSTR;
|
|
typedef const wchar_t *STRSAFE_LPCWSTR;
|
|
|
|
typedef _Null_terminated_ char *NTSTRSAFE_PSTR;
|
|
typedef _Null_terminated_ const char *NTSTRSAFE_PCSTR;
|
|
typedef _Null_terminated_ wchar_t *NTSTRSAFE_PWSTR;
|
|
typedef _Null_terminated_ const wchar_t *NTSTRSAFE_PCWSTR;
|
|
|
|
typedef ULONG STRSAFE_DWORD;
|
|
|
|
NTSTRSAFEAPI RtlStringCopyWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc);
|
|
NTSTRSAFEAPI RtlStringCopyWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc);
|
|
NTSTRSAFEAPI RtlStringCopyExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCopyExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCopyNWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy);
|
|
NTSTRSAFEAPI RtlStringCopyNWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy);
|
|
NTSTRSAFEAPI RtlStringCopyNExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCopyNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCatWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc);
|
|
NTSTRSAFEAPI RtlStringCatWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc);
|
|
NTSTRSAFEAPI RtlStringCatExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCatExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCatNWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToAppend);
|
|
NTSTRSAFEAPI RtlStringCatNWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend);
|
|
NTSTRSAFEAPI RtlStringCatNExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCSTR pszSrc, size_t cchToAppend, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cchToAppend, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags);
|
|
NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat, va_list argList);
|
|
NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCSTR pszFormat, va_list argList);
|
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest, size_t cchDest, size_t cbDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat, va_list argList);
|
|
NTSTRSAFEAPI RtlUnicodeStringValidate(PCUNICODE_STRING SourceString);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringLengthWorkerA(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringLengthWorkerW(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyWorkerA(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyWorkerW(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(char);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
return RtlStringCopyWorkerA(pszDest, cbDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
return RtlStringCopyWorkerW(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyExWorkerA(pszDest, cchDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
size_t cbDest = cchDest * sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyExA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyExW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyExA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest = cbDest / sizeof(char);
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = RtlStringCopyExWorkerA(pszDest, cbDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
|
|
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
if (pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyExW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = RtlStringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToCopy);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToCopy);
|
|
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToCopy)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNWorkerA(pszDest, cchDest, pszSrc, cchToCopy);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToCopy)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNWorkerW(pszDest, cchDest, pszSrc, cchToCopy);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNA(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToCopy);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToCopy);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNA(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToCopy)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(char);
|
|
size_t cchToCopy = cbToCopy / sizeof(char);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNWorkerA(pszDest, cchDest, pszSrc, cchToCopy);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToCopy)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchToCopy = cbToCopy / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNWorkerW(pszDest, cchDest, pszSrc, cchToCopy);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToCopy,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToCopy,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToCopy,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNExWorkerA(pszDest, cchDest, cchDest, pszSrc, cchToCopy, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCopyNExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToCopy,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringCopyNExWorkerW(pszDest, cchDest, cchDest * sizeof(wchar_t), pszSrc, cchToCopy, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNExA(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToCopy,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNExW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToCopy,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNExA(
|
|
_Out_writes_bytes_(cbDest) STRSAFE_LPSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToCopy,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) STRSAFE_LPSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if ((pszDest != NULL) && (cbDest > 0))
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = RtlStringCopyNExWorkerA(pszDest, cbDest, cbDest, pszSrc, cbToCopy, ppszDestEnd, &cchRemaining, dwFlags);
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = cchRemaining;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCopyNExW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToCopy,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchToCopy = cbToCopy / sizeof(wchar_t);
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if ((pszDest != NULL) && (cbDest > 0))
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = RtlStringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchToCopy, ppszDestEnd, &cchRemaining, dwFlags);
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatWorkerA(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatWorkerW(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc)
|
|
{
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
return RtlStringCatWorkerA(pszDest, cbDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatWorkerW(pszDest, cchDest, pszSrc);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatExA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatExW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatExA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatExWorkerA(pszDest, cchDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatExW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
size_t cbDest = cchDest * sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatExA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatExW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatExA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringCatExWorkerA(pszDest, cbDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
|
|
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatExW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ NTSTRSAFE_PCWSTR pszSrc,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags);
|
|
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToAppend);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToAppend);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToAppend)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNWorkerA(pszDest, cchDest, pszSrc, cchToAppend);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToAppend)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNWorkerW(pszDest, cchDest, pszSrc, cchToAppend);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToAppend);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToAppend);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToAppend)
|
|
{
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNWorkerA(pszDest, cbDest, pszSrc, cbToAppend);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToAppend)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchToAppend = cbToAppend / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNWorkerW(pszDest, cchDest, pszSrc, cchToAppend);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNExA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToAppend,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNExW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToAppend,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNExA(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cchToAppend,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNExWorkerA(pszDest, cchDest, cchDest, pszSrc, cchToAppend, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchCatNExW(
|
|
_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_reads_or_z_(cchToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cchToAppend,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlStringCatNExWorkerW(pszDest, cchDest, (cchDest * sizeof(wchar_t)), pszSrc, cchToAppend, ppszDestEnd, pcchRemaining, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNExA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToAppend,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNExW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToAppend,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNExA(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCSTR pszSrc,
|
|
_In_ size_t cbToAppend,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringCatNExWorkerA(pszDest, cbDest, cbDest, pszSrc, cbToAppend, ppszDestEnd, &cchRemaining, dwFlags);
|
|
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbCatNExW(
|
|
_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_reads_bytes_(cbToAppend) STRSAFE_LPCWSTR pszSrc,
|
|
_In_ size_t cbToAppend,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
size_t cchToAppend = cbToAppend / sizeof(wchar_t);
|
|
size_t cchRemaining = 0;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchToAppend, ppszDestEnd, &cchRemaining, dwFlags);
|
|
|
|
if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cbDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringVPrintfWorkerA(pszDest, cbDest, pszFormat, argList);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
va_list argList;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfWorkerA(pszDest, cchDest, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
va_list argList;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
va_list argList;
|
|
|
|
if (cbDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cbDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfWorkerA(pszDest, cbDest, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
va_list argList;
|
|
size_t cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfWorkerW(pszDest, cchDest, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
va_list argList;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cchDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCchPrintfExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cbDest = cchDest * sizeof(wchar_t);
|
|
va_list argList;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
|
|
va_end(argList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfExA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfExW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...);
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfExA(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
cchDest = cbDest / sizeof(char);
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
{
|
|
va_list argList;
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
|
|
va_end(argList);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (pcbRemaining)
|
|
{
|
|
*pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlStringCbPrintfExW(
|
|
_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest;
|
|
size_t cchRemaining = 0;
|
|
cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
{
|
|
va_list argList;
|
|
va_start(argList, pszFormat);
|
|
Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
|
|
va_end(argList);
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (pcbRemaining)
|
|
{
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfExA(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = '\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
{
|
|
size_t cbDest;
|
|
cbDest = cchDest * sizeof(char);
|
|
Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCchVPrintfExW(
|
|
_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cchDest,
|
|
_Outptr_opt_result_buffer_(*pcchRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcchRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
if (cchDest > 0)
|
|
*pszDest = L'\0';
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
{
|
|
size_t cbDest;
|
|
cbDest = cchDest * sizeof(wchar_t);
|
|
Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfExA(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfExW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList);
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfExA(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest;
|
|
size_t cchRemaining = 0;
|
|
cchDest = cbDest / sizeof(char);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (pcbRemaining)
|
|
{
|
|
*pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringCbVPrintfExW(
|
|
_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest,
|
|
_In_ size_t cbDest,
|
|
_Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd,
|
|
_Out_opt_ size_t *pcbRemaining,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,
|
|
_In_ va_list argList)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchDest;
|
|
size_t cchRemaining = 0;
|
|
cchDest = cbDest / sizeof(wchar_t);
|
|
|
|
if (cchDest > NTSTRSAFE_MAX_CCH)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, &cchRemaining, dwFlags, pszFormat, argList);
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (pcbRemaining)
|
|
{
|
|
*pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCchLengthA(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength);
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCchLengthW(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength);
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCchLengthA(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringLengthWorkerA(psz, cchMax, pcchLength);
|
|
|
|
if (!NT_SUCCESS(Status) && pcchLength)
|
|
{
|
|
*pcchLength = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCchLengthW(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(< , cchMax) _Deref_out_range_(<= , _String_length_(psz)) size_t *pcchLength)
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringLengthWorkerW(psz, cchMax, pcchLength);
|
|
|
|
if (!NT_SUCCESS(Status) && pcchLength)
|
|
{
|
|
*pcchLength = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCbLengthA(
|
|
_In_reads_or_z_(cbMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(char)) size_t cbMax,
|
|
_Out_opt_ _Deref_out_range_(< , cbMax) size_t *pcbLength);
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCbLengthW(
|
|
_In_reads_or_z_(cbMax / sizeof(wchar_t)) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(wchar_t)) size_t cbMax,
|
|
_Out_opt_ _Deref_out_range_(< , cbMax - 1) size_t *pcbLength);
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCbLengthA(
|
|
_In_reads_or_z_(cbMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(char)) size_t cbMax,
|
|
_Out_opt_ _Deref_out_range_(< , cbMax) size_t *pcbLength)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchMax;
|
|
size_t cchLength = 0;
|
|
cchMax = cbMax / sizeof(char);
|
|
|
|
if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringLengthWorkerA(psz, cchMax, &cchLength);
|
|
|
|
if (pcbLength)
|
|
{
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*pcbLength = cchLength * sizeof(char);
|
|
}
|
|
else
|
|
{
|
|
*pcbLength = 0;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
_Must_inspect_result_
|
|
NTSTRSAFEAPI
|
|
RtlStringCbLengthW(
|
|
_In_reads_or_z_(cbMax / sizeof(wchar_t)) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(1, NTSTRSAFE_MAX_CCH * sizeof(wchar_t)) size_t cbMax,
|
|
_Out_opt_ _Deref_out_range_(< , cbMax - 1) size_t *pcbLength)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchMax;
|
|
size_t cchLength = 0;
|
|
cchMax = cbMax / sizeof(wchar_t);
|
|
|
|
if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = RtlStringLengthWorkerW(psz, cchMax, &cchLength);
|
|
|
|
if (pcbLength)
|
|
{
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*pcbLength = cchLength * sizeof(wchar_t);
|
|
}
|
|
else
|
|
{
|
|
*pcbLength = 0;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCSTR pszSrc)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
while (cchDest && (*pszSrc != '\0'))
|
|
{
|
|
*pszDest++ = *pszSrc++;
|
|
cchDest--;
|
|
}
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
pszDest--;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDest = '\0';
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszSrc)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
while (cchDest && (*pszSrc != L'\0'))
|
|
{
|
|
*pszDest++ = *pszSrc++;
|
|
cchDest--;
|
|
}
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
pszDest--;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDest = L'\0';
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyExWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
STRSAFE_LPSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = "";
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
|
|
if (*pszSrc != '\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
|
|
while (cchRemaining && (*pszSrc != '\0'))
|
|
{
|
|
*pszDestEnd++ = *pszSrc++;
|
|
cchRemaining--;
|
|
}
|
|
|
|
if (cchRemaining > 0)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
|
{
|
|
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd--;
|
|
cchRemaining++;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPWSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = L"";
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
|
|
if (*pszSrc != L'\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
|
|
while (cchRemaining && (*pszSrc != L'\0'))
|
|
{
|
|
*pszDestEnd++ = *pszSrc++;
|
|
cchRemaining--;
|
|
}
|
|
|
|
if (cchRemaining > 0)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
|
{
|
|
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd--;
|
|
cchRemaining++;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyNWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
size_t cchSrc)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
while (cchDest && cchSrc && (*pszSrc != '\0'))
|
|
{
|
|
*pszDest++ = *pszSrc++;
|
|
cchDest--;
|
|
cchSrc--;
|
|
}
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
pszDest--;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDest = '\0';
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyNWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
size_t cchToCopy)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
while (cchDest && cchToCopy && (*pszSrc != L'\0'))
|
|
{
|
|
*pszDest++ = *pszSrc++;
|
|
cchDest--;
|
|
cchToCopy--;
|
|
}
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
pszDest--;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDest = L'\0';
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyNExWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
size_t cchToCopy,
|
|
STRSAFE_LPSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else if (cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = "";
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
|
|
if ((cchToCopy != 0) && (*pszSrc != '\0'))
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
|
|
while (cchRemaining && cchToCopy && (*pszSrc != '\0'))
|
|
{
|
|
*pszDestEnd++ = *pszSrc++;
|
|
cchRemaining--;
|
|
cchToCopy--;
|
|
}
|
|
|
|
if (cchRemaining > 0)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
|
{
|
|
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd--;
|
|
cchRemaining++;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
|
|
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
|
{
|
|
if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCopyNExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
size_t cchToCopy,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPWSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else if (cchToCopy > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = L"";
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
|
|
if ((cchToCopy != 0) && (*pszSrc != L'\0'))
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
|
|
while (cchRemaining && cchToCopy && (*pszSrc != L'\0'))
|
|
{
|
|
*pszDestEnd++ = *pszSrc++;
|
|
cchRemaining--;
|
|
cchToCopy--;
|
|
}
|
|
|
|
if (cchRemaining > 0)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
|
{
|
|
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDestEnd--;
|
|
cchRemaining++;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
|
{
|
|
if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCSTR pszSrc)
|
|
{
|
|
size_t cchDestLength;
|
|
NTSTATUS Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
Status = RtlStringCopyWorkerA(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszSrc)
|
|
{
|
|
size_t cchDestLength;
|
|
NTSTATUS Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
Status = RtlStringCopyWorkerW(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatExWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
STRSAFE_LPSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
size_t cchDestLength;
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest == 0) && (cbDest == 0))
|
|
cchDestLength = 0;
|
|
else
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = "";
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
if (*pszSrc != '\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCopyExWorkerA(pszDestEnd, cchRemaining, (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), pszSrc, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPWSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
size_t cchDestLength;
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest == 0) && (cbDest == 0))
|
|
cchDestLength = 0;
|
|
else
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = L"";
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
if (*pszSrc != L'\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCopyExWorkerW(pszDestEnd, cchRemaining, (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), pszSrc, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatNWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
size_t cchToAppend)
|
|
{
|
|
size_t cchDestLength;
|
|
NTSTATUS Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
Status = RtlStringCopyNWorkerA(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc, cchToAppend);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatNWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
size_t cchToAppend)
|
|
{
|
|
size_t cchDestLength;
|
|
NTSTATUS Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
Status = RtlStringCopyNWorkerW(pszDest + cchDestLength, cchDest - cchDestLength, pszSrc, cchToAppend);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatNExWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCSTR pszSrc,
|
|
size_t cchToAppend,
|
|
STRSAFE_LPSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
size_t cchDestLength = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else if (cchToAppend > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest == 0) && (cbDest == 0))
|
|
cchDestLength = 0;
|
|
else
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = "";
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerA(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
if ((cchToAppend != 0) && (*pszSrc != '\0'))
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCopyNExWorkerA(pszDestEnd, cchRemaining, (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), pszSrc, cchToAppend, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringCatNExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPCWSTR pszSrc,
|
|
size_t cchToAppend,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPWSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
size_t cchDestLength = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else if (cchToAppend > NTSTRSAFE_MAX_CCH)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest == 0) && (cbDest == 0))
|
|
cchDestLength = 0;
|
|
else
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (!pszSrc)
|
|
pszSrc = L"";
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringLengthWorkerW(pszDest, cchDest, &cchDestLength);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
pszDestEnd = pszDest + cchDestLength;
|
|
cchRemaining = cchDest - cchDestLength;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
if ((cchToAppend != 0) && (*pszSrc != L'\0'))
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = RtlStringCopyNExWorkerW(pszDestEnd, cchRemaining, (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), pszSrc, cchToAppend, &pszDestEnd, &cchRemaining, dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
|
|
if ((dwFlags & STRSAFE_NULL_ON_FAILURE) && cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringVPrintfWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCSTR pszFormat,
|
|
va_list argList)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (cchDest == 0)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
size_t cchMax = cchDest - 1;
|
|
int iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
|
|
|
|
if ((iRet < 0) || (((size_t)iRet) > cchMax))
|
|
{
|
|
pszDest += cchMax;
|
|
*pszDest = '\0';
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else if (((size_t)iRet) == cchMax)
|
|
{
|
|
pszDest += cchMax;
|
|
*pszDest = '\0';
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlpArrayVPrintfWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszFormat,
|
|
size_t* pcchDestNewLen,
|
|
va_list argList)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
int iRet = _vsnwprintf(pszDest, cchDest, pszFormat, argList);
|
|
|
|
if ((iRet < 0) || (((size_t)iRet) > cchDest))
|
|
{
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
*pcchDestNewLen = cchDest;
|
|
}
|
|
else
|
|
{
|
|
*pcchDestNewLen = iRet;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlpStringVPrintfWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszFormat,
|
|
size_t* pcchDestNewLen,
|
|
va_list argList)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
size_t cchMax = cchDest - 1;
|
|
int iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList);
|
|
|
|
if ((iRet < 0) || (((size_t)iRet) > cchMax))
|
|
{
|
|
pszDest += cchMax;
|
|
*pszDest = L'\0';
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else if (((size_t)iRet) == cchMax)
|
|
{
|
|
pszDest += cchMax;
|
|
*pszDest = L'\0';
|
|
}
|
|
|
|
if (pcchDestNewLen)
|
|
*pcchDestNewLen = (iRet == -1) ? cchDest : iRet;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringVPrintfWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
STRSAFE_LPCWSTR pszFormat,
|
|
va_list argList)
|
|
{
|
|
if (cchDest == 0)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlpStringVPrintfWorkerW(pszDest, cchDest, pszFormat, NULL, argList);
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerA(
|
|
STRSAFE_LPSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags,
|
|
STRSAFE_LPCSTR pszFormat,
|
|
va_list argList)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszFormat)
|
|
pszFormat = "";
|
|
}
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
|
|
if (*pszFormat != '\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int iRet;
|
|
size_t cchMax;
|
|
cchMax = cchDest - 1;
|
|
iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList);
|
|
if ((iRet < 0) || (((size_t)iRet) > cchMax))
|
|
{
|
|
pszDestEnd = pszDest + cchMax;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
else if (((size_t)iRet) == cchMax)
|
|
{
|
|
pszDestEnd = pszDest + cchMax;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
else if (((size_t)iRet) < cchMax)
|
|
{
|
|
pszDestEnd = pszDest + iRet;
|
|
cchRemaining = cchDest - iRet;
|
|
|
|
if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
|
|
{
|
|
memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
|
|
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
|
{
|
|
if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlpStringVPrintfExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags,
|
|
STRSAFE_LPCWSTR pszFormat,
|
|
size_t* pcchDestNewLen,
|
|
va_list argList)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
STRSAFE_LPWSTR pszDestEnd = pszDest;
|
|
size_t cchRemaining = 0;
|
|
|
|
if (dwFlags & (~STRSAFE_VALID_FLAGS))
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if (dwFlags & STRSAFE_IGNORE_NULLS)
|
|
{
|
|
if (!pszDest)
|
|
{
|
|
if ((cchDest != 0) || (cbDest != 0))
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!pszFormat)
|
|
pszFormat = L"";
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (cchDest == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = 0;
|
|
if (*pszFormat != L'\0')
|
|
{
|
|
if (!pszDest)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
size_t cchDestNewLen = 0;
|
|
|
|
Status = RtlpArrayVPrintfWorkerW(pszDest, cchDest, pszFormat, &cchDestNewLen, argList);
|
|
pszDestEnd = pszDest + cchDestNewLen;
|
|
cchRemaining = cchDest - cchDestNewLen;
|
|
|
|
if (NT_SUCCESS(Status) && (dwFlags & STRSAFE_FILL_BEHIND) && cchRemaining)
|
|
{
|
|
memset(pszDestEnd, STRSAFE_GET_FILL_PATTERN(dwFlags), (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
|
|
}
|
|
|
|
if (pcchDestNewLen)
|
|
*pcchDestNewLen = cchDestNewLen;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (pszDest)
|
|
{
|
|
if (dwFlags & STRSAFE_FILL_ON_FAILURE)
|
|
{
|
|
memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest);
|
|
if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
}
|
|
else if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest + cchDest - 1;
|
|
cchRemaining = 1;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
|
|
if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
|
|
{
|
|
if (cchDest > 0)
|
|
{
|
|
pszDestEnd = pszDest;
|
|
cchRemaining = cchDest;
|
|
*pszDestEnd = L'\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_OVERFLOW))
|
|
{
|
|
if (ppszDestEnd)
|
|
*ppszDestEnd = pszDestEnd;
|
|
|
|
if (pcchRemaining)
|
|
*pcchRemaining = cchRemaining;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI RtlStringVPrintfExWorkerW(
|
|
STRSAFE_LPWSTR pszDest,
|
|
size_t cchDest,
|
|
size_t cbDest,
|
|
STRSAFE_LPWSTR *ppszDestEnd,
|
|
size_t *pcchRemaining,
|
|
STRSAFE_DWORD dwFlags,
|
|
STRSAFE_LPCWSTR pszFormat,
|
|
va_list argList)
|
|
{
|
|
return RtlpStringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, NULL, argList);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringLengthWorkerA(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCSTR psz,
|
|
_In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
size_t cchMaxPrev = cchMax;
|
|
|
|
while (cchMax && (*psz != '\0'))
|
|
{
|
|
psz++;
|
|
cchMax--;
|
|
}
|
|
|
|
if (cchMax == 0)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
if (pcchLength)
|
|
{
|
|
if (NT_SUCCESS(Status))
|
|
*pcchLength = cchMaxPrev - cchMax;
|
|
else
|
|
*pcchLength = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlStringLengthWorkerW(
|
|
_In_reads_or_z_(cchMax) STRSAFE_LPCWSTR psz,
|
|
_In_ _In_range_(<=, NTSTRSAFE_MAX_CCH) size_t cchMax,
|
|
_Out_opt_ _Deref_out_range_(<, cchMax) size_t *pcchLength)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
size_t cchMaxPrev = cchMax;
|
|
|
|
while (cchMax && (*psz != L'\0'))
|
|
{
|
|
psz++;
|
|
cchMax--;
|
|
}
|
|
|
|
if (cchMax == 0)
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
if (pcchLength)
|
|
{
|
|
if (NT_SUCCESS(Status))
|
|
*pcchLength = cchMaxPrev - cchMax;
|
|
else
|
|
*pcchLength = 0;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlpUnicodeStringValidate(
|
|
_In_opt_ PCUNICODE_STRING SourceString,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (SourceString)
|
|
{
|
|
if (SourceString->Length % sizeof(WCHAR) != 0 ||
|
|
SourceString->MaximumLength % sizeof(WCHAR) != 0 ||
|
|
SourceString->Length > SourceString->MaximumLength ||
|
|
SourceString->MaximumLength > NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR) ||
|
|
(SourceString->Buffer == NULL && (SourceString->Length != 0 || SourceString->MaximumLength != 0)))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(dwFlags & STRSAFE_IGNORE_NULLS))
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlUnicodeStringValidate(_In_opt_ PCUNICODE_STRING SourceString)
|
|
{
|
|
return RtlpUnicodeStringValidate(SourceString, 0);
|
|
}
|
|
|
|
NTSTRSAFEAPI
|
|
RtlUnicodeStringValidateEx(
|
|
_In_opt_ PCUNICODE_STRING SourceString,
|
|
_In_ STRSAFE_DWORD dwFlags)
|
|
{
|
|
if (dwFlags & ~(STRSAFE_UNICODE_STRING_VALID_FLAGS))
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return RtlpUnicodeStringValidate(SourceString, dwFlags);
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlUnicodeStringPrintf(
|
|
_In_ PUNICODE_STRING DestinationString,
|
|
_In_ NTSTRSAFE_PCWSTR pszFormat,
|
|
...)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchFinalLength;
|
|
va_list argList;
|
|
|
|
if (DestinationString == NULL || pszFormat == NULL)
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
Status = RtlUnicodeStringValidate(DestinationString);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
va_start(argList, pszFormat);
|
|
|
|
Status = RtlpArrayVPrintfWorkerW(DestinationString->Buffer,
|
|
DestinationString->MaximumLength / sizeof(WCHAR),
|
|
pszFormat,
|
|
&cchFinalLength,
|
|
argList);
|
|
|
|
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
DestinationString->Length = (USHORT)(cchFinalLength * sizeof(WCHAR));
|
|
}
|
|
|
|
va_end(argList);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTRSAFEVAPI
|
|
RtlUnicodeStringPrintfEx(
|
|
_In_opt_ PUNICODE_STRING DestinationString,
|
|
_In_opt_ PUNICODE_STRING RemainingString,
|
|
_In_ STRSAFE_DWORD dwFlags,
|
|
_In_ NTSTRSAFE_PCWSTR pszFormat, ...)
|
|
{
|
|
NTSTATUS Status;
|
|
size_t cchFinalLength;
|
|
size_t cchRemaining;
|
|
va_list argList;
|
|
|
|
va_start(argList, pszFormat);
|
|
|
|
Status = RtlpStringVPrintfExWorkerW(DestinationString->Buffer,
|
|
DestinationString->MaximumLength / sizeof(WCHAR),
|
|
DestinationString->MaximumLength,
|
|
&RemainingString->Buffer,
|
|
&cchRemaining,
|
|
dwFlags,
|
|
pszFormat,
|
|
&cchFinalLength,
|
|
argList);
|
|
|
|
va_end(argList);
|
|
|
|
if (Status == STATUS_BUFFER_OVERFLOW || NT_SUCCESS(Status))
|
|
{
|
|
DestinationString->Length = (USHORT)(cchFinalLength * sizeof(WCHAR));
|
|
|
|
if (RemainingString)
|
|
{
|
|
RemainingString->Length = 0;
|
|
RemainingString->MaximumLength = (USHORT)cchRemaining * sizeof(WCHAR);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
#define RtlStringCopyWorkerA RtlStringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
|
|
#define RtlStringCopyWorkerW RtlStringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
|
|
#define RtlStringCopyExWorkerA RtlStringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
|
|
#define RtlStringCopyExWorkerW RtlStringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
|
|
#define RtlStringCatWorkerA RtlStringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
|
|
#define RtlStringCatWorkerW RtlStringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
|
|
#define RtlStringCatExWorkerA RtlStringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
|
|
#define RtlStringCatExWorkerW RtlStringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
|
|
#define RtlStringCatNWorkerA RtlStringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
|
|
#define RtlStringCatNWorkerW RtlStringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
|
|
#define RtlStringCatNExWorkerA RtlStringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
|
|
#define RtlStringCatNExWorkerW RtlStringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
|
|
#define RtlStringVPrintfWorkerA RtlStringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
|
|
#define RtlStringVPrintfWorkerW RtlStringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
|
|
#define RtlStringVPrintfExWorkerA RtlStringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
|
|
#define RtlStringVPrintfExWorkerW RtlStringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
|
|
#define RtlStringLengthWorkerA RtlStringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
|
|
#define RtlStringLengthWorkerW RtlStringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(pop)
|
|
#endif /* _MSC_VER */
|
|
|
|
#endif /* _NTSTRSAFE_H_INCLUDED_ */
|