#ifndef _NTSTRSAFE_H_INCLUDED_
#ifndef NTSTRSAFE_LIB_IMPL
#ifndef NTSTRSAFE_NO_UNICODE_STRING_FUNCTIONS
#ifndef NTSTRSAFE_NO_CB_FUNCTIONS
NTSTRSAFEDDI
RtlUnicodeStringCbCopyStringNEx(
_Inout_ PUNICODE_STRING DestinationString,
_In_ NTSTRSAFE_PCWSTR pszSrc,
_In_ size_t cbToCopy,
_Out_opt_ PUNICODE_STRING RemainingString,
_In_ DWORD dwFlags)
{
NTSTATUS status;
wchar_t* pszDest;
size_t cchDest;
status = RtlUnicodeStringValidateDestWorker(DestinationString,
&pszDest,
&cchDest,
NULL,
NTSTRSAFE_UNICODE_STRING_MAX_CCH,
dwFlags);
if (NT_SUCCESS(status))
{
wchar_t* pszDestEnd = pszDest;
size_t cchRemaining = cchDest;
size_t cchNewDestLength = 0;
size_t cchToCopy = cbToCopy / sizeof(wchar_t);
status = RtlStringExValidateSrcW(&pszSrc, &cchToCopy, NTSTRSAFE_UNICODE_STRING_MAX_CCH, dwFlags);
if (NT_SUCCESS(status))
{
if (dwFlags & (~STRSAFE_UNICODE_STRING_VALID_FLAGS))
{
status = STATUS_INVALID_PARAMETER;
}
else if (cchDest == 0)
{
// only fail if there was actually src data to copy
if ((cchToCopy != 0) && (*pszSrc != L'\0'))
{
if (pszDest == NULL)
{
status = STATUS_INVALID_PARAMETER;
}
else
{
status = STATUS_BUFFER_OVERFLOW;
}
}
}
else
{
status = RtlWideCharArrayCopyStringWorker(pszDest,
cchDest,
&cchNewDestLength,
pszSrc,
cchToCopy);
pszDestEnd = pszDest + cchNewDestLength;
cchRemaining = cchDest - cchNewDestLength;
if (NT_SUCCESS(status) &&
(dwFlags & STRSAFE_FILL_BEHIND) &&
(cchRemaining != 0))
{
// handle the STRSAFE_FILL_BEHIND flag
RtlUnicodeStringExHandleFill(pszDestEnd, cchRemaining, dwFlags);
}
}
}
if (!NT_SUCCESS(status) &&
(dwFlags & (STRSAFE_NO_TRUNCATION | STRSAFE_FILL_ON_FAILURE | STRSAFE_ZERO_LENGTH_ON_FAILURE)) &&
(cchDest != 0))
{
// handle the STRSAFE_NO_TRUNCATION, STRSAFE_FILL_ON_FAILURE, and STRSAFE_ZERO_LENGTH_ON_FAILURE flags
RtlUnicodeStringExHandleOtherFlags(pszDest,
cchDest,
0,
&cchNewDestLength,
&pszDestEnd,
&cchRemaining,
dwFlags);
}
if (DestinationString)
{
// safe to multiply cchNewDestLength * sizeof(wchar_t) since cchDest < NTSTRSAFE_UNICODE_STRING_MAX_CCH and sizeof(wchar_t) is 2
DestinationString->Length = (USHORT)(cchNewDestLength * sizeof(wchar_t));
}
if (NT_SUCCESS(status) || (status == STATUS_BUFFER_OVERFLOW))
{
if (RemainingString)
{
RemainingString->Length = 0;
// safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < NTSTRSAFE_UNICODE_STRING_MAX_CCH and sizeof(wchar_t) is 2
RemainingString->MaximumLength = (USHORT)(cchRemaining * sizeof(wchar_t));
RemainingString->Buffer = pszDestEnd;
}
}
}
return status;
}
View code on GitHub
No description available.