240 lines
5.9 KiB
C
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;
|
|
}
|
|
|