Geoff Chappell, Software Analyst
The RtlCopyUnicodeString function sets one UNICODE_STRING structure from another, copying as much of the described string as fits.
VOID RtlCopyUnicodeString ( UNICODE_STRING *DestinationString, UNICODE_STRING const *SourceString);
The required DestinationString argument addresses the UNICODE_STRING structure that the function is to change. It is assumed to have a Buffer of MaximumLength bytes.
The optional SourceString argument is the address of a UNICODE_STRING whose contents are to be copied. It is assumed to have a Buffer that contains Length bytes. The DestinationString receives a copy of as many of these bytes as fit. This argument can be NULL to clear the DestinationString.
The RtlCopyUnicodeString function is exported by name from the kernel and from NTDLL in all known versions, i.e., 3.10 and higher.
The RtlCopyUnicodeString function is documented in all known editions of the Device Driver Kit (DDK) or Windows Driver Kit (WDK) since at least the DDK for Windows NT 3.51. Though this documentation is of the kernel-mode function as an export from the kernel, it is mostly applicable to the user-mode implementation too, both being plausibly compiled from the same source file.
Starting with the WDK for Windows 7, Microsoft documents the availability of RtlCopyUnicodeString as “Windows 2000 and later versions of Windows.”
The intention of the UNICODE_STRING structure is to keep together both the address and size of a Unicode string, presumably to save on passing them as separate arguments for subsequent work with the string and to save on repeated re-reading of the whole string to rediscover its size. Indeed, the structure keeps two sizes. The Length member is the size in bytes of the array of Unicode characters at Buffer. If this array is null-terminated, which it explicitly need not be, then Length does not count the null terminator. The MaximumLength member is the size in bytes of the memory from Buffer onwards.
The RtlCopyUnicodeString function copies from the Buffer of SourceString to the Buffer of DestinationString. It does not find new memory for the DestinationString. It copies to the destination’s existing Buffer however much will fit from the source’s Buffer, and it appends a null terminator if this too will fit. It updates the destination’s Length to match the new content.
For the special case with NULL for the SourceString, there is no content to copy and the function is trivial except for setting the destination’s Length to zero.
In all other cases, the function assumes that: the SourceString has a Buffer that is not NULL and at which there are at least Length bytes to read; and the DestinationString has a Buffer that is not NULL and which can hold MaximumLength bytes. Versions before 5.2 also assume that the destination’s MaximumLength is even.
Note that the function has no return value. It has no success or failure to signify that the copy was whole or truncated. If a caller would regard truncation as failure, then the easiest detection of truncation is to test whether Length at SourceString on output is less than Length at DestinationString.
The kernel-mode implementation is in a non-paged section in all applicable versions. Provided that the two UNICODE_STRING structures and the memory they each point to from their Buffer members are in non-paged memory, the RtlCopyUnicodeString function can safely be called at any IRQL. That it can has been documented by Microsoft since at least the DDK for Windows NT 3.51, but with only the one condition that “the buffers must be resident”, not also the structures, for use at and above DISPATCH_LEVEL.