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.

668 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. mm.c
  5. Abstract:
  6. This module implements the memory managment routines for the SMB mini
  7. redirector
  8. Notes:
  9. The SMB mini redirector manipulates entities which have very different usage
  10. patterns. They range from very static entities ( which are allocated and freed
  11. with a very low frequency ) to very dynamic entities.
  12. The entities manipulated in the SMB mini redirector are SMBCE_SERVER, SMBCE_NET_ROOT,
  13. SMBCE_VC, SMBCE_SESSION. These represent a connection to a server, a share on
  14. a particular server, a virtual circuit used in the connection and a session
  15. for a particular user.
  16. These are not very dynamic, i.e., the allocation/deallocation is very infrequent.
  17. The SMB_EXCHANGE and SMBCE_REQUEST map to the SMB's that are sent along that
  18. a connection. Every file operation in turn maps to a certain number of calls
  19. for allocationg/freeing exchanges and requests. Therefore it is imperative
  20. that some form of scavenging/caching of recently freed entries be maintained
  21. to satisfy requests quickly.
  22. In the current implementation the exchanges and requests are implemented
  23. using the zone allocation primitives.
  24. The exchange allocation and free routines are currently implemented as wrappers
  25. around the RxAllocate and RxFree routines. It would be far more efficient if
  26. a look aside cache of some exchange instances are maintained.
  27. --*/
  28. #include "precomp.h"
  29. #pragma hdrstop
  30. #include <vcsndrcv.h>
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text(PAGE, SmbMmAllocateSessionEntry)
  33. #pragma alloc_text(PAGE, SmbMmFreeSessionEntry)
  34. #pragma alloc_text(PAGE, SmbMmAllocateServerTransport)
  35. #pragma alloc_text(PAGE, SmbMmFreeServerTransport)
  36. #pragma alloc_text(PAGE, SmbMmInit)
  37. #pragma alloc_text(PAGE, SmbMmTearDown)
  38. #endif
  39. #define SMBMM_ZONE_ALLOCATION 0x10
  40. // The memory management package addresses a number of concerns w.r.t debugging
  41. // and performance. By centralizing all the allocation/deallocation routines to
  42. // thsi one module it is possible to build up profiles regarding various data
  43. // structures used by the connection engine. In addition debugging support is
  44. // provided by thereading together all allocated objects of a particular type
  45. // are threaded together in a linked list according to type.
  46. //
  47. // At any stage by inspecting these lists the currently active instances of a
  48. // particular type can be enumerated.
  49. //
  50. // Each type handled by this module is provided with two routines, e.g., for
  51. // server entries there are SmbMmInitializeEntry and SmbMmUninitializeEntry. The
  52. // first routine is called before handing over a pointer of a newly created
  53. // instance. This will ensure that the instance is in a wll known initial state.
  54. // Similarly the second routine is called just before deallocating the pool
  55. // associated with the instance. This helps enforce the necessary integrity
  56. // constraints, e.g., all enclosed pointers must be NULL etc.
  57. //
  58. // The pool allocation/deallocation is handled by the following routines
  59. //
  60. // SmbMmAllocateObjectPool/SmbMmFreeObjectPool
  61. //
  62. // SmbMmAllocateExchange/SmbMmFreeExchange
  63. //
  64. // The Object allocation routines are split up into two parts so as to be able to
  65. // handle the session allocationson par with other objects even though they are
  66. // further subtyped.
  67. //
  68. // On debug builds additional pool is allocated and the appropriate linking is
  69. // done into the corresponding list. On retail builds these map to the regular
  70. // pool allocation wrappers.
  71. //
  72. // Zone allocation to speed up memory management of RxCe entities.
  73. //
  74. ULONG SmbMmRequestZoneEntrySize;
  75. ZONE_HEADER SmbMmRequestZone;
  76. PVOID SmbMmRequestZoneSegmentPtr;
  77. //
  78. // Pool allocation resources and spin locks
  79. //
  80. KSPIN_LOCK SmbMmSpinLock;
  81. ULONG SmbMmExchangeId;
  82. //
  83. // List of the various objects/exchanges allocated.
  84. //
  85. LIST_ENTRY SmbMmExchangesInUse[SENTINEL_EXCHANGE];
  86. LIST_ENTRY SmbMmObjectsInUse[SMBCEDB_OT_SENTINEL];
  87. ULONG ObjectSizeInBytes[SMBCEDB_OT_SENTINEL];
  88. ULONG ExchangeSizeInBytes[SENTINEL_EXCHANGE];
  89. //
  90. // Lookaside lists for Exchange allocation
  91. //
  92. NPAGED_LOOKASIDE_LIST SmbMmExchangesLookasideList[SENTINEL_EXCHANGE];
  93. INLINE PSMBCE_OBJECT_HEADER
  94. SmbMmAllocateObjectPool(
  95. SMBCEDB_OBJECT_TYPE ObjectType,
  96. ULONG PoolType,
  97. ULONG PoolSize)
  98. {
  99. KIRQL SavedIrql;
  100. PVOID pv = NULL;
  101. UCHAR Flags = 0;
  102. PSMBCE_OBJECT_HEADER pHeader = NULL;
  103. ASSERT((ObjectType >= 0) && (ObjectType < SMBCEDB_OT_SENTINEL));
  104. if (ObjectType == SMBCEDB_OT_REQUEST) {
  105. // Acquire the resource lock.
  106. KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
  107. if (!ExIsFullZone( &SmbMmRequestZone )) {
  108. pv = ExAllocateFromZone( &SmbMmRequestZone );
  109. Flags = SMBMM_ZONE_ALLOCATION;
  110. }
  111. // Release the resource lock.
  112. KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
  113. }
  114. if (pv == NULL) {
  115. PLIST_ENTRY pListEntry;
  116. pv = RxAllocatePoolWithTag(
  117. PoolType,
  118. PoolSize + sizeof(LIST_ENTRY),
  119. MRXSMB_MM_POOLTAG);
  120. if (pv != NULL) {
  121. pListEntry = (PLIST_ENTRY)pv;
  122. pHeader = (PSMBCE_OBJECT_HEADER)(pListEntry + 1);
  123. ExInterlockedInsertTailList(
  124. &SmbMmObjectsInUse[ObjectType],
  125. pListEntry,
  126. &SmbMmSpinLock);
  127. }
  128. } else {
  129. pHeader = (PSMBCE_OBJECT_HEADER)pv;
  130. }
  131. if (pHeader != NULL) {
  132. // Zero the memory.
  133. RtlZeroMemory( pHeader, PoolSize);
  134. pHeader->Flags = Flags;
  135. }
  136. return pHeader;
  137. }
  138. INLINE VOID
  139. SmbMmFreeObjectPool(
  140. PSMBCE_OBJECT_HEADER pHeader)
  141. {
  142. KIRQL SavedIrql;
  143. BOOLEAN ZoneAllocation = FALSE;
  144. PLIST_ENTRY pListEntry;
  145. ASSERT((pHeader->ObjectType >= 0) && (pHeader->ObjectType < SMBCEDB_OT_SENTINEL));
  146. // Acquire the resource lock.
  147. KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
  148. // Check if it was a zone allocation
  149. if (pHeader->Flags & SMBMM_ZONE_ALLOCATION) {
  150. ZoneAllocation = TRUE;
  151. ExFreeToZone(&SmbMmRequestZone,pHeader);
  152. } else {
  153. pListEntry = (PLIST_ENTRY)((PCHAR)pHeader - sizeof(LIST_ENTRY));
  154. RemoveEntryList(pListEntry);
  155. }
  156. // Release the resource lock.
  157. KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
  158. if (!ZoneAllocation) {
  159. RxFreePool(pListEntry);
  160. }
  161. }
  162. // Construction and destruction of various SMB connection engine objects
  163. //
  164. #define SmbMmInitializeServerEntry(pServerEntry) \
  165. InitializeListHead(&(pServerEntry)->OutstandingRequests.ListHead); \
  166. InitializeListHead(&(pServerEntry)->MidAssignmentRequests.ListHead); \
  167. InitializeListHead(&(pServerEntry)->Sessions.ListHead); \
  168. InitializeListHead(&(pServerEntry)->NetRoots.ListHead); \
  169. InitializeListHead(&(pServerEntry)->VNetRootContexts.ListHead); \
  170. InitializeListHead(&(pServerEntry)->ActiveExchanges); \
  171. InitializeListHead(&(pServerEntry)->ExpiredExchanges); \
  172. InitializeListHead(&(pServerEntry)->Sessions.DefaultSessionList); \
  173. (pServerEntry)->pTransport = NULL; \
  174. (pServerEntry)->pMidAtlas = NULL
  175. #define SmbMmInitializeSessionEntry(pSessionEntry) \
  176. InitializeListHead(&(pSessionEntry)->Requests.ListHead); \
  177. InitializeListHead(&(pSessionEntry)->SerializationList); \
  178. (pSessionEntry)->DefaultSessionLink.Flink = NULL; \
  179. (pSessionEntry)->DefaultSessionLink.Blink = NULL
  180. #define SmbMmInitializeNetRootEntry(pNetRootEntry) \
  181. InitializeListHead(&(pNetRootEntry)->Requests.ListHead)
  182. #define SmbMmUninitializeServerEntry(pServerEntry) \
  183. ASSERT(IsListEmpty(&(pServerEntry)->OutstandingRequests.ListHead) && \
  184. IsListEmpty(&(pServerEntry)->MidAssignmentRequests.ListHead) && \
  185. IsListEmpty(&(pServerEntry)->Sessions.ListHead) && \
  186. IsListEmpty(&(pServerEntry)->NetRoots.ListHead) && \
  187. ((pServerEntry)->pMidAtlas == NULL))
  188. #define SmbMmUninitializeSessionEntry(pSessionEntry) \
  189. ASSERT(IsListEmpty(&(pSessionEntry)->Requests.ListHead) && \
  190. ((pSessionEntry)->DefaultSessionLink.Flink == NULL))
  191. #define SmbMmUninitializeNetRootEntry(pNetRootEntry) \
  192. ASSERT(IsListEmpty(&(pNetRootEntry)->Requests.ListHead))
  193. #define SmbMmInitializeRequestEntry(pRequestEntry)
  194. #define SmbMmUninitializeRequestEntry(pRequestEntry)
  195. PVOID
  196. SmbMmAllocateObject(
  197. SMBCEDB_OBJECT_TYPE ObjectType)
  198. {
  199. PSMBCE_OBJECT_HEADER pHeader;
  200. ASSERT((ObjectType >= 0) && (ObjectType < SMBCEDB_OT_SENTINEL));
  201. pHeader = SmbMmAllocateObjectPool(
  202. ObjectType,
  203. NonPagedPool,
  204. ObjectSizeInBytes[ObjectType]);
  205. if (pHeader != NULL) {
  206. pHeader->NodeType = SMB_CONNECTION_ENGINE_NTC(ObjectType);
  207. pHeader->State = SMBCEDB_START_CONSTRUCTION;
  208. switch (ObjectType) {
  209. case SMBCEDB_OT_SERVER :
  210. SmbMmInitializeServerEntry((PSMBCEDB_SERVER_ENTRY)pHeader);
  211. break;
  212. case SMBCEDB_OT_NETROOT :
  213. SmbMmInitializeNetRootEntry((PSMBCEDB_NET_ROOT_ENTRY)pHeader);
  214. break;
  215. case SMBCEDB_OT_REQUEST :
  216. SmbMmInitializeRequestEntry((PSMBCEDB_REQUEST_ENTRY)pHeader);
  217. break;
  218. default:
  219. ASSERT(!"Valid Type for SmbMmAllocateObject");
  220. break;
  221. }
  222. }
  223. return pHeader;
  224. }
  225. VOID
  226. SmbMmFreeObject(
  227. PVOID pv)
  228. {
  229. PSMBCE_OBJECT_HEADER pHeader = (PSMBCE_OBJECT_HEADER)pv;
  230. switch (pHeader->ObjectType) {
  231. case SMBCEDB_OT_SERVER :
  232. SmbMmUninitializeServerEntry((PSMBCEDB_SERVER_ENTRY)pHeader);
  233. break;
  234. case SMBCEDB_OT_NETROOT :
  235. SmbMmUninitializeNetRootEntry((PSMBCEDB_NET_ROOT_ENTRY)pHeader);
  236. break;
  237. case SMBCEDB_OT_REQUEST :
  238. SmbMmUninitializeRequestEntry((PSMBCEDB_REQUEST_ENTRY)pHeader);
  239. break;
  240. default:
  241. ASSERT(!"Valid Type for SmbMmFreeObject");
  242. break;
  243. }
  244. SmbMmFreeObjectPool(pHeader);
  245. }
  246. PSMBCEDB_SESSION_ENTRY
  247. SmbMmAllocateSessionEntry(
  248. PSMBCEDB_SERVER_ENTRY pServerEntry)
  249. {
  250. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  251. SESSION_TYPE SessionType;
  252. ULONG SessionSize;
  253. PAGED_CODE();
  254. SessionSize = sizeof(SMBCEDB_SESSION_ENTRY);
  255. SessionType = LANMAN_SESSION;
  256. pSessionEntry = (PSMBCEDB_SESSION_ENTRY)
  257. SmbMmAllocateObjectPool(
  258. SMBCEDB_OT_SESSION,
  259. NonPagedPool,
  260. SessionSize);
  261. if (pSessionEntry != NULL) {
  262. pSessionEntry->Header.NodeType = SMB_CONNECTION_ENGINE_NTC(SMBCEDB_OT_SESSION);
  263. pSessionEntry->Header.State = SMBCEDB_START_CONSTRUCTION;
  264. pSessionEntry->Session.Type = SessionType;
  265. SmbMmInitializeSessionEntry(pSessionEntry);
  266. pSessionEntry->Session.CredentialHandle.dwUpper = 0xffffffff;
  267. pSessionEntry->Session.CredentialHandle.dwLower = 0xffffffff;
  268. pSessionEntry->Session.SecurityContextHandle.dwUpper = 0xffffffff;
  269. pSessionEntry->Session.SecurityContextHandle.dwLower = 0xffffffff;
  270. }
  271. return pSessionEntry;
  272. }
  273. VOID
  274. SmbMmFreeSessionEntry(
  275. PSMBCEDB_SESSION_ENTRY pSessionEntry)
  276. {
  277. PAGED_CODE();
  278. SmbMmUninitializeSessionEntry(pSessionEntry);
  279. SmbMmFreeObjectPool(&pSessionEntry->Header);
  280. }
  281. PVOID
  282. SmbMmAllocateExchange(
  283. SMB_EXCHANGE_TYPE ExchangeType,
  284. PVOID pv)
  285. {
  286. KIRQL SavedIrql;
  287. ULONG SizeInBytes;
  288. USHORT Flags = 0;
  289. PSMB_EXCHANGE pExchange = NULL;
  290. PLIST_ENTRY pListEntry;
  291. ASSERT((ExchangeType >= 0) && (ExchangeType < SENTINEL_EXCHANGE));
  292. if (pv==NULL) {
  293. pv = ExAllocateFromNPagedLookasideList(
  294. &SmbMmExchangesLookasideList[ExchangeType]);
  295. } else {
  296. Flags |= SMBCE_EXCHANGE_NOT_FROM_POOL;
  297. }
  298. if (pv != NULL) {
  299. // Initialize the object header
  300. pExchange = (PSMB_EXCHANGE)(pv);
  301. // Zero the memory.
  302. RtlZeroMemory(
  303. pExchange,
  304. ExchangeSizeInBytes[ExchangeType]);
  305. pExchange->NodeTypeCode = SMB_EXCHANGE_NTC(ExchangeType);
  306. pExchange->NodeByteSize = (USHORT)ExchangeSizeInBytes[ExchangeType];
  307. pExchange->SmbCeState = SMBCE_EXCHANGE_INITIALIZATION_START;
  308. pExchange->SmbCeFlags = Flags;
  309. InitializeListHead(&pExchange->ExchangeList);
  310. switch (pExchange->Type) {
  311. case CONSTRUCT_NETROOT_EXCHANGE:
  312. pExchange->pDispatchVector = &ConstructNetRootExchangeDispatch;
  313. break;
  314. case TRANSACT_EXCHANGE :
  315. pExchange->pDispatchVector = &TransactExchangeDispatch;
  316. break;
  317. case ADMIN_EXCHANGE:
  318. pExchange->pDispatchVector = &AdminExchangeDispatch;
  319. break;
  320. }
  321. // Acquire the resource lock.
  322. KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
  323. InsertTailList(
  324. &SmbMmExchangesInUse[pExchange->Type],
  325. &pExchange->SmbMmInUseListEntry);
  326. pExchange->Id = SmbMmExchangeId++;
  327. // Release the resource lock.
  328. KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
  329. }
  330. return pExchange;
  331. }
  332. VOID
  333. SmbMmFreeExchange(
  334. PSMB_EXCHANGE pExchange)
  335. {
  336. if (pExchange != NULL) {
  337. SMB_EXCHANGE_TYPE ExchangeType;
  338. KIRQL SavedIrql;
  339. ExchangeType = pExchange->Type;
  340. ASSERT((ExchangeType >= 0) && (ExchangeType < SENTINEL_EXCHANGE));
  341. // Acquire the resource lock.
  342. KeAcquireSpinLock( &SmbMmSpinLock, &SavedIrql );
  343. RemoveEntryList(&pExchange->SmbMmInUseListEntry);
  344. // Release the resource lock.
  345. KeReleaseSpinLock( &SmbMmSpinLock, SavedIrql );
  346. if (!FlagOn(pExchange->SmbCeFlags,SMBCE_EXCHANGE_NOT_FROM_POOL)) {
  347. ExFreeToNPagedLookasideList(
  348. &SmbMmExchangesLookasideList[ExchangeType],
  349. pExchange);
  350. }
  351. }
  352. }
  353. PVOID
  354. SmbMmAllocateServerTransport(
  355. SMBCE_SERVER_TRANSPORT_TYPE ServerTransportType)
  356. {
  357. PSMBCE_OBJECT_HEADER pHeader;
  358. ULONG AllocationSize;
  359. ULONG PoolTag;
  360. PAGED_CODE();
  361. switch (ServerTransportType) {
  362. case SMBCE_STT_VC:
  363. AllocationSize = sizeof(SMBCE_SERVER_VC_TRANSPORT);
  364. PoolTag = MRXSMB_VC_POOLTAG;
  365. break;
  366. default:
  367. ASSERT(!"Valid Server Transport Type");
  368. return NULL;
  369. }
  370. pHeader = (PSMBCE_OBJECT_HEADER)
  371. RxAllocatePoolWithTag(
  372. NonPagedPool,
  373. AllocationSize,
  374. PoolTag);
  375. if (pHeader != NULL) {
  376. PSMBCE_SERVER_TRANSPORT pServerTransport;
  377. RtlZeroMemory(pHeader,AllocationSize);
  378. pHeader->ObjectCategory = SMB_SERVER_TRANSPORT_CATEGORY;
  379. pHeader->ObjectType = (UCHAR)ServerTransportType;
  380. pHeader->SwizzleCount = 0;
  381. pHeader->State = 0;
  382. pHeader->Flags = 0;
  383. pServerTransport = (PSMBCE_SERVER_TRANSPORT)pHeader;
  384. pServerTransport->pRundownEvent = NULL;
  385. switch (ServerTransportType) {
  386. case SMBCE_STT_VC:
  387. {
  388. PSMBCE_SERVER_VC_TRANSPORT pVcTransport;
  389. pVcTransport = (PSMBCE_SERVER_VC_TRANSPORT)pHeader;
  390. }
  391. break;
  392. default:
  393. break;
  394. }
  395. }
  396. return pHeader;
  397. }
  398. VOID
  399. SmbMmFreeServerTransport(
  400. PSMBCE_SERVER_TRANSPORT pServerTransport)
  401. {
  402. PAGED_CODE();
  403. ASSERT((pServerTransport->SwizzleCount == 0) &&
  404. (pServerTransport->ObjectCategory == SMB_SERVER_TRANSPORT_CATEGORY));
  405. RxFreePool(pServerTransport);
  406. }
  407. NTSTATUS SmbMmInit()
  408. /*++
  409. Routine Description:
  410. This routine initialises the connection engine structures for memory management
  411. Return Value:
  412. STATUS_SUCCESS if successful, otherwise an informative error code.
  413. --*/
  414. {
  415. NTSTATUS Status = STATUS_SUCCESS;
  416. ULONG ZoneSegmentSize;
  417. PAGED_CODE();
  418. // Initialize the resource lock for the zone allocator.
  419. KeInitializeSpinLock( &SmbMmSpinLock );
  420. SmbMmRequestZoneEntrySize = QuadAlign(sizeof(SMBCEDB_REQUEST_ENTRY));
  421. // Currently the request zone size is restricted to that of a page. This can and should
  422. // be fine tuned.
  423. ZoneSegmentSize = PAGE_SIZE;
  424. SmbMmRequestZoneSegmentPtr = RxAllocatePoolWithTag(
  425. NonPagedPool,
  426. ZoneSegmentSize,
  427. MRXSMB_MM_POOLTAG);
  428. if (SmbMmRequestZoneSegmentPtr != NULL) {
  429. SMB_EXCHANGE_TYPE ExchangeType;
  430. ExInitializeZone(
  431. &SmbMmRequestZone,
  432. SmbMmRequestZoneEntrySize,
  433. SmbMmRequestZoneSegmentPtr,
  434. ZoneSegmentSize );
  435. // set up the sizes for allocation.
  436. ObjectSizeInBytes[SMBCEDB_OT_SERVER] = sizeof(SMBCEDB_SERVER_ENTRY);
  437. ObjectSizeInBytes[SMBCEDB_OT_NETROOT] = sizeof(SMBCEDB_NET_ROOT_ENTRY);
  438. ObjectSizeInBytes[SMBCEDB_OT_SESSION] = sizeof(SMBCEDB_SESSION_ENTRY);
  439. ObjectSizeInBytes[SMBCEDB_OT_REQUEST] = sizeof(SMBCEDB_REQUEST_ENTRY);
  440. ExchangeSizeInBytes[CONSTRUCT_NETROOT_EXCHANGE] = sizeof(SMB_CONSTRUCT_NETROOT_EXCHANGE);
  441. ExchangeSizeInBytes[TRANSACT_EXCHANGE] = sizeof(SMB_TRANSACT_EXCHANGE);
  442. ExchangeSizeInBytes[ORDINARY_EXCHANGE] = sizeof(SMB_PSE_ORDINARY_EXCHANGE);
  443. ExchangeSizeInBytes[ADMIN_EXCHANGE] = sizeof(SMB_ADMIN_EXCHANGE);
  444. InitializeListHead(&SmbMmExchangesInUse[CONSTRUCT_NETROOT_EXCHANGE]);
  445. ExInitializeNPagedLookasideList(
  446. &SmbMmExchangesLookasideList[CONSTRUCT_NETROOT_EXCHANGE],
  447. ExAllocatePoolWithTag,
  448. ExFreePool,
  449. 0,
  450. sizeof(SMB_CONSTRUCT_NETROOT_EXCHANGE),
  451. MRXSMB_MM_POOLTAG,
  452. 1);
  453. InitializeListHead(&SmbMmExchangesInUse[TRANSACT_EXCHANGE]);
  454. ExInitializeNPagedLookasideList(
  455. &SmbMmExchangesLookasideList[TRANSACT_EXCHANGE],
  456. ExAllocatePoolWithTag,
  457. ExFreePool,
  458. 0,
  459. sizeof(SMB_TRANSACT_EXCHANGE),
  460. MRXSMB_MM_POOLTAG,
  461. 2);
  462. InitializeListHead(&SmbMmExchangesInUse[ORDINARY_EXCHANGE]);
  463. ExInitializeNPagedLookasideList(
  464. &SmbMmExchangesLookasideList[ORDINARY_EXCHANGE],
  465. ExAllocatePoolWithTag,
  466. ExFreePool,
  467. 0,
  468. sizeof(SMB_PSE_ORDINARY_EXCHANGE),
  469. MRXSMB_MM_POOLTAG,
  470. 4);
  471. InitializeListHead(&SmbMmExchangesInUse[ADMIN_EXCHANGE]);
  472. ExInitializeNPagedLookasideList(
  473. &SmbMmExchangesLookasideList[ADMIN_EXCHANGE],
  474. ExAllocatePoolWithTag,
  475. ExFreePool,
  476. 0,
  477. sizeof(SMB_ADMIN_EXCHANGE),
  478. MRXSMB_MM_POOLTAG,
  479. 1);
  480. InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_SERVER]);
  481. InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_SESSION]);
  482. InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_NETROOT]);
  483. InitializeListHead(&SmbMmObjectsInUse[SMBCEDB_OT_REQUEST]);
  484. SmbMmExchangeId = 1;
  485. } else {
  486. Status = STATUS_INSUFFICIENT_RESOURCES;
  487. }
  488. return Status;
  489. }
  490. VOID SmbMmTearDown()
  491. /*++
  492. Routine Description:
  493. This routine tears down the memory management structures in the SMB connection
  494. engine
  495. --*/
  496. {
  497. NTSTATUS Status;
  498. PAGED_CODE();
  499. // free the segment associated with RxCe object allocation.
  500. RxFreePool(SmbMmRequestZoneSegmentPtr);
  501. ExDeleteNPagedLookasideList(
  502. &SmbMmExchangesLookasideList[CONSTRUCT_NETROOT_EXCHANGE]);
  503. ExDeleteNPagedLookasideList(
  504. &SmbMmExchangesLookasideList[TRANSACT_EXCHANGE]);
  505. ExDeleteNPagedLookasideList(
  506. &SmbMmExchangesLookasideList[ORDINARY_EXCHANGE]);
  507. ExDeleteNPagedLookasideList(
  508. &SmbMmExchangesLookasideList[ADMIN_EXCHANGE]);
  509. }