Leaked source code of windows server 2003
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.

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