/*++ 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 // if (CheckStringPrefixUnicode(&DosDevicePrefix, &ustrDosPath, TRUE)) { DeleteCharsUnicodeString(&ustrDosPath, 0, DosDevicePrefix.Length); } } *ppDosPath = pDosPath; return TRUE; }