RtlUnicodeStringCbCatN - NtDoc

Native API online documentation, based on the System Informer (formerly Process Hacker) phnt headers
#ifndef _NTSTRSAFE_H_INCLUDED_
#ifndef NTSTRSAFE_LIB_IMPL
#ifndef NTSTRSAFE_NO_UNICODE_STRING_FUNCTIONS
#ifndef NTSTRSAFE_NO_CB_FUNCTIONS

/*++

  NTSTATUS
  RtlUnicodeStringCbCatN(
  _Inout_ PUNICODE_STRING     DestinationString,
  _In_    PCUNICODE_STRING    SourceString,
  _In_    size_t              cbToAppend
  );

  Routine Description:

  This routine is a safer version of the C built-in function 'strncat' for
  PUNICODE_STRINGs.

  This function returns an NTSTATUS value, and not a pointer. It returns
  STATUS_SUCCESS if all of SourceString or the first cbToAppend bytes were
  appended to the destination string, otherwise it will return a failure
  code. In failure cases as much of SourceString will be appended to DestinationString as
  possible.

Arguments:

DestinationString   -   pointer to the counted unicode destination string

SourceString        -   pointer to the counted unicode source string

cbToAppend          -   maximum number of bytes to append

Notes:
Behavior is undefined if source and destination strings overlap.

DestinationString and SourceString should not be NULL. See RtlUnicodeStringCbCatNEx if
you require the handling of NULL values.

Return Value:

STATUS_SUCCESS -   if all of SourceString or the first cbToAppend bytes were
concatenated to pszDest

failure        -   the operation did not succeed

STATUS_BUFFER_OVERFLOW
Note: This status has the severity class Warning - IRPs completed with this
status do have their data copied back to user mode
-   this return value is an indication that the
operation failed due to insufficient space. When this
error occurs, the destination buffer is modified to
contain a truncated version of the ideal result. This is
useful for situations where truncation is ok

It is strongly recommended to use the NT_SUCCESS() macro to test the
return value of this function

--*/

NTSTRSAFEDDI
RtlUnicodeStringCbCatN(
        _Inout_ PUNICODE_STRING DestinationString,
        _In_ PCUNICODE_STRING SourceString,
        _In_ size_t cbToAppend)
{
    NTSTATUS status;
    wchar_t* pszDest;
    size_t cchDest;
    size_t cchDestLength;

    status = RtlUnicodeStringValidateDestWorker(DestinationString,
            &pszDest,
            &cchDest,
            &cchDestLength,
            NTSTRSAFE_UNICODE_STRING_MAX_CCH,
            0);

    if (NT_SUCCESS(status))
    {
        wchar_t* pszSrc;
        size_t cchSrcLength;

        status = RtlUnicodeStringValidateSrcWorker(SourceString,
                &pszSrc,
                &cchSrcLength,
                NTSTRSAFE_UNICODE_STRING_MAX_CCH,
                0);

        if (NT_SUCCESS(status))
        {
            size_t cchToAppend = cbToAppend / sizeof(wchar_t);

            if (cchToAppend > NTSTRSAFE_UNICODE_STRING_MAX_CCH)
            {
                status = STATUS_INVALID_PARAMETER;
            }
            else
            {
                size_t cchCopied = 0;

                if (cchSrcLength < cchToAppend)
                {
                    cchToAppend = cchSrcLength;
                }

                status = RtlWideCharArrayCopyWorker(pszDest + cchDestLength,
                        cchDest - cchDestLength,
                        &cchCopied,
                        pszSrc,
                        cchToAppend);

                // safe to multiply (cchDestLength + cchCopied) * sizeof(wchar_t) since (cchDestLength + cchCopied) < NTSTRSAFE_UNICODE_STRING_MAX_CCH and sizeof(wchar_t) is 2
                DestinationString->Length = (USHORT)((cchDestLength + cchCopied) * sizeof(wchar_t));
            }
        }
    }

    return status;
}

#endif
#endif
#endif
#endif

View code on GitHub

No description available.