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

NTSTRSAFEDDI
    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_ DWORD dwFlags)
{
    NTSTATUS status;

    status = RtlStringExValidateDestW(pszDest, cchDest, NTSTRSAFE_MAX_CCH, dwFlags);

    if (NT_SUCCESS(status))
    {
        NTSTRSAFE_PWSTR pszDestEnd = pszDest;
        size_t cchRemaining = cchDest;

        status = RtlStringExValidateSrcW(&pszSrc, NULL, NTSTRSAFE_MAX_CCH, dwFlags);

        if (NT_SUCCESS(status))
        {
            if (dwFlags & (~STRSAFE_VALID_FLAGS))
            {
                status = STATUS_INVALID_PARAMETER;

                if (cchDest != 0)
                {
                    *pszDest = L'\0';
                }
            }
            else if (cchDest == 0)
            {
                // only fail if there was actually src data to copy
                if (*pszSrc != L'\0')
                {
                    if (pszDest == NULL)
                    {
                        status = STATUS_INVALID_PARAMETER;
                    }
                    else
                    {
                        status = STATUS_BUFFER_OVERFLOW;
                    }
                }
            }
            else
            {
                size_t cchCopied = 0;

                status = RtlStringCopyWorkerW(pszDest,
                        cchDest,
                        &cchCopied,
                        pszSrc,
                        NTSTRSAFE_MAX_LENGTH);

                pszDestEnd = pszDest + cchCopied;
                cchRemaining = cchDest - cchCopied;

                if (NT_SUCCESS(status)                           &&
                        (dwFlags & STRSAFE_FILL_BEHIND_NULL)    &&
                        (cchRemaining > 1))
                {
                    size_t cbRemaining;

                    // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < NTSTRSAFE_MAX_CCH and sizeof(wchar_t) is 2
                    cbRemaining = cchRemaining * sizeof(wchar_t);

                    // handle the STRSAFE_FILL_BEHIND_NULL flag
                    RtlStringExHandleFillBehindNullW(pszDestEnd, cbRemaining, dwFlags);
                }
            }
        }
        else
        {
            if (cchDest != 0)
            {
                *pszDest = L'\0';
            }
        }

        if (!NT_SUCCESS(status)                                                                              &&
                (dwFlags & (STRSAFE_NO_TRUNCATION | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)) &&
                (cchDest != 0))
        {
            size_t cbDest;

            // safe to multiply cchDest * sizeof(wchar_t) since cchDest < NTSTRSAFE_MAX_CCH and sizeof(wchar_t) is 2
            cbDest = cchDest * sizeof(wchar_t);

            // handle the STRSAFE_FILL_ON_FAILURE, STRSAFE_NULL_ON_FAILURE, and STRSAFE_NO_TRUNCATION flags
            RtlStringExHandleOtherFlagsW(pszDest,
                    cbDest,
                    0,
                    &pszDestEnd,
                    &cchRemaining,
                    dwFlags);
        }

        if (NT_SUCCESS(status) || (status == STATUS_BUFFER_OVERFLOW))
        {
            if (ppszDestEnd)
            {
                *ppszDestEnd = pszDestEnd;
            }

            if (pcchRemaining)
            {
                *pcchRemaining = cchRemaining;
            }
        }
    }
    else if (cchDest > 0)
    {
        *pszDest = L'\0';
    }

    return status;
}

#endif
#endif
#endif

View code on GitHub

No description available.