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.

263 lines
7.2 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: prefixp.c
  7. //
  8. // Contents: PREFIX table implementation
  9. //
  10. // History: SethuR -- Implemented
  11. //
  12. // Notes:
  13. //
  14. //--------------------------------------------------------------------------
  15. #ifdef KERNEL_MODE
  16. #include <dfsprocs.h>
  17. #define Dbg DEBUG_TRACE_RTL
  18. #else
  19. #define DebugTrace(x,y,z,a)
  20. #endif
  21. #include <prefix.h>
  22. #include <prefixp.h>
  23. //
  24. // This macro takes a pointer (or ulong) and returns its rounded up quadword
  25. // value
  26. //
  27. #define QuadAlign(Ptr) ( \
  28. ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
  29. )
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Function: _InitializePrefixTableEntryAllocation
  33. //
  34. // Synopsis: private fn. for initializing prefix table entry allocation
  35. //
  36. // Arguments: [pTable] -- table to be initialized
  37. //
  38. // Returns: one of the following NTSTATUS codes
  39. // STATUS_SUCCESS -- call was successfull.
  40. // STATUS_NO_MEMORY -- no resource available
  41. //
  42. // History: 04-18-94 SethuR Created
  43. //
  44. // Notes:
  45. //
  46. //----------------------------------------------------------------------------
  47. NTSTATUS _InitializePrefixTableEntryAllocation(PDFS_PREFIX_TABLE pTable)
  48. {
  49. NTSTATUS status = STATUS_SUCCESS;
  50. return status;
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Function: _AllocateNamePageEntry
  55. //
  56. // Synopsis: private fn. for allocating a name page entry
  57. //
  58. // Arguments: [pNamePageList] -- name page list to allocate from
  59. //
  60. // [cLength] -- length of the buffer in WCHAR's
  61. //
  62. // Returns: NULL if unsuccessfull otherwise valid pointer
  63. //
  64. // History: 04-18-94 SethuR Created
  65. //
  66. // Notes:
  67. //
  68. //----------------------------------------------------------------------------
  69. PWSTR _AllocateNamePageEntry(PNAME_PAGE_LIST pNamePageList,
  70. ULONG cLength)
  71. {
  72. PNAME_PAGE pTempPage = pNamePageList->pFirstPage;
  73. PWSTR pBuffer = NULL;
  74. //
  75. // We alloc in chunks of FREESPACE_IN_NAME_PAGE, so if cLength is
  76. // greater than that, we can't alloc anything.
  77. //
  78. if (cLength > FREESPACE_IN_NAME_PAGE) {
  79. return NULL;
  80. }
  81. while (pTempPage != NULL)
  82. {
  83. if (pTempPage->cFreeSpace >= (LONG)cLength)
  84. break;
  85. else
  86. pTempPage = pTempPage->pNextPage;
  87. }
  88. if (pTempPage == NULL)
  89. {
  90. pTempPage = ALLOCATE_NAME_PAGE();
  91. if (pTempPage != NULL)
  92. {
  93. INITIALIZE_NAME_PAGE(pTempPage);
  94. pTempPage->pNextPage = pNamePageList->pFirstPage;
  95. pNamePageList->pFirstPage = pTempPage;
  96. pTempPage->cFreeSpace = FREESPACE_IN_NAME_PAGE;
  97. }
  98. }
  99. if ((pTempPage != NULL) && (pTempPage->cFreeSpace >= (LONG)cLength))
  100. {
  101. pTempPage->cFreeSpace -= cLength;
  102. pBuffer = &pTempPage->Names[pTempPage->cFreeSpace];
  103. }
  104. return pBuffer;
  105. }
  106. //+---------------------------------------------------------------------------
  107. //
  108. // Function: _LookupPrefixTable
  109. //
  110. // Synopsis: private fn. for looking up a name segment in a prefix table
  111. //
  112. // Arguments: [pTable] -- the DFS prefix table instance
  113. //
  114. // [pPath] -- the path to be looked up.
  115. //
  116. // [pSuffix] -- the suffix that could not be found.
  117. //
  118. // [ppEntry] -- placeholder for the matching entry for the prefix.
  119. //
  120. //
  121. // Returns: one of the following NTSTATUS codes
  122. // STATUS_SUCCESS -- call was successfull.
  123. // STATUS_OBJECT_PATH_NOT_FOUND -- no entry for the path
  124. //
  125. // History: 04-18-94 SethuR Created
  126. //
  127. // Notes:
  128. //
  129. //----------------------------------------------------------------------------
  130. NTSTATUS _LookupPrefixTable(PDFS_PREFIX_TABLE pTable,
  131. UNICODE_STRING *pPath,
  132. UNICODE_STRING *pSuffix,
  133. PDFS_PREFIX_TABLE_ENTRY *ppEntry)
  134. {
  135. NTSTATUS status = STATUS_SUCCESS;
  136. UNICODE_STRING Path = *pPath;
  137. WCHAR Buffer[MAX_PATH_SEGMENT_SIZE];
  138. PWCHAR NameBuffer = Buffer;
  139. USHORT cbNameBuffer = sizeof(Buffer);
  140. UNICODE_STRING Name;
  141. ULONG BucketNo;
  142. BOOLEAN fPrefixFound = FALSE;
  143. PDFS_PREFIX_TABLE_ENTRY pEntry = NULL;
  144. PDFS_PREFIX_TABLE_ENTRY pParentEntry = &pTable->RootEntry;
  145. BOOLEAN fNameFound = FALSE;
  146. DebugTrace(0, Dbg, "_LookupPrefixTable -- Entry\n", 0);
  147. // The \ is treated as a special case. The test for all names starting with
  148. // a delimiter is done before we initiate the complete search process.
  149. if (Path.Buffer[0] == PATH_DELIMITER)
  150. {
  151. Path.Length = Path.Length - sizeof(WCHAR);
  152. Path.Buffer += 1; // Skip the path delimiter at the beginning.
  153. if (pTable->RootEntry.pData != NULL)
  154. {
  155. fPrefixFound = TRUE;
  156. *pSuffix = Path;
  157. *ppEntry = &pTable->RootEntry;
  158. }
  159. }
  160. if (Path.Length > MAX_PATH_SEGMENT_SIZE) {
  161. NameBuffer = ExAllocatePoolWithTag( NonPagedPool, Path.Length + sizeof(WCHAR), ' sfD' );
  162. if (NameBuffer == NULL) {
  163. DebugTrace(0, Dbg, "Unable to allocate %d non-paged bytes\n", (Path.Length + sizeof(WCHAR)) );
  164. return( STATUS_INSUFFICIENT_RESOURCES );
  165. } else {
  166. cbNameBuffer = Path.Length + sizeof(WCHAR);
  167. }
  168. }
  169. while (Path.Length > 0)
  170. {
  171. Name.Length = 0;
  172. Name.Buffer = NameBuffer;
  173. Name.MaximumLength = cbNameBuffer;
  174. if (pTable->CaseSensitive)
  175. {
  176. SPLIT_CASE_SENSITIVE_PATH(&Path,&Name,BucketNo);
  177. }
  178. else
  179. {
  180. SPLIT_CASE_INSENSITIVE_PATH(&Path,&Name,BucketNo);
  181. }
  182. if (Name.Length > 0)
  183. {
  184. // Process the name segment
  185. // Lookup the bucket to see if the entry exists.
  186. DebugTrace(0, Dbg, "LOOKUP_BUCKET: Bucket(%ld)", ULongToPtr( BucketNo ));
  187. DebugTrace(0, Dbg, "for Name(%wZ)\n", &Name);
  188. LOOKUP_BUCKET(pTable->Buckets[BucketNo],Name,pParentEntry,pEntry,fNameFound);
  189. DebugTrace(0, Dbg, "Returned pEntry(%lx)", pEntry);
  190. DebugTrace(0, Dbg, " and fNameFound(%s)\n",fNameFound ? "TRUE" : "FALSE" );
  191. if (pEntry != NULL)
  192. {
  193. // Cache the data available for this prefix if any.
  194. if (pEntry->pData != NULL)
  195. {
  196. *pSuffix = Path;
  197. *ppEntry = pEntry;
  198. fPrefixFound = TRUE;
  199. }
  200. }
  201. else
  202. {
  203. break;
  204. }
  205. // set the stage for processing the next name segment.
  206. pParentEntry = pEntry;
  207. }
  208. }
  209. if (!fPrefixFound)
  210. {
  211. status = STATUS_OBJECT_PATH_NOT_FOUND;
  212. DebugTrace(0, Dbg, "_LookupPrefixTable Error -- %lx\n", ULongToPtr( status ));
  213. }
  214. if (NameBuffer != Buffer) {
  215. ExFreePool( NameBuffer );
  216. }
  217. DebugTrace(-1, Dbg, "_LookupPrefixTable -- Exit\n", 0);
  218. return status;
  219. }