windows-nt/Source/XPSP1/NT/windows/appcompat/apphelp/path.c
2020-09-26 16:20:57 +08:00

240 lines
5.9 KiB
C

/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
path.c
Abstract:
This module implements string utilities for dealing with NT device names.
Author:
vadimb created sometime in 2000
Revision History:
clupu cleanup 12/27/2000
--*/
#include "apphelp.h"
UNICODE_STRING DosDevicePrefix = RTL_CONSTANT_STRING(L"\\??\\");
UNICODE_STRING DosDeviceUNCPrefix = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
BOOL
CheckStringPrefixUnicode(
IN PUNICODE_STRING pStrPrefix, // the prefix to check for
IN PUNICODE_STRING pString, // the string
IN BOOL CaseInSensitive
)
/*++
Return: TRUE if the specified string contains pStrPrefix at it's start.
Desc: Verifies if a string is a prefix in another unicode counted string.
It is equivalent to RtlStringPrefix.
--*/
{
PWSTR ps1, ps2;
UINT n;
WCHAR c1, c2;
n = pStrPrefix->Length;
if (pString->Length < n) {
return FALSE;
}
n /= sizeof(WCHAR); // convert to char count
ps1 = pStrPrefix->Buffer;
ps2 = pString->Buffer;
if (CaseInSensitive) {
while (n--) {
c1 = *ps1++;
c2 = *ps2++;
if (c1 != c2) {
c1 = RtlUpcaseUnicodeChar(c1);
c2 = RtlUpcaseUnicodeChar(c2);
if (c1 != c2) {
return FALSE;
}
}
}
} else {
while (n--) {
if (*ps1++ != *ps2++) {
return FALSE;
}
}
}
return TRUE;
}
BOOL
DeleteCharsUnicodeString(
OUT PUNICODE_STRING pStringDest, // UNICODE string to operate on
IN USHORT nIndexStart, // starting byte for deletion
IN USHORT nLength // number of bytes to be removed
)
/*++
Return: TRUE if the characters were removed, FALSE on failure.
Desc: Removes the specified number of characters from a unicode string
starting at the specified position (including starting character).
--*/
{
if (nIndexStart > pStringDest->Length) { // start past length
return FALSE;
}
if (nLength >= (pStringDest->Length - nIndexStart)) {
pStringDest->Length = nIndexStart;
*(PWCHAR)((PUCHAR)pStringDest->Buffer + nIndexStart) = UNICODE_NULL;
} else {
USHORT nNewLength;
nNewLength = pStringDest->Length - nLength;
RtlMoveMemory((PUCHAR)pStringDest->Buffer + nIndexStart,
(PUCHAR)pStringDest->Buffer + nIndexStart + nLength,
nNewLength - nIndexStart);
pStringDest->Length = nNewLength;
*(PWCHAR)((PUCHAR)pStringDest->Buffer + nNewLength) = UNICODE_NULL;
}
return TRUE;
}
void
InitZeroUnicodeString(
OUT PUNICODE_STRING pStr,
IN PWSTR pwsz,
IN USHORT nMaximumLength
)
/*++
Return: void.
Desc: Initializes an empty UNICODE string given the pointer
starting at the specified position (including starting character).
--*/
{
pStr->Length = 0;
pStr->MaximumLength = nMaximumLength;
pStr->Buffer = pwsz;
if (pwsz != NULL) {
pwsz[0] = UNICODE_NULL;
}
}
static WCHAR szStaticDosPathBuffer[MAX_PATH];
void
FreeDosPath(
WCHAR* pDosPath
)
/*++
Return: BUGBUG: ?
Desc: BUGBUG: ?
--*/
{
//
// Check whether this memory points to our internal buffer.
// If not then this was allocated. We need to free it.
//
if (pDosPath &&
((ULONG_PTR)pDosPath < (ULONG_PTR)szStaticDosPathBuffer ||
(ULONG_PTR)pDosPath >= ((ULONG_PTR)szStaticDosPathBuffer) + sizeof(szStaticDosPathBuffer))) {
SdbFree(pDosPath);
}
}
BOOL
ConvertToDosPath(
OUT LPWSTR* ppDosPath,
IN LPCWSTR pwszPath
)
/*++
Return: TRUE on success, FALSE otherwise.
Desc: This function can determine what sort of path has been given to it.
If it's NT Path it returns DosPath.
The function returns path name in a static buffer which is global
or allocates memory as necessary if the static buffer is not
large enough.
--*/
{
UNICODE_STRING ustrPath;
UNICODE_STRING ustrDosPath;
WCHAR* pDosPath;
RtlInitUnicodeString(&ustrPath, pwszPath);
//
// If the length is sufficient use the static buffer. If not allocate memory.
//
if (ustrPath.Length < sizeof(szStaticDosPathBuffer)) {
pDosPath = szStaticDosPathBuffer;
} else {
//
// Allocate an output buffer that is large enough
//
pDosPath = SdbAlloc(ustrPath.Length + sizeof(UNICODE_NULL));
if (pDosPath == NULL) {
DBGPRINT((sdlError,
"ConvertToDosPath",
"Failed to allocate %d bytes\n",
ustrPath.Length + sizeof(UNICODE_NULL)));
return FALSE;
}
}
InitZeroUnicodeString(&ustrDosPath, pDosPath, ustrPath.Length + sizeof(UNICODE_NULL));
//
// Now it's unicode string. Copy the source string into it.
//
RtlCopyUnicodeString(&ustrDosPath, &ustrPath);
if (CheckStringPrefixUnicode(&DosDeviceUNCPrefix, &ustrDosPath, TRUE)) {
//
// UNC path name. We convert it to DosPathName.
//
DeleteCharsUnicodeString(&ustrDosPath,
(USHORT)0,
(USHORT)(DosDeviceUNCPrefix.Length - 2 * sizeof(WCHAR)));
ustrDosPath.Buffer[0] = L'\\';
} else {
//
// The string is not prefixed by <UNC\>
//
if (CheckStringPrefixUnicode(&DosDevicePrefix, &ustrDosPath, TRUE)) {
DeleteCharsUnicodeString(&ustrDosPath,
0,
DosDevicePrefix.Length);
}
}
*ppDosPath = pDosPath;
return TRUE;
}