Windows NT 4.0 source code leak
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.

319 lines
8.8 KiB

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