Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
5.9 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. path.c
  5. Abstract:
  6. This module implements string utilities for dealing with NT device names.
  7. Author:
  8. vadimb created sometime in 2000
  9. Revision History:
  10. clupu cleanup 12/27/2000
  11. --*/
  12. #include "apphelp.h"
  13. UNICODE_STRING DosDevicePrefix = RTL_CONSTANT_STRING(L"\\??\\");
  14. UNICODE_STRING DosDeviceUNCPrefix = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
  15. BOOL
  16. CheckStringPrefixUnicode(
  17. IN PUNICODE_STRING pStrPrefix, // the prefix to check for
  18. IN PUNICODE_STRING pString, // the string
  19. IN BOOL CaseInSensitive
  20. )
  21. /*++
  22. Return: TRUE if the specified string contains pStrPrefix at it's start.
  23. Desc: Verifies if a string is a prefix in another unicode counted string.
  24. It is equivalent to RtlStringPrefix.
  25. --*/
  26. {
  27. PWSTR ps1, ps2;
  28. UINT n;
  29. WCHAR c1, c2;
  30. n = pStrPrefix->Length;
  31. if (pString->Length < n) {
  32. return FALSE;
  33. }
  34. n /= sizeof(WCHAR); // convert to char count
  35. ps1 = pStrPrefix->Buffer;
  36. ps2 = pString->Buffer;
  37. if (CaseInSensitive) {
  38. while (n--) {
  39. c1 = *ps1++;
  40. c2 = *ps2++;
  41. if (c1 != c2) {
  42. c1 = RtlUpcaseUnicodeChar(c1);
  43. c2 = RtlUpcaseUnicodeChar(c2);
  44. if (c1 != c2) {
  45. return FALSE;
  46. }
  47. }
  48. }
  49. } else {
  50. while (n--) {
  51. if (*ps1++ != *ps2++) {
  52. return FALSE;
  53. }
  54. }
  55. }
  56. return TRUE;
  57. }
  58. BOOL
  59. DeleteCharsUnicodeString(
  60. OUT PUNICODE_STRING pStringDest, // UNICODE string to operate on
  61. IN USHORT nIndexStart, // starting byte for deletion
  62. IN USHORT nLength // number of bytes to be removed
  63. )
  64. /*++
  65. Return: TRUE if the characters were removed, FALSE on failure.
  66. Desc: Removes the specified number of characters from a unicode string
  67. starting at the specified position (including starting character).
  68. --*/
  69. {
  70. if (nIndexStart > pStringDest->Length) { // start past length
  71. return FALSE;
  72. }
  73. if (nLength >= (pStringDest->Length - nIndexStart)) {
  74. pStringDest->Length = nIndexStart;
  75. *(PWCHAR)((PUCHAR)pStringDest->Buffer + nIndexStart) = UNICODE_NULL;
  76. } else {
  77. USHORT nNewLength;
  78. nNewLength = pStringDest->Length - nLength;
  79. RtlMoveMemory((PUCHAR)pStringDest->Buffer + nIndexStart,
  80. (PUCHAR)pStringDest->Buffer + nIndexStart + nLength,
  81. nNewLength - nIndexStart);
  82. pStringDest->Length = nNewLength;
  83. *(PWCHAR)((PUCHAR)pStringDest->Buffer + nNewLength) = UNICODE_NULL;
  84. }
  85. return TRUE;
  86. }
  87. void
  88. InitZeroUnicodeString(
  89. OUT PUNICODE_STRING pStr,
  90. IN PWSTR pwsz,
  91. IN USHORT nMaximumLength
  92. )
  93. /*++
  94. Return: void.
  95. Desc: Initializes an empty UNICODE string given the pointer
  96. starting at the specified position (including starting character).
  97. --*/
  98. {
  99. pStr->Length = 0;
  100. pStr->MaximumLength = nMaximumLength;
  101. pStr->Buffer = pwsz;
  102. if (pwsz != NULL) {
  103. pwsz[0] = UNICODE_NULL;
  104. }
  105. }
  106. static WCHAR szStaticDosPathBuffer[MAX_PATH];
  107. void
  108. FreeDosPath(
  109. WCHAR* pDosPath
  110. )
  111. /*++
  112. Return: BUGBUG: ?
  113. Desc: BUGBUG: ?
  114. --*/
  115. {
  116. //
  117. // Check whether this memory points to our internal buffer.
  118. // If not then this was allocated. We need to free it.
  119. //
  120. if (pDosPath &&
  121. ((ULONG_PTR)pDosPath < (ULONG_PTR)szStaticDosPathBuffer ||
  122. (ULONG_PTR)pDosPath >= ((ULONG_PTR)szStaticDosPathBuffer) + sizeof(szStaticDosPathBuffer))) {
  123. SdbFree(pDosPath);
  124. }
  125. }
  126. BOOL
  127. ConvertToDosPath(
  128. OUT LPWSTR* ppDosPath,
  129. IN LPCWSTR pwszPath
  130. )
  131. /*++
  132. Return: TRUE on success, FALSE otherwise.
  133. Desc: This function can determine what sort of path has been given to it.
  134. If it's NT Path it returns DosPath.
  135. The function returns path name in a static buffer which is global
  136. or allocates memory as necessary if the static buffer is not
  137. large enough.
  138. --*/
  139. {
  140. UNICODE_STRING ustrPath;
  141. UNICODE_STRING ustrDosPath;
  142. WCHAR* pDosPath;
  143. RtlInitUnicodeString(&ustrPath, pwszPath);
  144. //
  145. // If the length is sufficient use the static buffer. If not allocate memory.
  146. //
  147. if (ustrPath.Length < sizeof(szStaticDosPathBuffer)) {
  148. pDosPath = szStaticDosPathBuffer;
  149. } else {
  150. //
  151. // Allocate an output buffer that is large enough
  152. //
  153. pDosPath = SdbAlloc(ustrPath.Length + sizeof(UNICODE_NULL));
  154. if (pDosPath == NULL) {
  155. DBGPRINT((sdlError,
  156. "ConvertToDosPath",
  157. "Failed to allocate %d bytes\n",
  158. ustrPath.Length + sizeof(UNICODE_NULL)));
  159. return FALSE;
  160. }
  161. }
  162. InitZeroUnicodeString(&ustrDosPath, pDosPath, ustrPath.Length + sizeof(UNICODE_NULL));
  163. //
  164. // Now it's unicode string. Copy the source string into it.
  165. //
  166. RtlCopyUnicodeString(&ustrDosPath, &ustrPath);
  167. if (CheckStringPrefixUnicode(&DosDeviceUNCPrefix, &ustrDosPath, TRUE)) {
  168. //
  169. // UNC path name. We convert it to DosPathName.
  170. //
  171. DeleteCharsUnicodeString(&ustrDosPath,
  172. (USHORT)0,
  173. (USHORT)(DosDeviceUNCPrefix.Length - 2 * sizeof(WCHAR)));
  174. ustrDosPath.Buffer[0] = L'\\';
  175. } else {
  176. //
  177. // The string is not prefixed by <UNC\>
  178. //
  179. if (CheckStringPrefixUnicode(&DosDevicePrefix, &ustrDosPath, TRUE)) {
  180. DeleteCharsUnicodeString(&ustrDosPath,
  181. 0,
  182. DosDevicePrefix.Length);
  183. }
  184. }
  185. *ppDosPath = pDosPath;
  186. return TRUE;
  187. }