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.

786 lines
24 KiB

  1. /*++
  2. Copyright (c) 1987-1999 Microsoft Corporation
  3. Module Name:
  4. midatlas.c
  5. Abstract:
  6. This module defines the data structure used in mapping MIDS to the
  7. corresponding requests/contexts associated with them.
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #ifdef ALLOC_PRAGMA
  12. #pragma alloc_text(PAGE, _InitializeMidMapFreeList)
  13. #pragma alloc_text(PAGE, FsRtlCreateMidAtlas)
  14. #pragma alloc_text(PAGE, _UninitializeMidMap)
  15. #pragma alloc_text(PAGE, FsRtlDestroyMidAtlas)
  16. #endif
  17. #define ENTRY_TYPE_FREE_MID_LIST (0x1)
  18. #define ENTRY_TYPE_VALID_CONTEXT (0x2)
  19. #define ENTRY_TYPE_MID_MAP (0x3)
  20. #define ENTRY_TYPE_MASK (0x3)
  21. #define MID_MAP_FLAGS_CAN_BE_EXPANDED (0x1)
  22. #define MID_MAP_FLAGS_FREE_POOL (0x2)
  23. typedef struct _MID_MAP_ {
  24. LIST_ENTRY MidMapList; // the list of MID maps in the MID atlas
  25. USHORT MaximumNumberOfMids; // the maximum number of MIDs in this map
  26. USHORT NumberOfMidsInUse; // the number of MIDs in use
  27. USHORT BaseMid; // the base MID associated with the map
  28. USHORT IndexMask; // the index mask for this map
  29. UCHAR IndexAlignmentCount; // the bits by which the index field is to be shifted
  30. UCHAR IndexFieldWidth; // the index field width
  31. UCHAR Flags; // flags ...
  32. UCHAR Level; // the level associated with this map ( useful for expansion )
  33. PVOID *pFreeMidListHead; // the list of free mid entries in this map
  34. PVOID Entries[1]; // the MID map entries.
  35. } MID_MAP, *PMID_MAP;
  36. //INLINE ULONG _GetEntryType(PVOID pEntry)
  37. #define _GetEntryType(pEntry) \
  38. ((ULONG)((ULONG_PTR)pEntry) & ENTRY_TYPE_MASK)
  39. //INLINE PVOID _GetEntryPointer(PVOID pEntry)
  40. #define _GetEntryPointer(pEntry) \
  41. ((PVOID)((ULONG_PTR)pEntry & ~ENTRY_TYPE_MASK))
  42. #define _MakeEntry(pContext,EntryType) \
  43. (PVOID)((ULONG_PTR)(pContext) | (EntryType))
  44. //INLINE PMID_MAP _GetFirstMidMap()
  45. /*++
  46. Routine Description:
  47. This first MID_MAP instance in the list
  48. Return Value:
  49. a valid PMID_MAP, NULL if none exists.
  50. Notes:
  51. This routine assumes that the necessary concurrency control action has been taken
  52. --*/
  53. #define _GetFirstMidMap(pListHead) \
  54. (IsListEmpty(pListHead) \
  55. ? NULL \
  56. : (PMID_MAP) \
  57. (CONTAINING_RECORD((pListHead)->Flink, \
  58. MID_MAP, \
  59. MidMapList)))
  60. //INLINE PSMBCEDB_SERVER_ENTRY GetNextMidMap(PLIST_ENTRY pListHead, PMID_MAP pMidMap)
  61. /*++
  62. Routine Description:
  63. This routine returns the next MID_MAP in the list
  64. Arguments:
  65. pListHead - the list of MID_MAP's
  66. pMidMap - the current instance
  67. Return Value:
  68. a valid PMID_MAP, NULL if none exists.
  69. Notes:
  70. This routine assumes that the necessary concurrency control action has been taken
  71. --*/
  72. #define _GetNextMidMap(pListHead,pMidMap) \
  73. (((pMidMap)->MidMapList.Flink == pListHead) \
  74. ? NULL \
  75. : (PMID_MAP) \
  76. (CONTAINING_RECORD((pMidMap)->MidMapList.Flink, \
  77. MID_MAP, \
  78. MidMapList)))
  79. //INLINE VOID _AddMidMap(
  80. // PLIST_ENTRY pListHead,
  81. // PMID_MAP pMidMap)
  82. /*++
  83. Routine Description:
  84. This routine adds a MID_MAP instance to a list
  85. Arguments:
  86. pListHead - the list of MID_MAP's
  87. pMidMap - the MID_MAP to be added
  88. --*/
  89. #define _AddMidMap(pListHead,pMidMap) \
  90. { \
  91. PMID_MAP pPredecessor; \
  92. pPredecessor = _GetFirstMidMap(pListHead); \
  93. while (pPredecessor != NULL) { \
  94. if (pPredecessor->Level < pMidMap->Level) { \
  95. pPredecessor = _GetNextMidMap(pListHead,pPredecessor); \
  96. } else { \
  97. pPredecessor = (PMID_MAP) \
  98. CONTAINING_RECORD( \
  99. pPredecessor->MidMapList.Blink, \
  100. MID_MAP, \
  101. MidMapList); \
  102. break; \
  103. } \
  104. } \
  105. \
  106. if (pPredecessor == NULL) { \
  107. InsertTailList(pListHead,&((pMidMap)->MidMapList)); \
  108. } else { \
  109. (pMidMap)->MidMapList.Flink = pPredecessor->MidMapList.Flink; \
  110. pPredecessor->MidMapList.Flink = &(pMidMap)->MidMapList; \
  111. \
  112. (pMidMap)->MidMapList.Blink = &pPredecessor->MidMapList; \
  113. (pMidMap)->MidMapList.Flink->Blink = &(pMidMap)->MidMapList; \
  114. } \
  115. }
  116. //INLINE VOID _RemoveMidMap(PMID_MAP pMidMap)
  117. /*++
  118. Routine Description:
  119. This routine removes a MID_MAP instance from the list
  120. Arguments:
  121. pMidMap - the MID_MAP instance to be removed
  122. --*/
  123. #define _RemoveMidMap(pMidMap) \
  124. RemoveEntryList(&(pMidMap)->MidMapList)
  125. VOID
  126. _InitializeMidMapFreeList(PMID_MAP pMidMap)
  127. /*++
  128. Routine Description:
  129. This routine initializes a MID_MAP data structure.
  130. Arguments:
  131. pMidMap - the MID_MAP instance to be initialized.
  132. Notes:
  133. --*/
  134. {
  135. USHORT i;
  136. PVOID *pEntryValue = (PVOID *)&pMidMap->Entries[1];
  137. PVOID *pEntriesPointer = (PVOID *)&pMidMap->Entries;
  138. PAGED_CODE();
  139. //DbgPrint("_InitializeMidMapFreeList .. Entry\n");
  140. if (pMidMap->MaximumNumberOfMids > 0) {
  141. pMidMap->pFreeMidListHead = pMidMap->Entries;
  142. for (i = 1; i <= pMidMap->MaximumNumberOfMids - 1;i++,pEntryValue++) {
  143. *pEntriesPointer++ = _MakeEntry(pEntryValue,ENTRY_TYPE_FREE_MID_LIST);
  144. }
  145. *pEntriesPointer = _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST);
  146. }
  147. //DbgPrint("_InitializeMidMapFreeList .. Exit\n");
  148. }
  149. PMID_ATLAS
  150. FsRtlCreateMidAtlas(
  151. USHORT MaximumNumberOfMids,
  152. USHORT MidsAllocatedAtStart)
  153. /*++
  154. Routine Description:
  155. This routine allocates a new instance of MID_ATLAS data structure.
  156. Arguments:
  157. MaximumNumberOfMids - the maximum number of MIDS in the atlas.
  158. MidsAllocatedAtStart - the number of MIDS allocated at start
  159. Notes:
  160. --*/
  161. {
  162. PMID_ATLAS pMidAtlas;
  163. PMID_MAP pMidMap;
  164. ULONG AtlasSize;
  165. USHORT MidsAllocatedRoundedToPowerOf2;
  166. USHORT MaximumMidsRoundedToPowerOf2;
  167. UCHAR MidFieldWidth,MaximumMidFieldWidth;
  168. PAGED_CODE();
  169. // Round off the Mids allocated at Start to a power of two
  170. MaximumMidsRoundedToPowerOf2 = 0x100;
  171. MaximumMidFieldWidth = 8;
  172. if (MaximumMidsRoundedToPowerOf2 != MaximumNumberOfMids) {
  173. if (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
  174. while (MaximumNumberOfMids > MaximumMidsRoundedToPowerOf2) {
  175. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
  176. MaximumMidFieldWidth++;
  177. }
  178. } else {
  179. while (MaximumNumberOfMids < MaximumMidsRoundedToPowerOf2) {
  180. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> 1;
  181. MaximumMidFieldWidth--;
  182. }
  183. MaximumMidFieldWidth++;
  184. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 << 1;
  185. }
  186. }
  187. MidsAllocatedRoundedToPowerOf2 = 0x100;
  188. MidFieldWidth = 8;
  189. if (MidsAllocatedRoundedToPowerOf2 != MidsAllocatedAtStart) {
  190. if (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
  191. while (MidsAllocatedAtStart > MidsAllocatedRoundedToPowerOf2) {
  192. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
  193. MidFieldWidth++;
  194. }
  195. } else {
  196. while (MidsAllocatedAtStart < MidsAllocatedRoundedToPowerOf2) {
  197. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 >> 1;
  198. MidFieldWidth--;
  199. }
  200. MidFieldWidth++;
  201. MidsAllocatedRoundedToPowerOf2 = MidsAllocatedRoundedToPowerOf2 << 1;
  202. }
  203. }
  204. AtlasSize = sizeof(MID_ATLAS) +
  205. FIELD_OFFSET(MID_MAP,Entries);
  206. if (MaximumNumberOfMids == MidsAllocatedAtStart) {
  207. AtlasSize += (sizeof(PVOID) * MidsAllocatedAtStart);
  208. } else {
  209. AtlasSize += (sizeof(PVOID) * MidsAllocatedRoundedToPowerOf2);
  210. }
  211. pMidAtlas = (PMID_ATLAS)RxAllocatePoolWithTag(
  212. NonPagedPool,
  213. AtlasSize,
  214. MRXSMB_MIDATLAS_POOLTAG);
  215. if (pMidAtlas != NULL) {
  216. pMidMap = (PMID_MAP)(pMidAtlas + 1);
  217. pMidMap->Flags = 0;
  218. pMidAtlas->MaximumNumberOfMids = MaximumNumberOfMids;
  219. pMidAtlas->MidsAllocated = MidsAllocatedAtStart;
  220. pMidAtlas->NumberOfMidsInUse = 0;
  221. pMidAtlas->NumberOfMidsDiscarded = 0;
  222. pMidAtlas->MaximumMidFieldWidth = MaximumMidFieldWidth;
  223. pMidMap->MaximumNumberOfMids = MidsAllocatedAtStart;
  224. pMidMap->NumberOfMidsInUse = 0;
  225. pMidMap->BaseMid = 0;
  226. pMidMap->IndexMask = MidsAllocatedRoundedToPowerOf2 - 1;
  227. pMidMap->IndexAlignmentCount = 0;
  228. pMidMap->IndexFieldWidth = MidFieldWidth;
  229. pMidMap->Level = 1;
  230. InitializeListHead(&pMidAtlas->MidMapFreeList);
  231. InitializeListHead(&pMidAtlas->MidMapExpansionList);
  232. _InitializeMidMapFreeList(pMidMap);
  233. _AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
  234. pMidAtlas->pRootMidMap = pMidMap;
  235. if (MaximumNumberOfMids > MidsAllocatedAtStart) {
  236. // Round off the maximum number of MIDS to determine the level and the
  237. // size of the quantum ( allocation increments)
  238. pMidMap->Flags |= MID_MAP_FLAGS_CAN_BE_EXPANDED;
  239. pMidAtlas->MidQuantum = 32;
  240. pMidAtlas->MidQuantumFieldWidth = 5;
  241. MaximumMidsRoundedToPowerOf2 = MaximumMidsRoundedToPowerOf2 >> (pMidMap->IndexAlignmentCount + 5);
  242. if (MaximumMidsRoundedToPowerOf2 > 0) {
  243. pMidAtlas->NumberOfLevels = 3;
  244. } else {
  245. pMidAtlas->NumberOfLevels = 2;
  246. }
  247. } else {
  248. pMidAtlas->MidQuantum = 0;
  249. pMidAtlas->NumberOfLevels = 1;
  250. pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
  251. }
  252. }
  253. //DbgPrint("FsRtlAllocatMidAtlas .. Exit (pMidAtlas) %lx\n",pMidAtlas);
  254. return pMidAtlas;
  255. }
  256. VOID
  257. _UninitializeMidMap(
  258. PMID_MAP pMidMap,
  259. PCONTEXT_DESTRUCTOR pContextDestructor)
  260. /*++
  261. Routine Description:
  262. This routine uninitializes a MID_MAP data structure.
  263. Arguments:
  264. pMidMap -- the MID_MAP instance to be uninitialized.
  265. pContextDestructor -- the context destructor
  266. Notes:
  267. --*/
  268. {
  269. USHORT i;
  270. ULONG EntryType;
  271. PAGED_CODE();
  272. //DbgPrint("_UninitializeMidMap .. Entry No.Of MIDS in Use %ld\n",pMidMap->NumberOfMidsInUse);
  273. RxLog(("_UninitMidMap .. num= %ld\n",pMidMap->NumberOfMidsInUse));
  274. for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
  275. PMID_MAP pChildMidMap;
  276. EntryType = _GetEntryType(pMidMap->Entries[i]);
  277. switch (EntryType) {
  278. case ENTRY_TYPE_MID_MAP :
  279. {
  280. pChildMidMap = (PMID_MAP)_GetEntryPointer(pMidMap->Entries[i]);
  281. _UninitializeMidMap(pChildMidMap,pContextDestructor);
  282. }
  283. break;
  284. case ENTRY_TYPE_VALID_CONTEXT :
  285. {
  286. if (pContextDestructor != NULL) {
  287. PVOID pContext;
  288. pContext = _GetEntryPointer(pMidMap->Entries[i]);
  289. (pContextDestructor)(pContext);
  290. }
  291. }
  292. break;
  293. default:
  294. break;
  295. }
  296. }
  297. if (pMidMap->Flags & MID_MAP_FLAGS_FREE_POOL) {
  298. RxFreePool(pMidMap);
  299. }
  300. //DbgPrint("_UninitializeMidMap .. Exit\n");
  301. }
  302. VOID
  303. FsRtlDestroyMidAtlas(
  304. PMID_ATLAS pMidAtlas,
  305. PCONTEXT_DESTRUCTOR pContextDestructor)
  306. /*++
  307. Routine Description:
  308. This routine frees a MID_ATLAS instance. As a side effect it invokes the
  309. passed in context destructor on every valid context in the MID_ATLAS
  310. Arguments:
  311. pMidAtlas - the MID_ATLAS instance to be freed.
  312. PCONTEXT_DESTRUCTOR - the associated context destructor
  313. Notes:
  314. --*/
  315. {
  316. PAGED_CODE();
  317. //DbgPrint("FsRtlFreeMidAtlas .. Entry\n");
  318. _UninitializeMidMap(pMidAtlas->pRootMidMap,pContextDestructor);
  319. RxFreePool(pMidAtlas);
  320. //DbgPrint("FsRtlFreeMidAtlas .. Exit\n");
  321. }
  322. PVOID
  323. FsRtlMapMidToContext(
  324. PMID_ATLAS pMidAtlas,
  325. USHORT Mid)
  326. /*++
  327. Routine Description:
  328. This routine maps a MID to its associated context in a MID_ATLAS.
  329. Arguments:
  330. pMidAtlas - the MID_ATLAS instance.
  331. Mid - the MId to be mapped
  332. Return value:
  333. the associated context, NULL if none exists
  334. Notes:
  335. --*/
  336. {
  337. ULONG EntryType;
  338. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  339. PVOID pContext;
  340. ULONG Index;
  341. //DbgPrint("FsRtlMapMidToContext Mid %lx ",Mid);
  342. for (;;) {
  343. Index = (Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount;
  344. if (Index >= pMidMap->MaximumNumberOfMids) {
  345. pContext = NULL;
  346. break;
  347. }
  348. pContext = pMidMap->Entries[Index];
  349. EntryType = _GetEntryType(pContext);
  350. pContext = (PVOID)_GetEntryPointer(pContext);
  351. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  352. break;
  353. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  354. pContext = NULL;
  355. break;
  356. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  357. pMidMap = (PMID_MAP)pContext;
  358. } else {
  359. pContext = NULL;
  360. break;
  361. }
  362. }
  363. //DbgPrint("Context %lx \n",pContext);
  364. return pContext;
  365. }
  366. NTSTATUS
  367. FsRtlMapAndDissociateMidFromContext(
  368. PMID_ATLAS pMidAtlas,
  369. USHORT Mid,
  370. PVOID *pContextPointer)
  371. /*++
  372. Routine Description:
  373. This routine maps a MID to its associated context in a MID_ATLAS.
  374. Arguments:
  375. pMidAtlas - the MID_ATLAS instance.
  376. Mid - the MId to be mapped
  377. Return value:
  378. the associated context, NULL if none exists
  379. Notes:
  380. --*/
  381. {
  382. ULONG EntryType;
  383. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  384. PVOID pContext;
  385. PVOID *pEntry;
  386. //DbgPrint("FsRtlMapAndDissociateMidFromContext Mid %lx ",Mid);
  387. for (;;) {
  388. pEntry = &pMidMap->Entries[
  389. (Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
  390. pContext = *pEntry;
  391. EntryType = _GetEntryType(pContext);
  392. pContext = (PVOID)_GetEntryPointer(pContext);
  393. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  394. pMidMap->NumberOfMidsInUse--;
  395. if (pMidMap->pFreeMidListHead == NULL) {
  396. if (pMidMap->Flags & MID_MAP_FLAGS_CAN_BE_EXPANDED) {
  397. _RemoveMidMap(pMidMap);
  398. }
  399. _AddMidMap(&pMidAtlas->MidMapFreeList,pMidMap);
  400. }
  401. *pEntry = _MakeEntry(pMidMap->pFreeMidListHead,ENTRY_TYPE_FREE_MID_LIST);
  402. pMidMap->pFreeMidListHead = pEntry;
  403. break;
  404. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  405. pContext = NULL;
  406. break;
  407. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  408. pMidMap = (PMID_MAP)pContext;
  409. }
  410. }
  411. pMidAtlas->NumberOfMidsInUse--;
  412. //DbgPrint("Context %lx\n",pContext);
  413. *pContextPointer = pContext;
  414. return STATUS_SUCCESS;
  415. }
  416. NTSTATUS
  417. FsRtlReassociateMid(
  418. PMID_ATLAS pMidAtlas,
  419. USHORT Mid,
  420. PVOID pNewContext)
  421. /*++
  422. Routine Description:
  423. This routine maps a MID to its associated context in a MID_ATLAS.
  424. Arguments:
  425. pMidAtlas - the MID_ATLAS instance.
  426. Mid - the MId to be mapped
  427. pNewContext - the new context
  428. Return value:
  429. the associated context, NULL if none exists
  430. Notes:
  431. --*/
  432. {
  433. ULONG EntryType;
  434. PMID_MAP pMidMap = pMidAtlas->pRootMidMap;
  435. PVOID pContext;
  436. //DbgPrint("FsRtlReassociateMid Mid %lx ",Mid);
  437. for (;;) {
  438. pContext = pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount];
  439. EntryType = _GetEntryType(pContext);
  440. pContext = (PVOID)_GetEntryPointer(pContext);
  441. if (EntryType == ENTRY_TYPE_VALID_CONTEXT) {
  442. pMidMap->Entries[(Mid & pMidMap->IndexMask) >> pMidMap->IndexAlignmentCount]
  443. = _MakeEntry(pNewContext,ENTRY_TYPE_VALID_CONTEXT);
  444. break;
  445. } else if (EntryType == ENTRY_TYPE_FREE_MID_LIST) {
  446. ASSERT(!"Valid MID Atlas");
  447. break;
  448. } else if (EntryType == ENTRY_TYPE_MID_MAP) {
  449. pMidMap = (PMID_MAP)pContext;
  450. }
  451. }
  452. //DbgPrint("New COntext %lx\n",pNewContext);
  453. return STATUS_SUCCESS;
  454. }
  455. NTSTATUS
  456. FsRtlAssociateContextWithMid(
  457. PMID_ATLAS pMidAtlas,
  458. PVOID pContext,
  459. PUSHORT pNewMid)
  460. /*++
  461. Routine Description:
  462. This routine initializes a MID_MAP data structure.
  463. Arguments:
  464. pMidMap - the MID_MAP instance to be initialized.
  465. Return Value:
  466. STATUS_SUCCESS if successful, otherwise one of the following errors
  467. STATUS_INSUFFICIENT_RESOURCES
  468. STATUS_UNSUCCESSFUL -- no mid could be associated
  469. Notes:
  470. --*/
  471. {
  472. NTSTATUS Status;
  473. PMID_MAP pMidMap;
  474. PVOID *pContextPointer;
  475. //DbgPrint("FsRtlAssociateContextWithMid Context %lx ",pContext);
  476. // Scan the list of MID_MAP's which have free entries in them.
  477. if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapFreeList)) != NULL) {
  478. ASSERT(pMidMap->pFreeMidListHead != _MakeEntry(NULL,ENTRY_TYPE_FREE_MID_LIST));
  479. pMidMap->NumberOfMidsInUse++;
  480. pContextPointer = pMidMap->pFreeMidListHead;
  481. pMidMap->pFreeMidListHead = _GetEntryPointer(*(pMidMap->pFreeMidListHead));
  482. *pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
  483. *pNewMid = ((USHORT)
  484. (pContextPointer - (PVOID *)&pMidMap->Entries)
  485. << pMidMap->IndexAlignmentCount) |
  486. pMidMap->BaseMid;
  487. // Check if the MID_MAP needs to be removed from the list of MID_MAP's with
  488. // free entries
  489. if (pMidMap->pFreeMidListHead == NULL) {
  490. _RemoveMidMap(pMidMap);
  491. // Check if it can be added to the expansion list.
  492. if (pMidAtlas->NumberOfLevels > pMidMap->Level) {
  493. _AddMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
  494. }
  495. }
  496. Status = STATUS_SUCCESS;
  497. } else if ((pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList)) != NULL) {
  498. PMID_MAP pNewMidMap;
  499. USHORT i;
  500. ULONG NewMidMapSize;
  501. // Locate the index in the mid map for the new mid map
  502. pMidMap = _GetFirstMidMap(&pMidAtlas->MidMapExpansionList);
  503. while (pMidMap != NULL) {
  504. for (i = 0; i < pMidMap->MaximumNumberOfMids; i++) {
  505. if (_GetEntryType(pMidMap->Entries[i]) != ENTRY_TYPE_MID_MAP) {
  506. break;
  507. }
  508. }
  509. if (i < pMidMap->MaximumNumberOfMids) {
  510. break;
  511. } else {
  512. pMidMap->Flags &= ~MID_MAP_FLAGS_CAN_BE_EXPANDED;
  513. _RemoveMidMap(pMidMap);
  514. pMidMap = _GetNextMidMap(&pMidAtlas->MidMapExpansionList,pMidMap);
  515. }
  516. }
  517. if (pMidMap != NULL) {
  518. USHORT NumberOfEntriesInMap = pMidAtlas->MaximumNumberOfMids -
  519. pMidAtlas->NumberOfMidsInUse;
  520. if (NumberOfEntriesInMap > pMidAtlas->MidQuantum) {
  521. NumberOfEntriesInMap = pMidAtlas->MidQuantum;
  522. }
  523. if (NumberOfEntriesInMap > 0) {
  524. NewMidMapSize = FIELD_OFFSET(MID_MAP,Entries) +
  525. NumberOfEntriesInMap * sizeof(PVOID);
  526. pNewMidMap = (PMID_MAP)RxAllocatePoolWithTag(
  527. NonPagedPool,
  528. NewMidMapSize,
  529. MRXSMB_MIDATLAS_POOLTAG);
  530. if (pNewMidMap != NULL) {
  531. pNewMidMap->Flags = MID_MAP_FLAGS_FREE_POOL;
  532. pNewMidMap->MaximumNumberOfMids = NumberOfEntriesInMap;
  533. pNewMidMap->NumberOfMidsInUse = 0;
  534. pNewMidMap->BaseMid = (pMidMap->BaseMid |
  535. i << pMidMap->IndexAlignmentCount);
  536. pNewMidMap->IndexAlignmentCount = pMidMap->IndexAlignmentCount +
  537. pMidMap->IndexFieldWidth;
  538. pNewMidMap->IndexMask = (pMidAtlas->MidQuantum - 1) << pNewMidMap->IndexAlignmentCount;
  539. pNewMidMap->IndexFieldWidth = pMidAtlas->MidQuantumFieldWidth;
  540. _InitializeMidMapFreeList(pNewMidMap);
  541. // Set up the mid map appropriately.
  542. pNewMidMap->NumberOfMidsInUse = 1;
  543. pNewMidMap->Entries[0] = pMidMap->Entries[i];
  544. pNewMidMap->Level = pMidMap->Level + 1;
  545. pNewMidMap->pFreeMidListHead = *(pNewMidMap->pFreeMidListHead);
  546. pMidMap->Entries[i] = _MakeEntry(pNewMidMap,ENTRY_TYPE_MID_MAP);
  547. // Update the free list and the expansion list respectively.
  548. _AddMidMap(&pMidAtlas->MidMapFreeList,pNewMidMap);
  549. pNewMidMap->NumberOfMidsInUse++;
  550. pContextPointer = pNewMidMap->pFreeMidListHead;
  551. pNewMidMap->pFreeMidListHead = _GetEntryPointer(*(pNewMidMap->pFreeMidListHead));
  552. *pContextPointer = _MakeEntry(pContext,ENTRY_TYPE_VALID_CONTEXT);
  553. *pNewMid = (USHORT)
  554. (((ULONG)(pContextPointer -
  555. (PVOID *)&pNewMidMap->Entries) / sizeof(PVOID))
  556. << pNewMidMap->IndexAlignmentCount) |
  557. pNewMidMap->BaseMid;
  558. Status = STATUS_SUCCESS;
  559. } else {
  560. Status = STATUS_INSUFFICIENT_RESOURCES;
  561. }
  562. } else {
  563. Status = STATUS_UNSUCCESSFUL;
  564. }
  565. } else {
  566. Status = STATUS_UNSUCCESSFUL;
  567. }
  568. } else {
  569. Status = STATUS_UNSUCCESSFUL;
  570. }
  571. if (Status == STATUS_SUCCESS) {
  572. pMidAtlas->NumberOfMidsInUse++;
  573. }
  574. //DbgPrint("Mid %lx\n",*pNewMid);
  575. return Status;
  576. }
  577.