RtlUnicodeStringCchCatNEx - 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_CCH_FUNCTIONS

NTSTRSAFEDDI
RtlUnicodeStringCchCatNEx(
        _Inout_   PUNICODE_STRING  DestinationString,
        _In_      PCUNICODE_STRING SourceString,
        _In_      size_t           cchToAppend,
        _Out_opt_ PUNICODE_STRING  RemainingString,
        _In_      DWORD            dwFlags)
{
    NTSTATUS status;
    wchar_t* pszDest;
    size_t cchDest;
    size_t cchDestLength;

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

    if (NT_SUCCESS(status))
    {
        wchar_t* pszSrc;
        size_t cchSrcLength;
        wchar_t* pszDestEnd = pszDest + cchDestLength;
        size_t cchRemaining = cchDest - cchDestLength;
        size_t cchNewDestLength = cchDestLength;

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

        if (NT_SUCCESS(status))
        {
            if (cchToAppend > NTSTRSAFE_UNICODE_STRING_MAX_CCH)
            {
                status = STATUS_INVALID_PARAMETER;
            }
            else
            {
                if (cchSrcLength < cchToAppend)
                {
                    cchToAppend = cchSrcLength;
                }

                if (dwFlags & (~STRSAFE_UNICODE_STRING_VALID_FLAGS))
                {
                    status = STATUS_INVALID_PARAMETER;
                }
                else if (cchRemaining == 0)
                {
                    // only fail if there was actually src data to append
                    if (cchToAppend != 0)
                    {
                        if (pszDest == NULL)
                        {
                            status = STATUS_INVALID_PARAMETER;
                        }
                        else
                        {
                            status = STATUS_BUFFER_OVERFLOW;
                        }
                    }
                }
                else
                {
                    size_t cchCopied = 0;

                    status = RtlWideCharArrayCopyStringWorker(pszDestEnd,
                            cchRemaining,
                            &cchCopied,
                            pszSrc,
                            cchToAppend);

                    pszDestEnd = pszDestEnd + cchCopied;
                    cchRemaining = cchRemaining - cchCopied;

                    cchNewDestLength = cchDestLength + cchCopied;

                    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,
                    cchDestLength,
                    &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;
}

#endif
#endif
#endif
#endif

View code on GitHub

No description available.