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.

644 lines
29 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: prefix.hxx
  7. //
  8. // Contents: PREFIX table definition
  9. //
  10. // History: SethuR -- Implemented
  11. //
  12. // Notes: The DFS prefix table data structure consists of three
  13. // entities and methods to manipulate them. They are the
  14. // DFS_PREFIX_TABLE_ENTRY,DFS_PREFIX_TABLE_BUCKET and the
  15. // DFS_PREFIX_TABLE.
  16. //
  17. // The DFS_PREFIX_TABLE is a hash table of DFS_PREFIX_TABLE_ENTRY's
  18. // wherein collisions are resolved through linear chaining. The
  19. // hash table is organized as an array of collision lists
  20. // (DFS_PREFIX_TABLE_BUCKET). A brief description with each of
  21. // these entities is attached to the declaration.
  22. //
  23. // There are certain characterstics that distinguish this
  24. // hash table from other hash tables. These are the extensions
  25. // provided to accomodate the special operations.
  26. //
  27. //--------------------------------------------------------------------------
  28. #ifndef __PREFIX_H__
  29. #define __PREFIX_H__
  30. #include <dfsheader.h>
  31. //+---------------------------------------------------------------------
  32. //
  33. // Struct: DFS_PREFIX_TABLE_ENTRY
  34. //
  35. // History:
  36. //
  37. // Notes: Each DFS_PREFIX_TABLE entry is in reality a member of two linked
  38. // lists -- a doubly linked list chaining the entries in a bucket
  39. // and a singly linked list establishing the path from any entry to
  40. // the root of the name space. In addition we have the data associated
  41. // with each entry, viz., the name and the data (pData). We also
  42. // keep track of the number of children of each entry. It can also
  43. // be defined as the number of paths to the root of which this entry
  44. // is a member.
  45. //
  46. //----------------------------------------------------------------------
  47. typedef struct _DFS_PREFIX_TABLE_ENTRY_
  48. {
  49. struct _DFS_PREFIX_TABLE_ENTRY_ *pParentEntry;
  50. struct _DFS_PREFIX_TABLE_ENTRY_ *pNextEntry;
  51. struct _DFS_PREFIX_TABLE_ENTRY_ *pPrevEntry;
  52. //
  53. // pFirstChildEntry and pSiblingEntry are used purely for enumeration
  54. //
  55. struct _DFS_PREFIX_TABLE_ENTRY_ *pFirstChildEntry;
  56. struct _DFS_PREFIX_TABLE_ENTRY_ *pSiblingEntry;
  57. ULONG Reference;
  58. UNICODE_STRING PathSegment;
  59. PVOID pData;
  60. } DFS_PREFIX_TABLE_ENTRY, *PDFS_PREFIX_TABLE_ENTRY;
  61. //+---------------------------------------------------------------------
  62. //
  63. // Struct: DFS_PREFIX_TABLE_BUCKET
  64. //
  65. // History:
  66. //
  67. // Notes: The DFS_PREFIX_TABLE_BUCKET is a doubly linked list of
  68. // DFS_PREFIX_TABLE_ENTRY's. The current implementation employs
  69. // the notion of a sentinel entry associated with each bucket. The
  70. // end pointers are never null but are always looped back to the
  71. // sentinel entry. The reason we employ such an organization is that
  72. // it considerably simplifies the list manipulation routines. The
  73. // reason this needs to be a doubly linked list is that we would like
  74. // to have the ability of deleting entries without having to traverse
  75. // the buckets from beginning.
  76. //
  77. // The following inline methods ( macro defns. ) are provided for
  78. // inserting, deleting and looking up an entry in the bucket.
  79. //
  80. //----------------------------------------------------------------------
  81. typedef struct _PREFIX_TABLE_BUCKET_
  82. {
  83. ULONG NoOfEntries; // High water mark for entries hashing to the bkt.
  84. DFS_PREFIX_TABLE_ENTRY SentinelEntry;
  85. } PREFIX_TABLE_BUCKET, *PPREFIX_TABLE_BUCKET;
  86. //+---------------------------------------------------------------------
  87. //
  88. // Struct: DFS_PREFIX_TABLE
  89. //
  90. // History:
  91. //
  92. // Notes: The DFS_PREFIX_TABLE is a hashed collection of DFS_PREFIX_TABLE_ENTRY
  93. // organized in the form of buckets. In addition one other space
  94. // conserving measure is adopted. There is only one copy of each
  95. // name segment stored in the table. As an example consider the
  96. // two pathnames \foo\bar and \bar\foo. We only store one copy of foo
  97. // and bar eventhough we accomdate both these paths. A beneficial
  98. // side effect of storing single copies is that our traversal of the
  99. // collision chain is considerably speeded up since once we have
  100. // located the pointer to the name, subsequent comparisons need merely
  101. // compare pointers as opposed to strings.
  102. //
  103. //----------------------------------------------------------------------
  104. #define NO_OF_HASH_BUCKETS 57
  105. typedef struct _DFS_PREFIX_TABLE
  106. {
  107. DFS_OBJECT_HEADER DfsHeader;
  108. ULONG Flags;
  109. ULONG TotalEntries;
  110. LONG LockCount;
  111. PVOID pPrefixTableLock;
  112. //
  113. // NextEntry is used purely for enumeration
  114. //
  115. PDFS_PREFIX_TABLE_ENTRY NextEntry;
  116. DFS_PREFIX_TABLE_ENTRY RootEntry;
  117. PREFIX_TABLE_BUCKET Buckets[NO_OF_HASH_BUCKETS];
  118. } DFS_PREFIX_TABLE, *PDFS_PREFIX_TABLE;
  119. #define PREFIX_TABLE_CASE_SENSITIVE 0x1
  120. #define PREFIX_TABLE_TABLE_ALLOCATED 0x2
  121. #define PREFIX_TABLE_LOCK_ALLOCATED 0x4
  122. #define PREFIX_TABLE_LOCK_INITIALIZED 0x8
  123. //--------------------------------------------------------------------------
  124. //
  125. // PREFIX TABLE UTILITIES
  126. //
  127. // A Path is a sequence of one or more name segments alternated with a
  128. // distinguished concatenation character ( typically \ in FAT,NTFS,HPFS and
  129. // / in UNIX file systems). These utilities are used to split a given path
  130. // into the first path segment followed by the remainder of the path.
  131. //
  132. // SPLIT_PATH("foo\bar\bar1",Name,RemainingPath) binds Name to foo and
  133. // RemainingPath to bar\bar1
  134. //
  135. // Similarly PROCESS_CASE_SENSITIVE_NAME and PROCESS_CASE_INSENSITIVE_NAME
  136. // compute the hash signatures ( bucket no. ) for a given string.
  137. //
  138. //--------------------------------------------------------------------------
  139. //
  140. // MAX_PATH_SEGMENT_SIZE is simply used as a good size buffer to do prefix
  141. // lookups and insertions. This should save us from having to allocate for
  142. // most cases.
  143. //
  144. #define MAX_PATH_SEGMENT_SIZE 256
  145. #define PATH_DELIMITER L'\\'
  146. //+---------------------------------------------------------------------------
  147. //
  148. // Function: SPLIT_CASE_INSENSITIVE_PATH
  149. //
  150. // Synopsis: Split the path name around deleimiters.
  151. //
  152. // Arguments: [pPath] -- path to be split(PUNICODE_STRING)
  153. //
  154. // [pName] -- the leftmost component of the path(PUNICODE_STRING)
  155. //
  156. // [BucketNo] -- Hash Bucket no. corresponding to the name(ULONG)
  157. //
  158. // SideEffects: the UNICODE_STRING pointed to by pName and BucketNo are
  159. // modified.
  160. //
  161. // PreRequisite: pName be associated with a valid buffer.
  162. //
  163. // History: 04-18-94 SethuR Created
  164. //
  165. // Notes: defined as a macro for inlining
  166. //
  167. //----------------------------------------------------------------------------
  168. #define SPLIT_CASE_INSENSITIVE_PATH(pPath,pName,BucketNo) \
  169. { \
  170. WCHAR *pPathBuffer = (pPath)->Buffer; \
  171. WCHAR *pNameBuffer = (pName)->Buffer; \
  172. WCHAR *pPathBufferEnd = &pPathBuffer[(pPath)->Length / sizeof(WCHAR)]; \
  173. \
  174. BucketNo = 0; \
  175. while ((pPathBufferEnd != pPathBuffer) && \
  176. ((*pNameBuffer = *pPathBuffer++) != PATH_DELIMITER)) \
  177. { \
  178. *pNameBuffer = (*pNameBuffer < L'a') \
  179. ? *pNameBuffer \
  180. : ((*pNameBuffer < L'z') \
  181. ? (*pNameBuffer - L'a' + L'A') \
  182. : RtlUpcaseUnicodeChar(*pNameBuffer)); \
  183. BucketNo *= 131; \
  184. BucketNo += *pNameBuffer; \
  185. pNameBuffer++; \
  186. } \
  187. \
  188. BucketNo = BucketNo % NO_OF_HASH_BUCKETS; \
  189. *pNameBuffer = L'\0'; \
  190. (pName)->Length = (USHORT)((CHAR *)pNameBuffer - (CHAR *)(pName)->Buffer); \
  191. \
  192. (pPath)->Length = (USHORT)((CHAR *)pPathBufferEnd - (CHAR *)pPathBuffer); \
  193. (pPath)->Buffer = pPathBuffer; \
  194. } \
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Function: SPLIT_CASE_SENSITIVE_PATH
  198. //
  199. // Synopsis: Split the patah name around deleimiters.
  200. //
  201. // Arguments: [pPath] -- path to be split(PUNICODE_STRING)
  202. //
  203. // [pName] -- the leftmost component of the path(PUNICODE_STRING)
  204. //
  205. // [BucketNo] -- Hash Bucket no. corresponding to the name(ULONG)
  206. //
  207. // SideEffects: the UNICODE_STRING pointed to by pName and BucketNo are modified.
  208. //
  209. // PreRequisite: pName be associated with a valid buffer.
  210. //
  211. // History: 04-18-94 SethuR Created
  212. //
  213. // Notes: defined as a macro for inlining
  214. //
  215. //----------------------------------------------------------------------------
  216. #define SPLIT_CASE_SENSITIVE_PATH(pPath,pName,BucketNo) \
  217. { \
  218. WCHAR *pPathBuffer = (pPath)->Buffer; \
  219. WCHAR *pNameBuffer = (pName)->Buffer; \
  220. WCHAR *pPathBufferEnd = &pPathBuffer[(pPath)->Length / sizeof(WCHAR)]; \
  221. \
  222. BucketNo = 0; \
  223. while ((pPathBufferEnd != pPathBuffer) && \
  224. ((*pNameBuffer = *pPathBuffer++) != PATH_DELIMITER)) \
  225. { \
  226. BucketNo *= 131; \
  227. BucketNo += *pNameBuffer; \
  228. pNameBuffer++; \
  229. } \
  230. \
  231. BucketNo = BucketNo % NO_OF_HASH_BUCKETS; \
  232. *pNameBuffer = L'\0'; \
  233. (pName)->Length = (USHORT)((CHAR *)pNameBuffer - (CHAR *)(pName)->Buffer); \
  234. \
  235. (pPath)->Length = (USHORT)((CHAR *)pPathBufferEnd - (CHAR *)pPathBuffer); \
  236. (pPath)->Buffer = pPathBuffer; \
  237. } \
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Function: INITIALIZE_BUCKET
  241. //
  242. // Synopsis: Initializes a hash bucket.
  243. //
  244. // Arguments: [Bucket] -- the bucket to be initialized(DFS_PREFIX_TABLE_BUCKET)
  245. //
  246. // SideEffects: the bucket is intialized ( the collision list and count are
  247. // initialized
  248. //
  249. // History: 04-18-94 SethuR Created
  250. //
  251. // Notes: defined as a macro for inlining
  252. //
  253. //----------------------------------------------------------------------------
  254. #define INITIALIZE_BUCKET(Bucket) \
  255. { \
  256. (Bucket).SentinelEntry.pNextEntry = &(Bucket).SentinelEntry; \
  257. (Bucket).SentinelEntry.pPrevEntry = &(Bucket).SentinelEntry; \
  258. (Bucket).NoOfEntries = 0; \
  259. } \
  260. //+---------------------------------------------------------------------------
  261. //
  262. // Function: LOOKUP_BUCKET
  263. //
  264. // Synopsis: lookups the bucket for an entry.
  265. //
  266. // Arguments: [Bucket] -- the bucket to be used (DFS_PREFIX_TABLE_BUCKET)
  267. //
  268. // [Name] -- the name to be looked up (UNICODE_STRING)
  269. //
  270. // [pParentEntry] -- the parent entry of the entry we are
  271. // searching for.
  272. //
  273. // [pEntry] -- placeholder for the desired entry.
  274. //
  275. // [fNameFound] -- indicates if the name was found.
  276. //
  277. // SideEffects: Name,fNameFound and pEntry are modified
  278. //
  279. // History: 04-18-94 SethuR Created
  280. //
  281. // Notes: defined as a macro for inlining
  282. //
  283. // We only store one copy of a string irrespective of the no. of
  284. // places it appears in, e.g. foo\bar and foo1\bar will result
  285. // in only one copy of bar being stored. This implies that the
  286. // lookup routine will have to return sufficient info. to prevent
  287. // the allocation of memory space for a string. If on exit
  288. // fNameFound is set to TRUE then this indicates that a similar
  289. // string was located in the table and the Name.Buffer field is
  290. // modified to point to the first instance of the string in
  291. // the table.
  292. //
  293. //----------------------------------------------------------------------------
  294. #define LOOKUP_BUCKET(Bucket,Name,pParentEntry,pEntry,fNameFound) \
  295. { \
  296. PDFS_PREFIX_TABLE_ENTRY pCurEntry = Bucket.SentinelEntry.pNextEntry; \
  297. \
  298. fNameFound = FALSE; \
  299. pEntry = NULL; \
  300. \
  301. while (pCurEntry != &Bucket.SentinelEntry) \
  302. { \
  303. if (pCurEntry->PathSegment.Length == Name.Length) \
  304. { \
  305. if (fNameFound && \
  306. (pCurEntry->PathSegment.Buffer == Name.Buffer)) \
  307. { \
  308. if (pCurEntry->pParentEntry == pParentEntry) \
  309. { \
  310. pEntry = pCurEntry; \
  311. break; \
  312. } \
  313. } \
  314. else if (!memcmp(pCurEntry->PathSegment.Buffer, \
  315. Name.Buffer, \
  316. Name.Length)) \
  317. { \
  318. fNameFound = TRUE; \
  319. Name.Buffer = pCurEntry->PathSegment.Buffer; \
  320. if (pCurEntry->pParentEntry == pParentEntry) \
  321. { \
  322. pEntry = pCurEntry; \
  323. break; \
  324. } \
  325. } \
  326. } \
  327. \
  328. pCurEntry = pCurEntry->pNextEntry; \
  329. } \
  330. } \
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Function: INSERT_IN_BUCKET
  334. //
  335. // Synopsis: inserts the entry in the bucket
  336. //
  337. // Arguments: [Bucket] -- the bucket to be initialized(DFS_PREFIX_TABLE_BUCKET)
  338. //
  339. // [pEntry] -- the entry to be inserted
  340. //
  341. // SideEffects: Bucket is modified to include the entry
  342. //
  343. // History: 04-18-94 SethuR Created
  344. //
  345. // Notes: defined as a macro for inlining
  346. //
  347. //----------------------------------------------------------------------------
  348. #define INSERT_IN_BUCKET(Bucket,pEntry) \
  349. { \
  350. (Bucket).NoOfEntries++; \
  351. (pEntry)->pPrevEntry = (Bucket).SentinelEntry.pPrevEntry; \
  352. (pEntry)->pNextEntry = &((Bucket).SentinelEntry); \
  353. ((Bucket).SentinelEntry.pPrevEntry)->pNextEntry = (pEntry); \
  354. (Bucket).SentinelEntry.pPrevEntry = (pEntry); \
  355. } \
  356. //+---------------------------------------------------------------------------
  357. //
  358. // Function: REMOVE_FROM_BUCKET
  359. //
  360. // Synopsis: removes the entry from the bucket
  361. //
  362. // Arguments: [pEntry] -- the entry to be inserted
  363. //
  364. // SideEffects: Bucket is modified to exclude the entry
  365. //
  366. // History: 04-18-94 SethuR Created
  367. //
  368. // Notes: defined as a macro for inlining
  369. //
  370. //----------------------------------------------------------------------------
  371. #define REMOVE_FROM_BUCKET(pEntry) \
  372. { \
  373. PDFS_PREFIX_TABLE_ENTRY pPrevEntry = (pEntry)->pPrevEntry; \
  374. PDFS_PREFIX_TABLE_ENTRY pNextEntry = (pEntry)->pNextEntry; \
  375. \
  376. pPrevEntry->pNextEntry = pNextEntry; \
  377. pNextEntry->pPrevEntry = pPrevEntry; \
  378. } \
  379. //+---------------------------------------------------------------------------
  380. //
  381. // Function: INSERT_IN_CHILD_LIST
  382. //
  383. // Synopsis: Inserts this entry in the parent's list of children
  384. //
  385. // Arguments: [pEntry] -- the entry to be inserted
  386. //
  387. // [pParentEntry] -- the entry into whose list of children
  388. // pEntry has to be inserted.
  389. //
  390. // SideEffects: Parent's list of children is modified.
  391. //
  392. // History: 01-09-96 MilanS Created
  393. //
  394. // Notes: defined as a macro for inlining
  395. //
  396. //----------------------------------------------------------------------------
  397. #define INSERT_IN_CHILD_LIST(pEntry, pParentEntry) \
  398. { \
  399. PDFS_PREFIX_TABLE_ENTRY pLastChild; \
  400. \
  401. if (pParentEntry->pFirstChildEntry == NULL) { \
  402. pParentEntry->pFirstChildEntry = pEntry; \
  403. } else { \
  404. for (pLastChild = pParentEntry->pFirstChildEntry; \
  405. pLastChild->pSiblingEntry != NULL; \
  406. pLastChild = pLastChild->pSiblingEntry) { \
  407. NOTHING; \
  408. } \
  409. pLastChild->pSiblingEntry = pEntry; \
  410. } \
  411. }
  412. //+----------------------------------------------------------------------------
  413. //
  414. // Function: REMOVE_FROM_CHILD_LIST
  415. //
  416. // Synopsis: Removes an entry from its parent's list of children
  417. //
  418. // Arguments: [pEntry] -- the Entry to remove from children list.
  419. //
  420. // SideEffects: The children list of pParentEntry is modified.
  421. //
  422. // History: 01-09-96 MilanS Created
  423. //
  424. // Notes: Defined as a macro for inlining.
  425. //
  426. // This routine will ASSERT if pEntry is not in the parent's
  427. // list of children.
  428. //
  429. //-----------------------------------------------------------------------------
  430. #define REMOVE_FROM_CHILD_LIST(pEntry) \
  431. { \
  432. PDFS_PREFIX_TABLE_ENTRY pParentEntry = pEntry->pParentEntry; \
  433. PDFS_PREFIX_TABLE_ENTRY pPrevSibling; \
  434. \
  435. if (pParentEntry->pFirstChildEntry == pEntry) { \
  436. pParentEntry->pFirstChildEntry = pEntry->pSiblingEntry; \
  437. } else { \
  438. for (pPrevSibling = pParentEntry->pFirstChildEntry; \
  439. pPrevSibling->pSiblingEntry != pEntry; \
  440. pPrevSibling = pPrevSibling->pSiblingEntry) { \
  441. ASSERT(pPrevSibling->pSiblingEntry != NULL); \
  442. } \
  443. pPrevSibling->pSiblingEntry = pEntry->pSiblingEntry; \
  444. } \
  445. }
  446. //+---------------------------------------------------------------------------
  447. //
  448. // Function: INITIALIZE_PREFIX_TABLE_ENTRY
  449. //
  450. // Synopsis: initializes the prefix table entry
  451. //
  452. // Arguments: [pEntry] -- the entry to be initialized
  453. //
  454. // SideEffects: the prefix table entry is modified
  455. //
  456. // History: 04-18-94 SethuR Created
  457. //
  458. // Notes: defined as a macro for inlining
  459. //
  460. //----------------------------------------------------------------------------
  461. #define INITIALIZE_PREFIX_TABLE_ENTRY(pEntry) \
  462. { \
  463. RtlZeroMemory( pEntry, sizeof( DFS_PREFIX_TABLE_ENTRY ) ); \
  464. (pEntry)->Reference = 1; \
  465. } \
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Function: private fns. extern declarations
  469. //
  470. //----------------------------------------------------------------------------
  471. extern
  472. NTSTATUS _LookupPrefixTable(
  473. IN PDFS_PREFIX_TABLE pTable,
  474. IN UNICODE_STRING *pPath,
  475. OUT UNICODE_STRING *pSuffix,
  476. OUT PDFS_PREFIX_TABLE_ENTRY *ppEntry,
  477. OUT PBOOLEAN pSubStringMatch );
  478. VOID
  479. DfsRemovePrefixTableEntry(
  480. PDFS_PREFIX_TABLE pTable,
  481. PDFS_PREFIX_TABLE_ENTRY pEntry );
  482. //+---------------------------------------------------------------------------
  483. //
  484. // Function: ALLOCATION ROUTINES
  485. //
  486. // Synopsis: all the allocation routines are defined to be used in the KERNEL as
  487. // well as user mode. The KERNEL mode is turned on by defining KERNEL
  488. //
  489. // History: 04-18-94 SethuR Created
  490. //
  491. // Notes: defined as a macro for inlining
  492. //
  493. //----------------------------------------------------------------------------
  494. //
  495. // We may be holding the PrefixLock shared. However, we won't need interlocks to
  496. // just read the value.
  497. //
  498. #define IS_PREFIX_TABLE_LOCKED(_pTable) \
  499. ((_pTable)->LockCount > 0)
  500. #define ALLOCATE_PREFIX_TABLE() \
  501. PREFIX_TABLE_ALLOCATE_MEMORY(sizeof(DFS_PREFIX_TABLE))
  502. #define FREE_PREFIX_TABLE(_ptable) \
  503. PREFIX_TABLE_FREE_MEMORY(_ptable)
  504. #ifdef KERNEL_MODE
  505. #define ALLOCATE_NAME_BUFFER(cLength) \
  506. ExAllocatePoolWithTag(PagedPool, cLength * sizeof(WCHAR), 'PsfD'); \
  507. #define FREE_NAME_BUFFER(pName) ExFreePool(pName);
  508. #define ALLOCATE_DFS_PREFIX_TABLE_ENTRY(pTable) \
  509. (PDFS_PREFIX_TABLE_ENTRY) ExAllocatePoolWithTag(PagedPool,sizeof(DFS_PREFIX_TABLE_ENTRY), 'PsfD')
  510. #define FREE_DFS_PREFIX_TABLE_ENTRY(pTable,pEntry) ExFreePool(pEntry);
  511. #define COMPARE_MEMORY(s,d,l) (!RtlEqualMemory(s,d,l))
  512. #define PREFIX_TABLE_ALLOCATE_MEMORY(size) ExAllocatePoolWithTag(PagedPool, size, 'PsfD')
  513. #define PREFIX_TABLE_ALLOCATE_NONPAGED_MEMORY(size) ExAllocatePoolWithTag(NonPagedPool, size, 'PsfD')
  514. #define PREFIX_TABLE_FREE_MEMORY(_p) ExFreePool(_p)
  515. #define ALLOCATE_PREFIX_TABLE_LOCK() \
  516. PREFIX_TABLE_ALLOCATE_NONPAGED_MEMORY(sizeof(ERESOURCE))
  517. #define FREE_PREFIX_TABLE_LOCK(_plock) PREFIX_TABLE_FREE_MEMORY(_plock)
  518. // We may be holding the PrefixLock shared. Use Interlocks to change the LockCount.
  519. #define UNLOCK_PREFIX_TABLE(_ptable) {InterlockedDecrement( (ULONG volatile *)&(_ptable)->LockCount ); ExReleaseResourceLite((_ptable)->pPrefixTableLock);}
  520. #define WRITE_LOCK_PREFIX_TABLE(_ptable,_sts) {(_sts) = STATUS_UNSUCCESSFUL;if((ExAcquireResourceExclusiveLite((_ptable)->pPrefixTableLock, TRUE) == TRUE)){InterlockedIncrement((ULONG volatile *)&(_ptable)->LockCount);(_sts) = STATUS_SUCCESS;}}
  521. #define READ_LOCK_PREFIX_TABLE(_ptable,_sts) {(_sts) = STATUS_UNSUCCESSFUL;if((ExAcquireResourceSharedLite((_ptable)->pPrefixTableLock, TRUE) == TRUE)){InterlockedIncrement((ULONG volatile *)&(_ptable)->LockCount);(_sts) = STATUS_SUCCESS;}}
  522. #define INITIALIZE_PREFIX_TABLE_LOCK(_plock) ExInitializeResourceLite(_plock)
  523. #define UNINITIALIZE_PREFIX_TABLE_LOCK(_plock) ExDeleteResourceLite(_plock)
  524. #else
  525. #define ALLOCATE_PREFIX_TABLE_LOCK() \
  526. PREFIX_TABLE_ALLOCATE_MEMORY(sizeof(CRITICAL_SECTION))
  527. #define FREE_PREFIX_TABLE_LOCK(_plock) \
  528. PREFIX_TABLE_FREE_MEMORY(_plock)
  529. #define PREFIX_TABLE_SPIN_COUNT 4000
  530. #define INITIALIZE_PREFIX_TABLE_LOCK(_plock) ((InitializeCriticalSectionAndSpinCount(_plock, PREFIX_TABLE_SPIN_COUNT) == FALSE) ? GetLastError() : STATUS_SUCCESS)
  531. #define UNINITIALIZE_PREFIX_TABLE_LOCK(_plock) DeleteCriticalSection(_plock)
  532. #define UNLOCK_PREFIX_TABLE(_pTable) {(_pTable)->LockCount--; LeaveCriticalSection((_pTable)->pPrefixTableLock); }
  533. #define READ_LOCK_PREFIX_TABLE(_ptable, _sts) \
  534. WRITE_LOCK_PREFIX_TABLE(_ptable, _sts)
  535. #define WRITE_LOCK_PREFIX_TABLE(_pTable, _sts ) \
  536. { EnterCriticalSection((_pTable)->pPrefixTableLock); (_pTable)->LockCount++; (_sts) = STATUS_SUCCESS; }
  537. #define ALLOCATE_NAME_BUFFER(cLength) \
  538. PREFIX_TABLE_ALLOCATE_MEMORY(cLength * sizeof(WCHAR))
  539. #define FREE_NAME_BUFFER(_pName) \
  540. PREFIX_TABLE_FREE_MEMORY(_pName)
  541. #define ALLOCATE_DFS_PREFIX_TABLE_ENTRY(_pTable) \
  542. (PDFS_PREFIX_TABLE_ENTRY)PREFIX_TABLE_ALLOCATE_MEMORY(sizeof(DFS_PREFIX_TABLE_ENTRY))
  543. #define FREE_DFS_PREFIX_TABLE_ENTRY(_pTable,_pEntry) \
  544. PREFIX_TABLE_FREE_MEMORY(_pEntry)
  545. #define COMPARE_MEMORY(s,d,l) memcmp(s,d,l)
  546. #if defined (PREFIX_TABLE_HEAP_MEMORY)
  547. #define PREFIX_TABLE_ALLOCATE_MEMORY(_sz) \
  548. HeapAlloc(PrefixTableHeapHandle, 0, _sz)
  549. #define PREFIX_TABLE_FREE_MEMORY(_addr) \
  550. HeapFree(PrefixTableHeapHandle, 0, _addr)
  551. #else
  552. #define PREFIX_TABLE_ALLOCATE_MEMORY(_sz) malloc(_sz)
  553. #define PREFIX_TABLE_FREE_MEMORY(_addr) free(_addr)
  554. #endif
  555. #endif /*!Kernel mode */
  556. #endif // __PREFIX_H__