xxx
NTSTATUS NTAPI RtlpWin32NTNameToNtPathName_U ( IN PUNICODE_STRING DosPath, OUT PUNICODE_STRING NtPath, OUT PCWSTR * PartName, OUT PRTL_RELATIVE_NAME_U RelativeName ) { ULONG DosLength; PWSTR NewBuffer, p; /* Validate the input */ if (!DosPath) return STATUS_OBJECT_NAME_INVALID; /* Validate the DOS length */ DosLength = DosPath->Length; if (DosLength >= UNICODE_STRING_MAX_BYTES) return STATUS_NAME_TOO_LONG; /* Make space for the new path */ NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DosLength + sizeof(UNICODE_NULL)); if (!NewBuffer) return STATUS_NO_MEMORY; /* Copy the prefix, and then the rest of the DOS path, and NULL-terminate */ RtlCopyMemory(NewBuffer, RtlpDosDevicesPrefix.Buffer, RtlpDosDevicesPrefix.Length); RtlCopyMemory((PCHAR)NewBuffer + RtlpDosDevicesPrefix.Length, DosPath->Buffer + RtlpDosDevicesPrefix.Length / sizeof(WCHAR), DosPath->Length - RtlpDosDevicesPrefix.Length); NewBuffer[DosLength / sizeof(WCHAR)] = UNICODE_NULL; /* Did the caller send a relative name? */ if (RelativeName) { /* Zero initialize it */ RtlInitEmptyUnicodeString(&RelativeName->RelativeName, NULL, 0); RelativeName->ContainingDirectory = NULL; RelativeName->CurDirRef = 0; } /* Did the caller request a partial name? */ if (PartName) { /* Loop from the back until we find a path separator */ p = &NewBuffer[(DosLength - 1) / sizeof (WCHAR)]; while (p > NewBuffer) if (*p-- == '\\') break; /* Was one found? */ if (p > NewBuffer) { /* Move past it -- anything left? */ p++; if (!*p) { /* The path ends with a path separator, no part name */ *PartName = NULL; } else { /* What follows the path separator is the part name */ *PartName = p; } } } /* Build the final NT path string */ NtPath->Length = (USHORT)DosLength; NtPath->Buffer = NewBuffer; NtPath->MaximumLength = (USHORT)DosLength + sizeof(UNICODE_NULL); return STATUS_SUCCESS; }