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.

2553 lines
70 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fspinit.c
  5. Abstract:
  6. This module implements the initialization phase of the LAN Manager
  7. server File System Process.
  8. Author:
  9. Chuck Lenzmeier (chuckl) 22-Sep-1989
  10. David Treadwell (davidtr)
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "fspinit.tmh"
  15. #pragma hdrstop
  16. #define BugCheckFileId SRV_FILE_FSPINIT
  17. //
  18. // Forward declarations.
  19. //
  20. PIRP
  21. DequeueConfigurationIrp (
  22. VOID
  23. );
  24. STATIC
  25. NTSTATUS
  26. InitializeServer (
  27. VOID
  28. );
  29. STATIC
  30. NTSTATUS
  31. TerminateServer (
  32. VOID
  33. );
  34. VOID
  35. SrvFreeRegTables (
  36. VOID
  37. );
  38. VOID
  39. SrvGetRegTables (
  40. VOID
  41. );
  42. #if SRVNTVERCHK
  43. VOID
  44. SrvGetRegClientNumber (
  45. VOID
  46. );
  47. #endif
  48. VOID
  49. StartQueueDepthComputations(
  50. PWORK_QUEUE queue
  51. );
  52. VOID
  53. StopQueueDepthComputations(
  54. PWORK_QUEUE queue
  55. );
  56. VOID
  57. ComputeAvgQueueDepth (
  58. IN PKDPC Dpc,
  59. IN PVOID DeferredContext,
  60. IN PVOID SystemArgument1,
  61. IN PVOID SystemArgument2
  62. );
  63. BOOLEAN
  64. GenerateCrcTable();
  65. BOOLEAN
  66. CleanupCrcTable();
  67. #ifdef ALLOC_PRAGMA
  68. #pragma alloc_text( PAGE, SrvConfigurationThread )
  69. #pragma alloc_text( PAGE, InitializeServer )
  70. #pragma alloc_text( PAGE, TerminateServer )
  71. #pragma alloc_text( PAGE, SrvFreeRegTables )
  72. #pragma alloc_text( PAGE, SrvGetRegTables )
  73. #if SRVNTVERCHK
  74. #pragma alloc_text( PAGE, SrvGetRegClientNumber )
  75. #endif
  76. #pragma alloc_text( PAGE, DequeueConfigurationIrp )
  77. #pragma alloc_text( PAGE, StartQueueDepthComputations )
  78. #endif
  79. extern ULONG SrvWmiInitialized;
  80. VOID
  81. SrvConfigurationThread (
  82. IN PDEVICE_OBJECT pDevice,
  83. IN PIO_WORKITEM pWorkItem
  84. )
  85. /*++
  86. Routine Description:
  87. This routine processes configuration IRPs.
  88. Arguments:
  89. None.
  90. Return Value:
  91. None.
  92. --*/
  93. {
  94. NTSTATUS status;
  95. PIRP irp;
  96. PIO_STACK_LOCATION irpSp;
  97. ULONG code;
  98. PAGED_CODE( );
  99. IF_DEBUG(FSP1) KdPrint(( "SrvConfigurationThread entered\n" ));
  100. //
  101. // Loop processing requests.
  102. //
  103. while ( TRUE ) {
  104. irp = DequeueConfigurationIrp( );
  105. if ( irp == NULL ) break;
  106. ASSERT( (LONG)SrvConfigurationIrpsInProgress >= 1 );
  107. //
  108. // Get the IRP stack pointer.
  109. //
  110. irpSp = IoGetCurrentIrpStackLocation( irp );
  111. if( irpSp->MajorFunction == IRP_MJ_CLOSE ) {
  112. //
  113. // If the dispatcher routed this irp here, it means
  114. // that we unexpectededly got the last handle close without
  115. // having gotten cleanly terminated first. Ok, so we should
  116. // shut ourselves down, since we can't sensibly run without
  117. // our usermode counterpart.
  118. //
  119. ACQUIRE_LOCK( &SrvStartupShutdownLock );
  120. status = TerminateServer();
  121. RELEASE_LOCK( &SrvStartupShutdownLock );
  122. } else {
  123. ASSERT( irpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL );
  124. try {
  125. //
  126. // Dispatch on the FsControlCode.
  127. //
  128. code = irpSp->Parameters.FileSystemControl.FsControlCode;
  129. switch ( code ) {
  130. case FSCTL_SRV_STARTUP:
  131. ACQUIRE_LOCK( &SrvStartupShutdownLock );
  132. status = InitializeServer();
  133. if ( !NT_SUCCESS(status) ) {
  134. //
  135. // Terminate the server FSP.
  136. //
  137. (void)TerminateServer();
  138. }
  139. RELEASE_LOCK( &SrvStartupShutdownLock );
  140. break;
  141. case FSCTL_SRV_SHUTDOWN:
  142. ACQUIRE_LOCK( &SrvStartupShutdownLock );
  143. status = TerminateServer();
  144. RELEASE_LOCK( &SrvStartupShutdownLock );
  145. //
  146. // If there is more than one handle open to the server
  147. // device (i.e., any handles other than the server service's
  148. // handle), return a special status code to the caller (who
  149. // should be the server service). This tells the caller to
  150. // NOT unload the driver, in order prevent weird situations
  151. // where the driver is sort of unloaded, so it can't be used
  152. // but also can't be reloaded, thus preventing the server
  153. // from being restarted.
  154. //
  155. if( NT_SUCCESS( status ) && SrvOpenCount != 1 ) {
  156. status = STATUS_SERVER_HAS_OPEN_HANDLES;
  157. }
  158. break;
  159. case FSCTL_SRV_REGISTRY_CHANGE:
  160. //
  161. // The Parameters section of the server service registry has changed.
  162. // That's likely due to somebody changing the Null Session pipe or
  163. // share lists. Pick up the new settings.
  164. //
  165. ACQUIRE_LOCK( &SrvConfigurationLock );
  166. SrvFreeRegTables();
  167. SrvGetRegTables();
  168. #if SRVNTVERCHK
  169. SrvGetRegClientNumber();
  170. #endif
  171. RELEASE_LOCK( &SrvConfigurationLock );
  172. status = STATUS_SUCCESS;
  173. break;
  174. case FSCTL_SRV_BEGIN_PNP_NOTIFICATIONS:
  175. //
  176. // If somebody tries to shut down the server while
  177. // we are registering our handlers, block them until
  178. // we are finished.
  179. //
  180. ACQUIRE_LOCK( &SrvStartupShutdownLock );
  181. {
  182. TDI_CLIENT_INTERFACE_INFO ClientInterfaceInfo;
  183. RtlZeroMemory(&ClientInterfaceInfo, sizeof(TDI_CLIENT_INTERFACE_INFO));
  184. ClientInterfaceInfo.MajorTdiVersion = 2;
  185. ClientInterfaceInfo.MinorTdiVersion = 0;
  186. ClientInterfaceInfo.ClientName = &StrRegSrvPnpClientName;
  187. ClientInterfaceInfo.BindingHandler = SrvPnpBindingHandler;
  188. ClientInterfaceInfo.PnPPowerHandler = SrvPnpPowerHandler;
  189. status = TdiRegisterPnPHandlers(
  190. &ClientInterfaceInfo,
  191. sizeof( ClientInterfaceInfo ),
  192. &SrvTdiNotificationHandle
  193. );
  194. if (status != STATUS_SUCCESS) {
  195. SrvTdiNotificationHandle = NULL;
  196. }
  197. }
  198. RELEASE_LOCK( &SrvStartupShutdownLock );
  199. if( !NT_SUCCESS( status ) ) {
  200. IF_DEBUG( PNP ) {
  201. KdPrint(("TdiRegisterNotificationHandler: status %X\n", status ));
  202. }
  203. SrvLogServiceFailure( SRV_SVC_PNP_TDI_NOTIFICATION, status );
  204. }
  205. //
  206. // Allow the transports to begin receiving connections
  207. //
  208. SrvCompletedPNPRegistration = TRUE;
  209. break;
  210. case FSCTL_SRV_XACTSRV_CONNECT:
  211. {
  212. ANSI_STRING ansiPortName;
  213. UNICODE_STRING portName;
  214. IF_DEBUG(XACTSRV) {
  215. KdPrint(( "SrvFspConfigurationThread: XACTSRV FSCTL "
  216. "received.\n" ));
  217. }
  218. ansiPortName.Buffer = irp->AssociatedIrp.SystemBuffer;
  219. ansiPortName.Length =
  220. (USHORT)irpSp->Parameters.FileSystemControl.InputBufferLength;
  221. status = RtlAnsiStringToUnicodeString(
  222. &portName,
  223. &ansiPortName,
  224. TRUE
  225. );
  226. if ( NT_SUCCESS(status) ) {
  227. status = SrvXsConnect( &portName );
  228. RtlFreeUnicodeString( &portName );
  229. }
  230. break;
  231. }
  232. case FSCTL_SRV_XACTSRV_DISCONNECT:
  233. {
  234. //
  235. // This is now obsolete
  236. //
  237. status = STATUS_SUCCESS;
  238. break;
  239. }
  240. case FSCTL_SRV_SEND_DATAGRAM:
  241. {
  242. ANSI_STRING domain;
  243. ULONG buffer1Length;
  244. PVOID buffer2;
  245. PSERVER_REQUEST_PACKET srp;
  246. buffer1Length = ALIGN_UP(
  247. irpSp->Parameters.FileSystemControl.InputBufferLength,
  248. PVOID );
  249. buffer2 = (PCHAR)irp->AssociatedIrp.SystemBuffer + buffer1Length;
  250. srp = irp->AssociatedIrp.SystemBuffer;
  251. //
  252. // Send the second-class mailslot in Buffer2 to the domain
  253. // specified in srp->Name1 on transport specified by srp->Name2.
  254. //
  255. domain = *((PANSI_STRING) &srp->Name1);
  256. status = SrvSendDatagram(
  257. &domain,
  258. ( srp->Name2.Length != 0 ? &srp->Name2 : NULL ),
  259. buffer2,
  260. irpSp->Parameters.FileSystemControl.OutputBufferLength
  261. );
  262. ExFreePool( irp->AssociatedIrp.SystemBuffer );
  263. DEBUG irp->AssociatedIrp.SystemBuffer = NULL;
  264. break;
  265. }
  266. case FSCTL_SRV_NET_FILE_CLOSE:
  267. case FSCTL_SRV_NET_SERVER_XPORT_ADD:
  268. case FSCTL_SRV_NET_SERVER_XPORT_DEL:
  269. case FSCTL_SRV_NET_SESSION_DEL:
  270. case FSCTL_SRV_NET_SHARE_ADD:
  271. case FSCTL_SRV_NET_SHARE_DEL:
  272. {
  273. PSERVER_REQUEST_PACKET srp;
  274. PVOID buffer2;
  275. ULONG buffer1Length;
  276. ULONG buffer2Length;
  277. //
  278. // These APIs are handled in the server FSP because they
  279. // open or close FSP handles.
  280. //
  281. ACQUIRE_LOCK_SHARED( &SrvConfigurationLock );
  282. if( SrvFspTransitioning == TRUE && SrvFspActive == TRUE ) {
  283. //
  284. // The server is coming down. Do not allow these
  285. // irps to continue.
  286. //
  287. RELEASE_LOCK( &SrvConfigurationLock );
  288. status = STATUS_SERVER_NOT_STARTED;
  289. break;
  290. }
  291. RELEASE_LOCK( &SrvConfigurationLock );
  292. //
  293. // Get the server request packet and secondary input buffer
  294. // pointers.
  295. //
  296. buffer1Length = ALIGN_UP(
  297. irpSp->Parameters.FileSystemControl.InputBufferLength,
  298. PVOID );
  299. buffer2Length =
  300. irpSp->Parameters.FileSystemControl.OutputBufferLength;
  301. srp = irp->AssociatedIrp.SystemBuffer;
  302. buffer2 = (PCHAR)srp + buffer1Length;
  303. //
  304. // Dispatch the API request to the appripriate API processing
  305. // routine.
  306. //
  307. status = SrvApiDispatchTable[ SRV_API_INDEX(code) ](
  308. srp,
  309. buffer2,
  310. buffer2Length
  311. );
  312. break;
  313. }
  314. default:
  315. IF_DEBUG(ERRORS) {
  316. KdPrint((
  317. "SrvFspConfigurationThread: Invalid control code %lx\n",
  318. irpSp->Parameters.FileSystemControl.FsControlCode ));
  319. }
  320. status = STATUS_INVALID_PARAMETER;
  321. }
  322. } except(EXCEPTION_EXECUTE_HANDLER) {
  323. status = GetExceptionCode();
  324. }
  325. }
  326. //
  327. // Make sure we're still at PASSIVE_LEVEL
  328. //
  329. if( KeGetCurrentIrql() > PASSIVE_LEVEL )
  330. {
  331. goto bad_irql_failure;
  332. }
  333. //
  334. // Complete the IO request.
  335. //
  336. irp->IoStatus.Status = status;
  337. IoCompleteRequest( irp, 2 );
  338. //
  339. // Make sure we're still at PASSIVE_LEVEL
  340. //
  341. if( KeGetCurrentIrql() > PASSIVE_LEVEL )
  342. {
  343. goto bad_irql_failure;
  344. }
  345. ASSERT( (LONG)SrvConfigurationIrpsInProgress >= 0 );
  346. // Make sure we don't continue if there are no IRP's left
  347. if( InterlockedDecrement( (PLONG)&SrvConfigurationIrpsInProgress ) == 0 )
  348. {
  349. break;
  350. }
  351. }
  352. IoFreeWorkItem( pWorkItem );
  353. return;
  354. bad_irql_failure:
  355. #if DBG
  356. DbgPrint( "ERROR: SrvConfigurationThread returning at >PASSIVE level\n" );
  357. DbgBreakPoint();
  358. #endif
  359. IoFreeWorkItem( pWorkItem );
  360. return;
  361. } // SrvConfigurationThread
  362. PIRP
  363. DequeueConfigurationIrp (
  364. VOID
  365. )
  366. /*++
  367. Routine Description:
  368. This routine retrieves an IRP from the configuration work queue.
  369. Arguments:
  370. None.
  371. Return Value:
  372. PIRP - Pointer to configuration IRP, or NULL.
  373. --*/
  374. {
  375. PLIST_ENTRY listEntry;
  376. PIRP irp;
  377. PAGED_CODE( );
  378. //
  379. // Take an IRP off the configuration queue.
  380. //
  381. ACQUIRE_LOCK( &SrvConfigurationLock );
  382. listEntry = RemoveHeadList( &SrvConfigurationWorkQueue );
  383. if ( listEntry == &SrvConfigurationWorkQueue ) {
  384. //
  385. // The queue is empty.
  386. //
  387. irp = NULL;
  388. } else {
  389. irp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry );
  390. }
  391. RELEASE_LOCK( &SrvConfigurationLock );
  392. return irp;
  393. } // DequeueConfigurationIrp
  394. STATIC
  395. NTSTATUS
  396. InitializeServer (
  397. VOID
  398. )
  399. /*++
  400. Routine Description:
  401. This routine initializes the server.
  402. Arguments:
  403. None.
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. NTSTATUS status;
  409. CLONG i;
  410. PWORK_CONTEXT workContext;
  411. OBJECT_ATTRIBUTES objectAttributes;
  412. IO_STATUS_BLOCK ioStatusBlock;
  413. OBJECT_HANDLE_INFORMATION handleInformation;
  414. PSID AdminSid;
  415. PSID AnonymousSid;
  416. PACL Acl;
  417. ULONG length;
  418. SID_IDENTIFIER_AUTHORITY BuiltinAuthority = SECURITY_NT_AUTHORITY;
  419. PWORK_QUEUE queue;
  420. HANDLE handle;
  421. UNICODE_STRING string;
  422. PAGED_CODE();
  423. //
  424. // If running as an Advanced Server, lock all pageable server code.
  425. //
  426. if ( SrvProductTypeServer ) {
  427. for ( i = 0; i < SRV_CODE_SECTION_MAX; i++ ) {
  428. SrvReferenceUnlockableCodeSection( i );
  429. }
  430. }
  431. //
  432. // Initialize the server start time
  433. //
  434. KeQuerySystemTime( &SrvStatistics.StatisticsStartTime );
  435. //
  436. // Get actual alert service name using the display name found in the
  437. // registry.
  438. //
  439. SrvGetAlertServiceName( );
  440. //
  441. // Get the Os versions strings.
  442. //
  443. SrvGetOsVersionString( );
  444. //
  445. // Get the list of null session pipes and shares
  446. //
  447. SrvGetRegTables( );
  448. #if SRVNTVERCHK
  449. SrvGetRegClientNumber();
  450. #endif
  451. #if MULTIPROCESSOR
  452. //
  453. // Allocate and init the nonblocking work queues, paying attention to cache lines
  454. //
  455. i = SrvNumberOfProcessors * sizeof( *SrvWorkQueues );
  456. i += CACHE_LINE_SIZE;
  457. SrvWorkQueuesBase = ALLOCATE_NONPAGED_POOL( i, BlockTypeWorkQueue );
  458. if( SrvWorkQueuesBase == NULL ) {
  459. return STATUS_INSUFF_SERVER_RESOURCES;
  460. }
  461. //
  462. // Round up the start of the work queue data structure to
  463. // the next cache line boundry
  464. //
  465. SrvWorkQueues = (PWORK_QUEUE)(((ULONG_PTR)SrvWorkQueuesBase + CACHE_LINE_SIZE-1) &
  466. ~(CACHE_LINE_SIZE-1));
  467. #endif
  468. eSrvWorkQueues = SrvWorkQueues + SrvNumberOfProcessors;
  469. RtlZeroMemory( SrvWorkQueues, (char *)eSrvWorkQueues - (char *)SrvWorkQueues );
  470. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++ ) {
  471. KeInitializeQueue( &queue->Queue, 1 );
  472. queue->WaitMode = SrvProductTypeServer ? KernelMode : UserMode;
  473. queue->MaxThreads = SrvMaxThreadsPerQueue;
  474. queue->MaximumWorkItems = SrvMaxReceiveWorkItemCount / SrvNumberOfProcessors;
  475. queue->MinFreeWorkItems = SrvMinReceiveQueueLength / SrvNumberOfProcessors;
  476. queue->MaxFreeRfcbs = SrvMaxFreeRfcbs;
  477. queue->MaxFreeMfcbs = SrvMaxFreeMfcbs;
  478. ExInitializeSListHead(&queue->InitialWorkItemList);
  479. ExInitializeSListHead(&queue->NormalWorkItemList);
  480. ExInitializeSListHead(&queue->RawModeWorkItemList);
  481. ExInitializeSListHead(&queue->RfcbFreeList);
  482. ExInitializeSListHead(&queue->MfcbFreeList);
  483. queue->PagedPoolLookAsideList.MaxSize = SrvMaxPagedPoolChunkSize;
  484. queue->NonPagedPoolLookAsideList.MaxSize = SrvMaxNonPagedPoolChunkSize;
  485. queue->CreateMoreWorkItems.CurrentWorkQueue = queue;
  486. queue->CreateMoreWorkItems.BlockHeader.ReferenceCount = 1;
  487. queue->IdleTimeOut.QuadPart = SrvIdleThreadTimeOut;
  488. INITIALIZE_SPIN_LOCK( &queue->SpinLock );
  489. SET_SERVER_TIME( queue );
  490. #if MULTIPROCESSOR
  491. StartQueueDepthComputations( queue );
  492. #endif
  493. }
  494. RtlZeroMemory( &SrvDoSWorkItem, sizeof(SPECIAL_WORK_ITEM) );
  495. SrvDoSWorkItem.BlockHeader.ReferenceCount = 1;
  496. SrvDoSWorkItemTearDown = SRV_DOS_TEARDOWN_MIN;
  497. KeInitializeSpinLock( &SrvDosSpinLock );
  498. //
  499. // Init the Blocking work queue
  500. //
  501. #if MULTIPROCESSOR
  502. if( SrvNumberOfProcessors < 4 )
  503. {
  504. i = 1 * sizeof( *SrvWorkQueues );
  505. i += CACHE_LINE_SIZE;
  506. }
  507. //
  508. // Allocate and init the nonblocking work queues, paying attention to cache lines
  509. //
  510. SrvBlockingWorkQueuesBase = ALLOCATE_NONPAGED_POOL( i, BlockTypeWorkQueue );
  511. if( SrvBlockingWorkQueuesBase == NULL ) {
  512. return STATUS_INSUFF_SERVER_RESOURCES;
  513. }
  514. //
  515. // Round up the start of the work queue data structure to
  516. // the next cache line boundry
  517. //
  518. SrvBlockingWorkQueues = (PWORK_QUEUE)(((ULONG_PTR)SrvBlockingWorkQueuesBase + CACHE_LINE_SIZE-1) &
  519. ~(CACHE_LINE_SIZE-1));
  520. #endif
  521. eSrvBlockingWorkQueues = SrvBlockingWorkQueues + ( (SrvNumberOfProcessors<4) ? 1 : SrvNumberOfProcessors);
  522. RtlZeroMemory( SrvBlockingWorkQueues, (char *)eSrvBlockingWorkQueues - (char *)SrvBlockingWorkQueues );
  523. for( queue = SrvBlockingWorkQueues; queue < eSrvBlockingWorkQueues; queue++ ) {
  524. KeInitializeQueue( &queue->Queue, 1 );
  525. queue->WaitMode = SrvProductTypeServer ? KernelMode : UserMode;
  526. queue->MaxThreads = SrvMaxThreadsPerQueue*2;
  527. queue->IdleTimeOut.QuadPart = SrvIdleThreadTimeOut;
  528. INITIALIZE_SPIN_LOCK( &queue->SpinLock );
  529. SET_SERVER_TIME( queue );
  530. }
  531. //
  532. // Initialize the LPC upcall work queue
  533. //
  534. RtlZeroMemory( &SrvLpcWorkQueue, sizeof(WORK_QUEUE) );
  535. KeInitializeQueue( &SrvLpcWorkQueue.Queue, 1 );
  536. SrvLpcWorkQueue.WaitMode = SrvProductTypeServer ? KernelMode : UserMode;
  537. SrvLpcWorkQueue.MaxThreads = SrvMaxThreadsPerQueue;
  538. SrvLpcWorkQueue.IdleTimeOut.QuadPart = SrvIdleThreadTimeOut;
  539. INITIALIZE_SPIN_LOCK( &SrvLpcWorkQueue.SpinLock );
  540. SET_SERVER_TIME( &SrvLpcWorkQueue );
  541. //
  542. // Build the receive work item list.
  543. //
  544. status = SrvAllocateInitialWorkItems( );
  545. if ( !NT_SUCCESS(status) ) {
  546. return status;
  547. }
  548. //
  549. // Build the raw mode work item list, and spread it around
  550. // the processors
  551. //
  552. queue = SrvWorkQueues;
  553. for ( i = 0; i < SrvInitialRawModeWorkItemCount; i++ ) {
  554. SrvAllocateRawModeWorkItem( &workContext, queue );
  555. if ( workContext == NULL ) {
  556. return STATUS_INSUFFICIENT_RESOURCES;
  557. }
  558. GET_SERVER_TIME( queue, &workContext->Timestamp );
  559. SrvRequeueRawModeWorkItem( workContext );
  560. if( ++queue == eSrvWorkQueues )
  561. queue = SrvWorkQueues;
  562. }
  563. //
  564. // Create worker threads.
  565. //
  566. status = SrvCreateWorkerThreads( );
  567. if ( !NT_SUCCESS(status) ) {
  568. return status;
  569. }
  570. //
  571. // Initialize the scavenger.
  572. //
  573. status = SrvInitializeScavenger( );
  574. if ( !NT_SUCCESS(status) ) {
  575. return status;
  576. }
  577. //
  578. // Initialize the global ordered lists.
  579. //
  580. // *** WARNING: Be careful when changing the locks associated with
  581. // these ordered lists. Certain places in the code depend on
  582. // the level of the lock associated with a list. Examples
  583. // include (but are NOT limited to) SrvSmbSessionSetupAndX,
  584. // SrvSmbTreeConnect, SrvSmbTreeConnectAndX, and CompleteOpen.
  585. //
  586. SrvInitializeOrderedList(
  587. &SrvEndpointList,
  588. FIELD_OFFSET( ENDPOINT, GlobalEndpointListEntry ),
  589. SrvCheckAndReferenceEndpoint,
  590. SrvDereferenceEndpoint,
  591. &SrvEndpointLock
  592. );
  593. SrvInitializeOrderedList(
  594. &SrvRfcbList,
  595. FIELD_OFFSET( RFCB, GlobalRfcbListEntry ),
  596. SrvCheckAndReferenceRfcb,
  597. SrvDereferenceRfcb,
  598. &SrvOrderedListLock
  599. );
  600. SrvInitializeOrderedList(
  601. &SrvSessionList,
  602. FIELD_OFFSET( SESSION, GlobalSessionListEntry ),
  603. SrvCheckAndReferenceSession,
  604. SrvDereferenceSession,
  605. &SrvOrderedListLock
  606. );
  607. SrvInitializeOrderedList(
  608. &SrvTreeConnectList,
  609. FIELD_OFFSET( TREE_CONNECT, GlobalTreeConnectListEntry ),
  610. SrvCheckAndReferenceTreeConnect,
  611. SrvDereferenceTreeConnect,
  612. &SrvShareLock
  613. );
  614. //
  615. // Open handle to NPFS. Do not return an error if we fail so that
  616. // the server can still run without NPFS in the system.
  617. //
  618. SrvInitializeObjectAttributes_U(
  619. &objectAttributes,
  620. &SrvNamedPipeRootDirectory,
  621. 0,
  622. NULL,
  623. NULL
  624. );
  625. status = IoCreateFile(
  626. &SrvNamedPipeHandle,
  627. GENERIC_READ | GENERIC_WRITE,
  628. &objectAttributes,
  629. &ioStatusBlock,
  630. NULL,
  631. FILE_ATTRIBUTE_NORMAL,
  632. FILE_SHARE_READ | FILE_SHARE_WRITE,
  633. FILE_OPEN,
  634. 0, // Create Options
  635. NULL, // EA Buffer
  636. 0, // EA Length
  637. CreateFileTypeNone, // File type
  638. NULL, // ExtraCreateParameters
  639. IO_FORCE_ACCESS_CHECK // Options
  640. );
  641. if (!NT_SUCCESS(status)) {
  642. INTERNAL_ERROR (
  643. ERROR_LEVEL_EXPECTED,
  644. "InitializeServer: Failed to open NPFS, err=%X\n",
  645. status,
  646. NULL
  647. );
  648. SrvLogServiceFailure( SRV_SVC_IO_CREATE_FILE_NPFS, status );
  649. SrvNamedPipeHandle = NULL;
  650. return status;
  651. } else {
  652. //
  653. // Get a pointer to the NPFS device object
  654. //
  655. status = SrvVerifyDeviceStackSize(
  656. SrvNamedPipeHandle,
  657. TRUE,
  658. &SrvNamedPipeFileObject,
  659. &SrvNamedPipeDeviceObject,
  660. &handleInformation
  661. );
  662. if ( !NT_SUCCESS( status )) {
  663. INTERNAL_ERROR(
  664. ERROR_LEVEL_EXPECTED,
  665. "InitializeServer: Verify Device Stack Size failed: %X\n",
  666. status,
  667. NULL
  668. );
  669. SrvNtClose( SrvNamedPipeHandle, FALSE );
  670. SrvNamedPipeHandle = NULL;
  671. return status;
  672. }
  673. }
  674. //
  675. // Initialize Dfs operations
  676. //
  677. SrvInitializeDfs();
  678. //
  679. // Intialize SrvAdminSecurityDescriptor, which allows Administrators READ access.
  680. // This descriptor is used by the server to check if a user is an administrator
  681. // in SrvIsAdmin().
  682. status = RtlCreateSecurityDescriptor( &SrvAdminSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  683. if( !NT_SUCCESS( status ) ) {
  684. return status;
  685. }
  686. //
  687. // Create an admin SID
  688. //
  689. AdminSid = ALLOCATE_HEAP_COLD( RtlLengthRequiredSid( 2 ), BlockTypeAdminCheck );
  690. if( AdminSid == NULL ) {
  691. return STATUS_INSUFFICIENT_RESOURCES;
  692. }
  693. RtlInitializeSid( AdminSid, &BuiltinAuthority, (UCHAR)2 );
  694. *(RtlSubAuthoritySid( AdminSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
  695. *(RtlSubAuthoritySid( AdminSid, 1 )) = DOMAIN_ALIAS_RID_ADMINS;
  696. length = sizeof(ACL) + sizeof( ACCESS_ALLOWED_ACE ) + RtlLengthSid( AdminSid );
  697. Acl = ALLOCATE_HEAP_COLD( length, BlockTypeAdminCheck );
  698. if( Acl == NULL ) {
  699. FREE_HEAP( AdminSid );
  700. return STATUS_INSUFFICIENT_RESOURCES;
  701. }
  702. status = RtlCreateAcl( Acl, length, ACL_REVISION2 );
  703. if( NT_SUCCESS( status ) ) {
  704. status = RtlAddAccessAllowedAce( Acl, ACL_REVISION2, FILE_GENERIC_READ, AdminSid );
  705. }
  706. if( NT_SUCCESS( status ) ) {
  707. status = RtlSetDaclSecurityDescriptor( &SrvAdminSecurityDescriptor, TRUE, Acl, FALSE );
  708. }
  709. if( NT_SUCCESS( status ) ) {
  710. status = RtlSetOwnerSecurityDescriptor( &SrvAdminSecurityDescriptor, AdminSid, FALSE );
  711. }
  712. if( !NT_SUCCESS( status ) ) {
  713. return status;
  714. }
  715. //
  716. // Intialize SrvNullSessionSecurityDescriptor, which allows anonymous
  717. // logons READ access. This descriptor is used by the server to check
  718. // if a user is an null session in SrvIsNullSession().
  719. //
  720. status = RtlCreateSecurityDescriptor( &SrvNullSessionSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  721. if( !NT_SUCCESS( status ) ) {
  722. return status;
  723. }
  724. //
  725. // Create an anonymous SID
  726. //
  727. AnonymousSid = ALLOCATE_HEAP_COLD( RtlLengthRequiredSid( 1 ), BlockTypeAdminCheck );
  728. if( AnonymousSid == NULL ) {
  729. return STATUS_INSUFFICIENT_RESOURCES;
  730. }
  731. RtlInitializeSid( AnonymousSid, &BuiltinAuthority, (UCHAR)1 );
  732. *(RtlSubAuthoritySid( AnonymousSid, 0 )) = SECURITY_ANONYMOUS_LOGON_RID;
  733. length = sizeof(ACL) + sizeof( ACCESS_ALLOWED_ACE ) + RtlLengthSid( AnonymousSid );
  734. Acl = ALLOCATE_HEAP_COLD( length, BlockTypeAdminCheck );
  735. if( Acl == NULL ) {
  736. FREE_HEAP( AnonymousSid );
  737. return STATUS_INSUFFICIENT_RESOURCES;
  738. }
  739. status = RtlCreateAcl( Acl, length, ACL_REVISION2 );
  740. if( NT_SUCCESS( status ) ) {
  741. status = RtlAddAccessAllowedAce( Acl, ACL_REVISION2, FILE_GENERIC_READ, AnonymousSid );
  742. }
  743. if( NT_SUCCESS( status ) ) {
  744. status = RtlSetDaclSecurityDescriptor( &SrvNullSessionSecurityDescriptor, TRUE, Acl, FALSE );
  745. }
  746. if( NT_SUCCESS( status ) ) {
  747. status = RtlSetOwnerSecurityDescriptor( &SrvNullSessionSecurityDescriptor, AnonymousSid, FALSE );
  748. }
  749. if( !NT_SUCCESS( status ) ) {
  750. return status;
  751. }
  752. (VOID) InitSecurityInterface();
  753. status = SrvValidateUser(
  754. &SrvNullSessionToken,
  755. NULL,
  756. NULL,
  757. NULL,
  758. StrNullAnsi,
  759. 1,
  760. NULL,
  761. 0,
  762. FALSE,
  763. NULL
  764. );
  765. if ( !NT_SUCCESS(status) ) {
  766. //
  767. // LSA doesn't want to let the null session in. He's the boss!
  768. //
  769. INVALIDATE_SECURITY_HANDLE( SrvNullSessionToken );
  770. }
  771. //
  772. // See if the filesystems are allowing extended characters in 8.3 names. If
  773. // so, we need to filter them out ourself.
  774. //
  775. RtlInitUnicodeString( &string, StrRegExtendedCharsInPath );
  776. InitializeObjectAttributes( &objectAttributes,
  777. &string,
  778. OBJ_CASE_INSENSITIVE,
  779. NULL,
  780. NULL
  781. );
  782. status = ZwOpenKey( &handle, KEY_READ, &objectAttributes );
  783. if( NT_SUCCESS( status ) ) {
  784. ULONG resultLength;
  785. union {
  786. KEY_VALUE_FULL_INFORMATION;
  787. UCHAR buffer[ sizeof( KEY_VALUE_FULL_INFORMATION ) + 100 ];
  788. } keyValueInformation;
  789. RtlInitUnicodeString( &string, StrRegExtendedCharsInPathValue );
  790. status = ZwQueryValueKey( handle,
  791. &string,
  792. KeyValueFullInformation,
  793. &keyValueInformation,
  794. sizeof( keyValueInformation ),
  795. &resultLength
  796. );
  797. if( NT_SUCCESS( status ) &&
  798. keyValueInformation.Type == REG_DWORD &&
  799. keyValueInformation.DataLength != 0 ) {
  800. SrvFilterExtendedCharsInPath =
  801. *(PULONG)(((PUCHAR)(&keyValueInformation)) + keyValueInformation.DataOffset) ?
  802. TRUE : FALSE;
  803. }
  804. ZwClose( handle );
  805. }
  806. //
  807. // Get a handle to use in PoRegisterSystemState() calls
  808. //
  809. SrvPoRegistrationState = PoRegisterSystemState( NULL, 0 );
  810. //
  811. // Indicate that the server is active.
  812. //
  813. ACQUIRE_LOCK( &SrvConfigurationLock );
  814. SrvFspTransitioning = FALSE;
  815. SrvFspActive = TRUE;
  816. RELEASE_LOCK( &SrvConfigurationLock );
  817. return STATUS_SUCCESS;
  818. } // InitializeServer
  819. STATIC
  820. NTSTATUS
  821. TerminateServer ( VOID )
  822. /*++
  823. Routine Description:
  824. This routine terminates the server. The following steps are performed:
  825. - Walk through SrvEndpointList and close all open endpoints.
  826. - Walk through the work context blocks in the work queues
  827. getting rid of them as appropiate
  828. - Close all shares open in the server
  829. - Deallocate the search table
  830. Arguments:
  831. Return Value:
  832. None.
  833. --*/
  834. {
  835. PLIST_ENTRY listEntry;
  836. PSLIST_ENTRY singleListEntry;
  837. PENDPOINT endpoint;
  838. ULONG numberOfThreads;
  839. PWORK_CONTEXT workContext;
  840. PSHARE share;
  841. ULONG i;
  842. SPECIAL_WORK_ITEM WorkItem;
  843. PSRV_TIMER timer;
  844. PSID adminsid;
  845. PSID anonymoussid;
  846. PACL acl;
  847. BOOLEAN defaulted;
  848. BOOLEAN daclpresent;
  849. NTSTATUS status;
  850. PWORK_QUEUE queue;
  851. PIRP irp;
  852. PLIST_ENTRY listEntryRoot;
  853. PAGED_CODE( );
  854. IF_DEBUG(FSP1) KdPrint(( "LAN Manager server FSP terminating.\n" ));
  855. //
  856. // Do not receive PNP notifications anymore
  857. //
  858. if( SrvTdiNotificationHandle != NULL ) {
  859. status = TdiDeregisterPnPHandlers( SrvTdiNotificationHandle );
  860. if( !NT_SUCCESS( status ) ) {
  861. KdPrint(( "TdiDeregisterPnPHandlers status %X\n", status ));
  862. SrvLogServiceFailure( SRV_SVC_PNP_TDI_NOTIFICATION, status );
  863. return status;
  864. }
  865. SrvTdiNotificationHandle = NULL;
  866. }
  867. //
  868. // Make sure we are not processing any other configuration IRPs. We know
  869. // that no new configuration IRPs can enter the queue because SrvFspTransitioning
  870. // has been set.
  871. //
  872. // First drain the configuration queue
  873. //
  874. while( 1 ) {
  875. ACQUIRE_LOCK( &SrvConfigurationLock );
  876. irp = DequeueConfigurationIrp( );
  877. RELEASE_LOCK( &SrvConfigurationLock );
  878. if( irp == NULL ) {
  879. break;
  880. }
  881. irp->IoStatus.Status = STATUS_SERVER_NOT_STARTED;
  882. IoCompleteRequest( irp, 2 );
  883. InterlockedDecrement( (PLONG)&SrvConfigurationIrpsInProgress );
  884. }
  885. //
  886. // Now wait until any already dequeued configuration IRPs have been completed. We
  887. // check for >1 because we need to account for our own IRP
  888. //
  889. while( SrvConfigurationIrpsInProgress > 1 ) {
  890. LARGE_INTEGER interval;
  891. interval.QuadPart = -1*10*1000*10; // .01 second
  892. ASSERT( (LONG)SrvConfigurationIrpsInProgress > 0 );
  893. KeDelayExecutionThread( KernelMode, FALSE, &interval );
  894. }
  895. //
  896. // If there are outstanding API requests in the server FSD,
  897. // wait for them to complete. The last one to complete will
  898. // set SrvApiCompletionEvent.
  899. //
  900. ACQUIRE_LOCK( &SrvConfigurationLock );
  901. if( SrvLWIOContext )
  902. {
  903. FREE_HEAP( SrvLWIOContext );
  904. SrvLWIOContext = NULL;
  905. }
  906. if ( SrvApiRequestCount != 0 ) {
  907. //
  908. // We must release the lock before waiting so that the FSD
  909. // threads can get it to decrement SrvApiRequestCount.
  910. //
  911. RELEASE_LOCK( &SrvConfigurationLock );
  912. for (;;) {
  913. NTSTATUS WaitStatus;
  914. //
  915. // Wait until the last API has completed. Since
  916. // SrvFspTransitioning was set to TRUE earlier, we know that the
  917. // API that makes SrvApiRequestCount go to zero will set the
  918. // event.
  919. //
  920. // This wait allows us to make the assumption later on that no
  921. // other thread is operating on server data structures.
  922. //
  923. WaitStatus = KeWaitForSingleObject(
  924. &SrvApiCompletionEvent,
  925. UserRequest,
  926. UserMode, // let kernel stack be paged
  927. FALSE,
  928. NULL
  929. );
  930. if (WaitStatus != STATUS_USER_APC) {
  931. break;
  932. }
  933. }
  934. } else {
  935. RELEASE_LOCK( &SrvConfigurationLock );
  936. }
  937. //
  938. // Close all the endpoints opened by the server. This also results
  939. // in the connections, sessions, tree connects, and files opened
  940. // by the server being closed.
  941. //
  942. ACQUIRE_LOCK( &SrvEndpointLock );
  943. if ( SrvEndpointCount != 0 ) {
  944. listEntry = SrvEndpointList.ListHead.Flink;
  945. while ( listEntry != &SrvEndpointList.ListHead ) {
  946. endpoint = CONTAINING_RECORD(
  947. listEntry,
  948. ENDPOINT,
  949. GlobalEndpointListEntry
  950. );
  951. if ( GET_BLOCK_STATE(endpoint) != BlockStateActive ) {
  952. listEntry = listEntry->Flink;
  953. continue;
  954. }
  955. //
  956. // We don't want to hold the endpoint lock while we close
  957. // the endpoint (this causes lock level problems), so we have
  958. // to play some games.
  959. //
  960. // Reference the endpoint to ensure that it doesn't go away.
  961. // (We'll need its Flink later.) Close the endpoint. This
  962. // releases the endpoint lock. Reacquire the endpoint lock.
  963. // Capture the address of the next endpoint. Dereference the
  964. // current endpoint.
  965. //
  966. SrvReferenceEndpoint( endpoint );
  967. SrvCloseEndpoint( endpoint );
  968. ACQUIRE_LOCK( &SrvEndpointLock );
  969. listEntry = listEntry->Flink;
  970. SrvDereferenceEndpoint( endpoint );
  971. }
  972. RELEASE_LOCK( &SrvEndpointLock );
  973. for (;;) {
  974. NTSTATUS WaitStatus;
  975. //
  976. // Wait until all the endpoints have actually closed.
  977. //
  978. WaitStatus = KeWaitForSingleObject(
  979. &SrvEndpointEvent,
  980. UserRequest,
  981. UserMode, // let kernel stack be paged
  982. FALSE,
  983. NULL
  984. );
  985. if (WaitStatus != STATUS_USER_APC) {
  986. break;
  987. }
  988. }
  989. } else {
  990. RELEASE_LOCK( &SrvEndpointLock );
  991. }
  992. KeClearEvent( &SrvEndpointEvent );
  993. //
  994. // All the endpoints are closed, so it's impossible for there to
  995. // be any outstanding requests to xactsrv. So shut it down.
  996. //
  997. SrvXsDisconnect();
  998. //
  999. // Queue a special work item to each of the work queues. This
  1000. // work item, when received by a worker thread. causes the thread
  1001. // to requeue the work item and terminate itself. In this way,
  1002. // each of the worker threads receives the work item and kills
  1003. // itself.
  1004. //
  1005. WorkItem.FspRestartRoutine = SrvTerminateWorkerThread;
  1006. SET_BLOCK_TYPE( &WorkItem, BlockTypeWorkContextSpecial );
  1007. //
  1008. // Kill the threads on the nonblocking work queues
  1009. //
  1010. if ( SrvWorkQueues != NULL ) {
  1011. for( queue=SrvWorkQueues; queue && queue < eSrvWorkQueues; queue++ ) {
  1012. WorkItem.CurrentWorkQueue = queue;
  1013. SrvInsertWorkQueueTail(
  1014. queue,
  1015. (PQUEUEABLE_BLOCK_HEADER)&WorkItem
  1016. );
  1017. //
  1018. // Wait for the threads to all die
  1019. //
  1020. while( queue->Threads != 0 ) {
  1021. LARGE_INTEGER interval;
  1022. interval.QuadPart = -1*10*1000*10; // .01 second
  1023. KeDelayExecutionThread( KernelMode, FALSE, &interval );
  1024. }
  1025. KeRundownQueue( &queue->Queue );
  1026. }
  1027. }
  1028. //
  1029. // Kill the threads on the blocking work queues
  1030. //
  1031. if( SrvBlockingWorkQueues != NULL )
  1032. {
  1033. for( queue=SrvBlockingWorkQueues; queue && queue < eSrvBlockingWorkQueues; queue++ ) {
  1034. WorkItem.CurrentWorkQueue = queue;
  1035. SrvInsertWorkQueueTail(
  1036. queue,
  1037. (PQUEUEABLE_BLOCK_HEADER)&WorkItem
  1038. );
  1039. //
  1040. // Wait for the threads to all die
  1041. //
  1042. while( queue->Threads != 0 ) {
  1043. LARGE_INTEGER interval;
  1044. interval.QuadPart = -1*10*1000*10; // .01 second
  1045. KeDelayExecutionThread( KernelMode, FALSE, &interval );
  1046. }
  1047. KeRundownQueue( &queue->Queue );
  1048. }
  1049. //
  1050. // Kill all the threads in the LPC work queue
  1051. // Note that if the Blocking Work Queues were successfully allocated, we're
  1052. // guaranteed that the LPC queue was successfully initialized.
  1053. //
  1054. WorkItem.CurrentWorkQueue = &SrvLpcWorkQueue;
  1055. SrvInsertWorkQueueTail(
  1056. &SrvLpcWorkQueue,
  1057. (PQUEUEABLE_BLOCK_HEADER)&WorkItem
  1058. );
  1059. //
  1060. // Wait for the threads to all die
  1061. //
  1062. while( SrvLpcWorkQueue.Threads != 0 )
  1063. {
  1064. LARGE_INTEGER interval;
  1065. interval.QuadPart = -1*10*1000*10; // .01 second
  1066. KeDelayExecutionThread( KernelMode, FALSE, &interval );
  1067. }
  1068. KeRundownQueue( &SrvLpcWorkQueue.Queue );
  1069. }
  1070. //
  1071. // Free any space allocated for the Null Session pipe and share lists
  1072. //
  1073. SrvFreeRegTables();
  1074. //
  1075. // If we allocated memory for the os version strings, free it now.
  1076. //
  1077. if ( SrvNativeOS.Buffer != NULL &&
  1078. SrvNativeOS.Buffer != StrDefaultNativeOs ) {
  1079. FREE_HEAP( SrvNativeOS.Buffer );
  1080. SrvNativeOS.Buffer = NULL;
  1081. RtlFreeOemString( &SrvOemNativeOS );
  1082. SrvOemNativeOS.Buffer = NULL;
  1083. FREE_HEAP( SrvNativeLanMan.Buffer );
  1084. SrvNativeLanMan.Buffer = NULL;
  1085. RtlFreeOemString( &SrvOemNativeLanMan );
  1086. SrvOemNativeLanMan.Buffer = NULL;
  1087. }
  1088. //
  1089. // If allocated memory for the display name, free it now.
  1090. //
  1091. if ( SrvAlertServiceName != NULL &&
  1092. SrvAlertServiceName != StrDefaultSrvDisplayName ) {
  1093. FREE_HEAP( SrvAlertServiceName );
  1094. SrvAlertServiceName = NULL;
  1095. }
  1096. //
  1097. // Make sure the scavenger is not running.
  1098. //
  1099. SrvTerminateScavenger( );
  1100. #if MULTIPROCESSOR
  1101. if( SrvWorkQueues ) {
  1102. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++ ) {
  1103. StopQueueDepthComputations( queue );
  1104. }
  1105. }
  1106. #endif
  1107. //
  1108. // Free the work items in the work queues and the receive work item
  1109. // list. This also deallocates the SMB buffers. Note that work
  1110. // items allocated dynamically may be deallocated singly, while work
  1111. // items allocated at server startup are part of one large block,
  1112. // and may not be deallocated singly.
  1113. //
  1114. // !!! Does this properly clean up buffers allocated during SMB
  1115. // processing? Probably not. Should probably allow the worker
  1116. // threads to run the work queue normally before they stop.
  1117. //
  1118. if( SrvWorkQueues ) {
  1119. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++ ) {
  1120. //
  1121. // Clean out the single FreeContext spot
  1122. //
  1123. workContext = NULL;
  1124. workContext = (PWORK_CONTEXT)InterlockedExchangePointer(
  1125. &queue->FreeContext, workContext );
  1126. if( workContext != NULL && workContext->PartOfInitialAllocation == FALSE ) {
  1127. SrvFreeNormalWorkItem( workContext );
  1128. }
  1129. //
  1130. // Clean out the normal work item list
  1131. //
  1132. while( 1 ) {
  1133. singleListEntry = ExInterlockedPopEntrySList(
  1134. &queue->NormalWorkItemList, &queue->SpinLock );
  1135. if( singleListEntry == NULL ) {
  1136. break;
  1137. }
  1138. workContext =
  1139. CONTAINING_RECORD( singleListEntry, WORK_CONTEXT, SingleListEntry );
  1140. SrvFreeNormalWorkItem( workContext );
  1141. queue->FreeWorkItems--;
  1142. }
  1143. //
  1144. // Clean out the raw mode work item list
  1145. //
  1146. while( 1 ) {
  1147. singleListEntry = ExInterlockedPopEntrySList(
  1148. &queue->RawModeWorkItemList, &queue->SpinLock );
  1149. if( singleListEntry == NULL ) {
  1150. break;
  1151. }
  1152. workContext =
  1153. CONTAINING_RECORD( singleListEntry, WORK_CONTEXT, SingleListEntry );
  1154. SrvFreeRawModeWorkItem( workContext );
  1155. }
  1156. //
  1157. // Free up any saved rfcbs
  1158. //
  1159. if( queue->CachedFreeRfcb != NULL ) {
  1160. FREE_HEAP( queue->CachedFreeRfcb->PagedRfcb );
  1161. DEALLOCATE_NONPAGED_POOL( queue->CachedFreeRfcb );
  1162. queue->CachedFreeRfcb = NULL;
  1163. }
  1164. while( 1 ) {
  1165. PRFCB Rfcb;
  1166. singleListEntry = ExInterlockedPopEntrySList( &queue->RfcbFreeList, &queue->SpinLock );
  1167. if( singleListEntry == NULL ) {
  1168. break;
  1169. }
  1170. Rfcb =
  1171. CONTAINING_RECORD( singleListEntry, RFCB, SingleListEntry );
  1172. FREE_HEAP( Rfcb->PagedRfcb );
  1173. DEALLOCATE_NONPAGED_POOL( Rfcb );
  1174. }
  1175. //
  1176. // Free up any saved mfcbs
  1177. //
  1178. if( queue->CachedFreeMfcb != NULL ) {
  1179. DEALLOCATE_NONPAGED_POOL( queue->CachedFreeMfcb );
  1180. queue->CachedFreeMfcb = NULL;
  1181. }
  1182. while( 1 ) {
  1183. PNONPAGED_MFCB nonpagedMfcb;
  1184. singleListEntry = ExInterlockedPopEntrySList( &queue->MfcbFreeList, &queue->SpinLock );
  1185. if( singleListEntry == NULL ) {
  1186. break;
  1187. }
  1188. nonpagedMfcb =
  1189. CONTAINING_RECORD( singleListEntry, NONPAGED_MFCB, SingleListEntry );
  1190. DEALLOCATE_NONPAGED_POOL( nonpagedMfcb );
  1191. }
  1192. }
  1193. } // SrvWorkQueues
  1194. //
  1195. // All dynamic work items have been freed, and the work item queues
  1196. // have been emptied. Release the initial work item allocation.
  1197. //
  1198. SrvFreeInitialWorkItems( );
  1199. //
  1200. // Walk through the global share list, closing them all.
  1201. //
  1202. for( listEntryRoot = SrvShareHashTable;
  1203. listEntryRoot < &SrvShareHashTable[ NSHARE_HASH_TABLE ];
  1204. listEntryRoot++ ) {
  1205. while( listEntryRoot->Flink != listEntryRoot ) {
  1206. share = CONTAINING_RECORD( listEntryRoot->Flink, SHARE, GlobalShareList );
  1207. SrvCloseShare( share );
  1208. }
  1209. }
  1210. //
  1211. // If we opened the NPFS during initialization, close the handle now
  1212. // and dereference the NPFS file object.
  1213. //
  1214. if ( SrvNamedPipeHandle != NULL) {
  1215. SrvNtClose( SrvNamedPipeHandle, FALSE );
  1216. ObDereferenceObject( SrvNamedPipeFileObject );
  1217. SrvNamedPipeHandle = NULL;
  1218. }
  1219. //
  1220. // Disconnect from the Dfs driver
  1221. //
  1222. SrvTerminateDfs();
  1223. //
  1224. // Clean up the Dns Domain Name if necessary
  1225. //
  1226. if( SrvDnsDomainName )
  1227. {
  1228. DEALLOCATE_NONPAGED_POOL( SrvDnsDomainName );
  1229. SrvDnsDomainName = NULL;
  1230. }
  1231. //
  1232. // Clean up the admin security descriptor
  1233. //
  1234. status = RtlGetDaclSecurityDescriptor( &SrvAdminSecurityDescriptor,
  1235. &daclpresent,
  1236. &acl,
  1237. &defaulted );
  1238. if( !NT_SUCCESS( status ) || !daclpresent ) {
  1239. acl = NULL;
  1240. }
  1241. status = RtlGetOwnerSecurityDescriptor( &SrvAdminSecurityDescriptor,
  1242. &adminsid,
  1243. &defaulted );
  1244. if( NT_SUCCESS( status ) && adminsid != NULL ) {
  1245. FREE_HEAP( adminsid );
  1246. }
  1247. if( acl != NULL ) {
  1248. FREE_HEAP( acl );
  1249. }
  1250. //
  1251. // Clean up the null session security descriptor
  1252. //
  1253. status = RtlGetDaclSecurityDescriptor( &SrvNullSessionSecurityDescriptor,
  1254. &daclpresent,
  1255. &acl,
  1256. &defaulted );
  1257. if( !NT_SUCCESS( status ) || !daclpresent ) {
  1258. acl = NULL;
  1259. }
  1260. status = RtlGetOwnerSecurityDescriptor( &SrvNullSessionSecurityDescriptor,
  1261. &anonymoussid,
  1262. &defaulted );
  1263. if( NT_SUCCESS( status ) && anonymoussid != NULL ) {
  1264. FREE_HEAP( anonymoussid );
  1265. }
  1266. if( acl != NULL ) {
  1267. FREE_HEAP( acl );
  1268. }
  1269. if (!CONTEXT_NULL(SrvNullSessionToken)) {
  1270. DeleteSecurityContext(&SrvNullSessionToken);
  1271. INVALIDATE_SECURITY_HANDLE( SrvNullSessionToken );
  1272. }
  1273. //
  1274. // Delete the global ordered lists.
  1275. //
  1276. SrvDeleteOrderedList( &SrvEndpointList );
  1277. SrvDeleteOrderedList( &SrvRfcbList );
  1278. SrvDeleteOrderedList( &SrvSessionList );
  1279. SrvDeleteOrderedList( &SrvTreeConnectList );
  1280. //
  1281. // Clear out the timer pool.
  1282. //
  1283. while ( (singleListEntry = ExInterlockedPopEntrySList(
  1284. &SrvTimerList,
  1285. &GLOBAL_SPIN_LOCK(Timer) )) != NULL ) {
  1286. timer = CONTAINING_RECORD( singleListEntry, SRV_TIMER, Next );
  1287. DEALLOCATE_NONPAGED_POOL( timer );
  1288. }
  1289. if( SrvWorkQueues ) {
  1290. //
  1291. // Clear out the saved pool chunks
  1292. //
  1293. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++ ) {
  1294. //
  1295. // Free up any paged pool that we've saved.
  1296. //
  1297. SrvClearLookAsideList( &queue->PagedPoolLookAsideList, SrvFreePagedPool );
  1298. //
  1299. // Free up any nonpaged pool that we've saved.
  1300. //
  1301. SrvClearLookAsideList( &queue->NonPagedPoolLookAsideList, SrvFreeNonPagedPool );
  1302. }
  1303. #if MULTIPROCESSOR
  1304. DEALLOCATE_NONPAGED_POOL( SrvWorkQueuesBase );
  1305. SrvWorkQueuesBase = NULL;
  1306. SrvWorkQueues = NULL;
  1307. #endif
  1308. }
  1309. if( SrvBlockingWorkQueues ) {
  1310. //
  1311. // Clear out the saved pool chunks
  1312. //
  1313. for( queue = SrvBlockingWorkQueues; queue < eSrvBlockingWorkQueues; queue++ ) {
  1314. //
  1315. // Free up any paged pool that we've saved.
  1316. //
  1317. SrvClearLookAsideList( &queue->PagedPoolLookAsideList, SrvFreePagedPool );
  1318. //
  1319. // Free up any nonpaged pool that we've saved.
  1320. //
  1321. SrvClearLookAsideList( &queue->NonPagedPoolLookAsideList, SrvFreeNonPagedPool );
  1322. }
  1323. #if MULTIPROCESSOR
  1324. DEALLOCATE_NONPAGED_POOL( SrvBlockingWorkQueuesBase );
  1325. SrvBlockingWorkQueuesBase = NULL;
  1326. SrvBlockingWorkQueues = NULL;
  1327. #endif
  1328. SrvClearLookAsideList( &SrvLpcWorkQueue.PagedPoolLookAsideList, SrvFreePagedPool );
  1329. SrvClearLookAsideList( &SrvLpcWorkQueue.NonPagedPoolLookAsideList, SrvFreeNonPagedPool );
  1330. }
  1331. //
  1332. // Unlock pageable sections.
  1333. //
  1334. for ( i = 0; i < SRV_CODE_SECTION_MAX; i++ ) {
  1335. if ( SrvSectionInfo[i].Handle != NULL ) {
  1336. ASSERT( SrvSectionInfo[i].ReferenceCount != 0 );
  1337. MmUnlockPagableImageSection( SrvSectionInfo[i].Handle );
  1338. SrvSectionInfo[i].Handle = 0;
  1339. SrvSectionInfo[i].ReferenceCount = 0;
  1340. }
  1341. }
  1342. //
  1343. // Zero out the statistics database.
  1344. //
  1345. RtlZeroMemory( &SrvStatistics, sizeof(SrvStatistics) );
  1346. #if SRVDBG_STATS || SRVDBG_STATS2
  1347. RtlZeroMemory( &SrvDbgStatistics, sizeof(SrvDbgStatistics) );
  1348. #endif
  1349. //
  1350. // Free the handle used in PoRegisterSystemState
  1351. //
  1352. if( SrvPoRegistrationState != NULL ) {
  1353. PoUnregisterSystemState( SrvPoRegistrationState );
  1354. SrvPoRegistrationState = NULL;
  1355. }
  1356. //
  1357. // Uninitialize WMI if we registered
  1358. //
  1359. if (SrvWmiInitialized) {
  1360. // Deregister WMI
  1361. //
  1362. SrvWmiInitialized = FALSE;
  1363. IoWMIRegistrationControl(SrvDeviceObject, WMIREG_ACTION_DEREGISTER);
  1364. }
  1365. //
  1366. // Indicate that the server is no longer active.
  1367. //
  1368. ACQUIRE_LOCK( &SrvConfigurationLock );
  1369. SrvFspTransitioning = FALSE;
  1370. SrvFspActive = FALSE;
  1371. SrvSvcProcess = NULL;
  1372. RELEASE_LOCK( &SrvConfigurationLock );
  1373. IF_DEBUG(FSP1) KdPrint(( "LAN Manager server FSP termination complete.\n" ));
  1374. return STATUS_SUCCESS;
  1375. } // TerminateServer
  1376. VOID
  1377. SrvFreeRegTables (
  1378. VOID
  1379. )
  1380. /*++
  1381. Routine Description:
  1382. This routine frees space allocated for the list of legal Null session shares
  1383. and pipes. The SrvConfigurationLock must be held when this routine is called.
  1384. Arguments:
  1385. None.
  1386. Return Value:
  1387. None.
  1388. --*/
  1389. {
  1390. PAGED_CODE( );
  1391. //
  1392. // If we allocated a buffer for the list of null session pipes,
  1393. // free it now.
  1394. //
  1395. if ( SrvNullSessionPipes != NULL &&
  1396. SrvNullSessionPipes != StrDefaultNullSessionPipes ) {
  1397. FREE_HEAP( SrvNullSessionPipes );
  1398. }
  1399. SrvNullSessionPipes = NULL;
  1400. if( SrvNoRemapPipeNames != NULL &&
  1401. SrvNoRemapPipeNames != StrDefaultNoRemapPipeNames ) {
  1402. FREE_HEAP( SrvNoRemapPipeNames );
  1403. }
  1404. SrvNoRemapPipeNames = NULL;
  1405. if ( SrvPipesNeedLicense != NULL &&
  1406. SrvPipesNeedLicense != StrDefaultPipesNeedLicense ) {
  1407. FREE_HEAP( SrvPipesNeedLicense );
  1408. }
  1409. SrvPipesNeedLicense = NULL;
  1410. if ( SrvNullSessionShares != NULL &&
  1411. SrvNullSessionShares != StrDefaultNullSessionShares ) {
  1412. FREE_HEAP( SrvNullSessionShares );
  1413. }
  1414. SrvNullSessionShares = NULL;
  1415. #if SRVNTVERCHK
  1416. if( SrvInvalidDomainNames != NULL ) {
  1417. FREE_HEAP( SrvInvalidDomainNames );
  1418. }
  1419. SrvInvalidDomainNames = NULL;
  1420. #endif
  1421. #if SRVCATCH
  1422. if( SrvCatchBuf != NULL ) {
  1423. FREE_HEAP( SrvCatchBuf );
  1424. SrvCatchBuf = NULL;
  1425. }
  1426. if( SrvCatchExtBuf != NULL ) {
  1427. FREE_HEAP( SrvCatchExtBuf );
  1428. SrvCatchExtBuf = NULL;
  1429. }
  1430. if( SrvCatchShareNames != NULL ) {
  1431. FREE_HEAP( SrvCatchShareNames );
  1432. SrvCatchShareNames = NULL;
  1433. SrvCatchShares = 0;
  1434. CleanupCrcTable();
  1435. }
  1436. #endif
  1437. }
  1438. VOID
  1439. SrvGetRegTables (
  1440. VOID
  1441. )
  1442. /*++
  1443. Routine Description:
  1444. This routine loads the lists of valid shares and pipes for null sessions.
  1445. The SrvConfigurationLock must be held when this routine is called.
  1446. Arguments:
  1447. None.
  1448. Return Value:
  1449. None.
  1450. --*/
  1451. {
  1452. PWSTR *strErrorLogIgnore;
  1453. DWORD dwSetting;
  1454. PAGED_CODE( );
  1455. //
  1456. // Get the list of null session pipes.
  1457. //
  1458. ASSERT( SrvNullSessionPipes == NULL );
  1459. SrvGetMultiSZList(
  1460. &SrvNullSessionPipes,
  1461. StrRegSrvParameterPath,
  1462. StrRegNullSessionPipes,
  1463. StrDefaultNullSessionPipes
  1464. );
  1465. //
  1466. // Get the list of non-remappable pipe names
  1467. //
  1468. ASSERT( SrvNoRemapPipeNames == NULL );
  1469. SrvGetMultiSZList(
  1470. &SrvNoRemapPipeNames,
  1471. StrRegSrvParameterPath,
  1472. StrRegNoRemapPipes,
  1473. StrDefaultNoRemapPipeNames
  1474. );
  1475. //
  1476. // Get the list of pipes requiring licenses
  1477. //
  1478. ASSERT( SrvPipesNeedLicense == NULL );
  1479. SrvGetMultiSZList(
  1480. &SrvPipesNeedLicense,
  1481. StrRegSrvParameterPath,
  1482. StrRegPipesNeedLicense,
  1483. StrDefaultPipesNeedLicense
  1484. );
  1485. //
  1486. // Get the list of null session pipes.
  1487. //
  1488. ASSERT( SrvNullSessionShares == NULL );
  1489. SrvGetMultiSZList(
  1490. &SrvNullSessionShares,
  1491. StrRegSrvParameterPath,
  1492. StrRegNullSessionShares,
  1493. StrDefaultNullSessionShares
  1494. );
  1495. //
  1496. // These are the security signature settings
  1497. //
  1498. SrvSmbSecuritySignaturesRequired = FALSE;
  1499. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegRequireSecuritySignatures, &dwSetting ) ) )
  1500. {
  1501. if( dwSetting != 0 )
  1502. {
  1503. SrvSmbSecuritySignaturesRequired = TRUE;
  1504. }
  1505. }
  1506. SrvSmbSecuritySignaturesEnabled = FALSE;
  1507. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegEnableSecuritySignatures, &dwSetting ) ) )
  1508. {
  1509. if( dwSetting != 0 )
  1510. {
  1511. SrvSmbSecuritySignaturesEnabled = TRUE;
  1512. }
  1513. }
  1514. SrvEnableExtendedSignatures = SrvSmbSecuritySignaturesEnabled;
  1515. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegEnableExtendedSignatures, &dwSetting ) ) )
  1516. {
  1517. if( dwSetting != 0 )
  1518. {
  1519. SrvEnableExtendedSignatures = TRUE;
  1520. }
  1521. else
  1522. {
  1523. SrvEnableExtendedSignatures = FALSE;
  1524. }
  1525. }
  1526. SrvRequireExtendedSignatures = FALSE;
  1527. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegRequireExtendedSignatures, &dwSetting ) ) )
  1528. {
  1529. if( dwSetting != 0 )
  1530. {
  1531. SrvRequireExtendedSignatures = TRUE;
  1532. }
  1533. }
  1534. // Precedence settings
  1535. // RequireExtended implies RequireSignatures and EnableExtended
  1536. if( SrvRequireExtendedSignatures )
  1537. {
  1538. SrvSmbSecuritySignaturesRequired = TRUE;
  1539. SrvEnableExtendedSignatures = TRUE;
  1540. }
  1541. // EnableExtended implies EnableSignatures
  1542. if( SrvEnableExtendedSignatures ) {
  1543. SrvSmbSecuritySignaturesEnabled = TRUE;
  1544. }
  1545. // RequireSignature implies EnableSignature
  1546. if( SrvSmbSecuritySignaturesRequired )
  1547. {
  1548. SrvSmbSecuritySignaturesEnabled = TRUE;
  1549. }
  1550. //
  1551. // Should we disable large read/write ops?
  1552. //
  1553. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegDisableLargeRead, &dwSetting ) ) )
  1554. {
  1555. if( dwSetting != 0 )
  1556. {
  1557. SrvDisableLargeRead = TRUE;
  1558. }
  1559. else
  1560. {
  1561. SrvDisableLargeRead = FALSE;
  1562. }
  1563. }
  1564. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegDisableLargeWrite, &dwSetting ) ) )
  1565. {
  1566. if( dwSetting != 0 )
  1567. {
  1568. SrvDisableLargeWrite = TRUE;
  1569. }
  1570. else
  1571. {
  1572. SrvDisableLargeWrite = FALSE;
  1573. }
  1574. }
  1575. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegMapNoIntermediateBuffering, &dwSetting ) ) )
  1576. {
  1577. if( dwSetting != 0 )
  1578. {
  1579. SrvMapNoIntermediateBuffering = TRUE;
  1580. }
  1581. else
  1582. {
  1583. SrvMapNoIntermediateBuffering = FALSE;
  1584. }
  1585. }
  1586. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegNoAliasingOnFilesystem, &dwSetting ) ) )
  1587. {
  1588. if( dwSetting != 0 )
  1589. {
  1590. SrvNoAliasingOnFilesystem = TRUE;
  1591. }
  1592. else
  1593. {
  1594. SrvNoAliasingOnFilesystem = FALSE;
  1595. }
  1596. }
  1597. SrvDisableDownlevelTimewarp = TRUE;
  1598. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegDisableDownlevelTimewarp, &dwSetting ) ) )
  1599. {
  1600. if( dwSetting == 0 )
  1601. {
  1602. SrvDisableDownlevelTimewarp = FALSE;
  1603. }
  1604. }
  1605. //
  1606. // Should we log invalid SMB commands?
  1607. //
  1608. #if DBG
  1609. SrvEnableInvalidSmbLogging = TRUE;
  1610. #else
  1611. SrvEnableInvalidSmbLogging = FALSE;
  1612. #endif
  1613. if( NT_SUCCESS( SrvGetDWord( StrRegSrvParameterPath, StrRegEnableInvalidSmbLogging, &dwSetting ) ) )
  1614. {
  1615. if( dwSetting != 0 )
  1616. {
  1617. SrvEnableInvalidSmbLogging = TRUE;
  1618. }
  1619. else
  1620. {
  1621. SrvEnableInvalidSmbLogging = FALSE;
  1622. }
  1623. }
  1624. #if SRVCATCH
  1625. {
  1626. USHORT i;
  1627. SrvCatch.Length = 0;
  1628. SrvCatch.Buffer = 0;
  1629. if( SrvCatchBuf != NULL ) {
  1630. FREE_HEAP( SrvCatchBuf );
  1631. SrvCatchBuf = NULL;
  1632. }
  1633. SrvGetMultiSZList(
  1634. &SrvCatchBuf,
  1635. StrRegSrvParameterPath,
  1636. L"CheckFile",
  1637. 0
  1638. );
  1639. if( SrvCatchBuf != NULL ) {
  1640. SrvCatch.Buffer = SrvCatchBuf[0];
  1641. for( i = 0; SrvCatch.Buffer[i]; i++ )
  1642. ;
  1643. SrvCatch.Length = i * sizeof( SrvCatch.Buffer[0] );
  1644. }
  1645. SrvCatchExt.Length = 0;
  1646. SrvCatchExt.Buffer = 0;
  1647. if( SrvCatchExtBuf != NULL )
  1648. {
  1649. FREE_HEAP( SrvCatchExtBuf );
  1650. SrvCatchExtBuf = NULL;
  1651. }
  1652. SrvGetMultiSZList(
  1653. &SrvCatchExtBuf,
  1654. StrRegSrvParameterPath,
  1655. L"CheckExtension",
  1656. 0
  1657. );
  1658. if( SrvCatchExtBuf != NULL ) {
  1659. SrvCatchExt.Buffer = SrvCatchExtBuf[0];
  1660. for( i = 0; SrvCatchExt.Buffer[i]; i++ )
  1661. ;
  1662. SrvCatchExt.Length = i * sizeof( SrvCatchExt.Buffer[0] );
  1663. }
  1664. if( SrvCatchShareNames != NULL )
  1665. {
  1666. FREE_HEAP( SrvCatchShareNames );
  1667. SrvCatchShareNames = NULL;
  1668. }
  1669. SrvGetMultiSZList(
  1670. &SrvCatchShareNames,
  1671. StrRegSrvParameterPath,
  1672. L"CheckShares",
  1673. 0
  1674. );
  1675. if( SrvCatchShareNames != NULL )
  1676. {
  1677. for( i=0; SrvCatchShareNames[i]; i++ ) ;
  1678. SrvCatchShares = i;
  1679. }
  1680. if( SrvCatchShares > 0 )
  1681. {
  1682. if( !GenerateCrcTable() )
  1683. {
  1684. FREE_HEAP( SrvCatchShareNames );
  1685. SrvCatchShareNames = NULL;
  1686. SrvCatchShares = 0;
  1687. }
  1688. }
  1689. }
  1690. #endif
  1691. //
  1692. // Get the list of error codes that we don't log
  1693. //
  1694. SrvGetMultiSZList(
  1695. &strErrorLogIgnore,
  1696. StrRegSrvParameterPath,
  1697. StrRegErrorLogIgnore,
  1698. StrDefaultErrorLogIgnore
  1699. );
  1700. if( strErrorLogIgnore != NULL ) {
  1701. DWORD i;
  1702. //
  1703. // They came in as strings, convert to NTSTATUS codes
  1704. //
  1705. for( i=0; i < SRVMAXERRLOGIGNORE; i++ ) {
  1706. NTSTATUS Status;
  1707. PWSTR p;
  1708. if( (p = strErrorLogIgnore[i]) == NULL )
  1709. break;
  1710. for( Status = 0; *p; p++ ) {
  1711. if( *p >= L'A' && *p <= L'F' ) {
  1712. Status <<= 4;
  1713. Status += 10 + (*p - L'A');
  1714. } else if( *p >= '0' && *p <= '9' ) {
  1715. Status <<= 4;
  1716. Status += *p - L'0';
  1717. }
  1718. }
  1719. SrvErrorLogIgnore[i] = Status;
  1720. IF_DEBUG(FSP1) KdPrint(( "LAN Manager server: %X errs not logged\n", Status ));
  1721. }
  1722. SrvErrorLogIgnore[i] = 0;
  1723. if( strErrorLogIgnore != StrDefaultErrorLogIgnore ) {
  1724. FREE_HEAP( strErrorLogIgnore );
  1725. }
  1726. }
  1727. #if SRVNTVERCHK
  1728. //
  1729. // Get the list of Domains that we disallow if the client
  1730. // is running NT5
  1731. //
  1732. ASSERT( SrvInvalidDomainNames == NULL );
  1733. SrvGetMultiSZList(
  1734. &SrvInvalidDomainNames,
  1735. StrRegSrvParameterPath,
  1736. StrRegInvalidDomainNames,
  1737. NULL
  1738. );
  1739. if( SrvInvalidDomainNames != NULL ) {
  1740. int i;
  1741. KdPrint(( "SRV disallows NT5 clients from the following domains:\n" ));
  1742. for( i = 0; SrvInvalidDomainNames[i]; i++ ) {
  1743. KdPrint(( " %ws\n", SrvInvalidDomainNames[i] ));
  1744. }
  1745. }
  1746. //
  1747. // Get the list of IP addresses of clients that we will allow to connect
  1748. // regardless of build number
  1749. //
  1750. {
  1751. PWSTR *strAllowedIPAddresses;
  1752. int i;
  1753. //
  1754. // Wipe out the current list
  1755. //
  1756. RtlZeroMemory( SrvAllowIPAddress, sizeof( SrvAllowIPAddress ) );
  1757. SrvGetMultiSZList(
  1758. &strAllowedIPAddresses,
  1759. StrRegSrvParameterPath,
  1760. StrRegAllowedIPAddresses,
  1761. NULL
  1762. );
  1763. if( strAllowedIPAddresses != NULL ) {
  1764. KdPrint(( "SRV ignores NT build version of clients at following IP addrs:\n" ));
  1765. //
  1766. // Fill it with the new ones
  1767. //
  1768. for(i = 0;
  1769. strAllowedIPAddresses[i] &&
  1770. i < (sizeof(SrvAllowIPAddress)/sizeof(SrvAllowIPAddress[0]))-1;
  1771. i++ ) {
  1772. LPWSTR p;
  1773. DWORD addr = 0;
  1774. char *s = (char *)&addr;
  1775. //
  1776. // Convert the IP address to a DWORD and store it
  1777. //
  1778. for( p = strAllowedIPAddresses[i]; *p && s < ((char *)&addr)+sizeof(addr); p++ ) {
  1779. if( *p == L'.' ) {
  1780. s++;
  1781. } else if( *p >= '0' && *p <= '9' ) {
  1782. *s = (*s * 10) + (*p - L'0');
  1783. }
  1784. }
  1785. SrvAllowIPAddress[i] = addr;
  1786. KdPrint(( " %ws\n", strAllowedIPAddresses[i] ));
  1787. }
  1788. FREE_HEAP( strAllowedIPAddresses );
  1789. }
  1790. }
  1791. #endif
  1792. }
  1793. #if SRVNTVERCHK
  1794. VOID
  1795. SrvGetRegClientNumber (
  1796. VOID
  1797. )
  1798. /*++
  1799. Routine Description:
  1800. This routine reads MinNt5Client REG_DWORD from the registry and sets
  1801. the global SrvMinNT5Client to the retrieved value. Later, if a client
  1802. running >= NT5 with a build number less than SrvMinNT5Client tries to
  1803. connect to a disk share, we reject the connection. This mechanism
  1804. is used on our SLM servers to ensure that people are upgrading to
  1805. current builds.
  1806. --*/
  1807. {
  1808. UNICODE_STRING unicodeKeyName;
  1809. UNICODE_STRING unicodeParamPath;
  1810. OBJECT_ATTRIBUTES objAttributes;
  1811. HANDLE keyHandle;
  1812. PKEY_VALUE_PARTIAL_INFORMATION infoBuffer;
  1813. ULONG lengthNeeded;
  1814. NTSTATUS status;
  1815. PAGED_CODE( );
  1816. SrvMinNT5Client = 0;
  1817. SrvMinNT5ClientIPCToo = FALSE;
  1818. RtlInitUnicodeString( &unicodeParamPath, StrRegSrvParameterPath );
  1819. RtlInitUnicodeString( &unicodeKeyName, L"MinNT5Client" );
  1820. InitializeObjectAttributes(
  1821. &objAttributes,
  1822. &unicodeParamPath,
  1823. OBJ_CASE_INSENSITIVE,
  1824. NULL,
  1825. NULL
  1826. );
  1827. status = ZwOpenKey(
  1828. &keyHandle,
  1829. KEY_QUERY_VALUE,
  1830. &objAttributes
  1831. );
  1832. if ( NT_SUCCESS(status) ) {
  1833. status = ZwQueryValueKey(
  1834. keyHandle,
  1835. &unicodeKeyName,
  1836. KeyValuePartialInformation,
  1837. NULL,
  1838. 0,
  1839. &lengthNeeded
  1840. );
  1841. if( status != STATUS_BUFFER_TOO_SMALL ) {
  1842. RtlInitUnicodeString( &unicodeKeyName, L"MinNT5ClientIPC" );
  1843. status = ZwQueryValueKey(
  1844. keyHandle,
  1845. &unicodeKeyName,
  1846. KeyValuePartialInformation,
  1847. NULL,
  1848. 0,
  1849. &lengthNeeded
  1850. );
  1851. SrvMinNT5ClientIPCToo = TRUE;
  1852. }
  1853. if( status == STATUS_BUFFER_TOO_SMALL ) {
  1854. infoBuffer = ALLOCATE_HEAP_COLD( lengthNeeded, BlockTypeDataBuffer );
  1855. if( infoBuffer ) {
  1856. status = ZwQueryValueKey(
  1857. keyHandle,
  1858. &unicodeKeyName,
  1859. KeyValuePartialInformation,
  1860. infoBuffer,
  1861. lengthNeeded,
  1862. &lengthNeeded
  1863. );
  1864. if( NT_SUCCESS( status ) &&
  1865. infoBuffer->Type == REG_DWORD &&
  1866. infoBuffer->DataLength == sizeof( DWORD ) ) {
  1867. SrvMinNT5Client = *(DWORD *)(&infoBuffer->Data[0]);
  1868. KdPrint(( "SRV: Restrict NT5 clients to builds >= %u\n",
  1869. SrvMinNT5Client ));
  1870. if( SrvMinNT5ClientIPCToo ) {
  1871. KdPrint(( " Restrict IPC clients\n" ));
  1872. }
  1873. }
  1874. FREE_HEAP( infoBuffer );
  1875. }
  1876. }
  1877. NtClose( keyHandle );
  1878. }
  1879. }
  1880. #endif
  1881. #if MULTIPROCESSOR
  1882. VOID
  1883. StartQueueDepthComputations(
  1884. PWORK_QUEUE queue
  1885. )
  1886. {
  1887. LARGE_INTEGER currentTime;
  1888. PAGED_CODE();
  1889. if( SrvNumberOfProcessors == 1 )
  1890. return;
  1891. //
  1892. // We're going to schedule a dpc to call the 'ComputeAvgQueueDepth' routine
  1893. // Initialize the dpc
  1894. //
  1895. KeInitializeDpc( &queue->QueueAvgDpc, ComputeAvgQueueDepth, queue );
  1896. //
  1897. // We want to make sure the dpc runs on the same processor handling the
  1898. // queue -- to avoid thrashing the cache
  1899. //
  1900. KeSetTargetProcessorDpc( &queue->QueueAvgDpc, (CCHAR)(queue - SrvWorkQueues));
  1901. //
  1902. // Initialize a timer object to schedule our dpc later
  1903. //
  1904. KeInitializeTimer( &queue->QueueAvgTimer );
  1905. KeQuerySystemTime( &currentTime );
  1906. queue->NextAvgUpdateTime.QuadPart = currentTime.QuadPart + SrvQueueCalc.QuadPart;
  1907. //
  1908. // Initialize the sample vector
  1909. //
  1910. queue->NextSample = queue->DepthSamples;
  1911. RtlZeroMemory( queue->DepthSamples, sizeof( queue->DepthSamples ) );
  1912. //
  1913. // And start it going!
  1914. //
  1915. KeSetTimer( &queue->QueueAvgTimer, queue->NextAvgUpdateTime, &queue->QueueAvgDpc );
  1916. }
  1917. VOID
  1918. StopQueueDepthComputations(
  1919. PWORK_QUEUE queue
  1920. )
  1921. {
  1922. KIRQL oldIrql;
  1923. if( SrvNumberOfProcessors == 1 )
  1924. return;
  1925. KeInitializeEvent( &queue->AvgQueueDepthTerminationEvent,
  1926. NotificationEvent,
  1927. FALSE
  1928. );
  1929. ACQUIRE_SPIN_LOCK( &queue->SpinLock, &oldIrql );
  1930. queue->NextSample = NULL;
  1931. RELEASE_SPIN_LOCK( &queue->SpinLock, oldIrql );
  1932. //
  1933. // Cancel the computation timer. If this works, then we know that
  1934. // the DPC code is not running. Otherwise, it is running or queued
  1935. // to run and we need to wait until it completes.
  1936. //
  1937. if( !KeCancelTimer( &queue->QueueAvgTimer ) ) {
  1938. KeWaitForSingleObject(
  1939. &queue->AvgQueueDepthTerminationEvent,
  1940. Executive,
  1941. KernelMode,
  1942. FALSE,
  1943. NULL
  1944. );
  1945. }
  1946. }
  1947. VOID
  1948. ComputeAvgQueueDepth (
  1949. IN PKDPC Dpc,
  1950. IN PVOID DeferredContext,
  1951. IN PVOID SystemArgument1,
  1952. IN PVOID SystemArgument2
  1953. )
  1954. {
  1955. LARGE_INTEGER currentTime;
  1956. PWORK_QUEUE queue = (PWORK_QUEUE)DeferredContext;
  1957. ACQUIRE_DPC_SPIN_LOCK( &queue->SpinLock );
  1958. if( queue->NextSample == NULL ) {
  1959. KeSetEvent( &queue->AvgQueueDepthTerminationEvent, 0, FALSE );
  1960. } else {
  1961. //
  1962. // Compute the sliding window average by taking a queue depth
  1963. // sample, removing the old sample value from the running sum
  1964. // and adding in the new value
  1965. //
  1966. currentTime.LowPart= PtrToUlong(SystemArgument1);
  1967. currentTime.HighPart = PtrToUlong(SystemArgument2);
  1968. queue->AvgQueueDepthSum -= *queue->NextSample;
  1969. *(queue->NextSample) = KeReadStateQueue( &queue->Queue );
  1970. queue->AvgQueueDepthSum += *queue->NextSample;
  1971. if( ++(queue->NextSample) == &queue->DepthSamples[ QUEUE_SAMPLES ] )
  1972. queue->NextSample = queue->DepthSamples;
  1973. queue->NextAvgUpdateTime.QuadPart =
  1974. currentTime.QuadPart + SrvQueueCalc.QuadPart;
  1975. KeSetTimer( &queue->QueueAvgTimer,
  1976. queue->NextAvgUpdateTime,
  1977. &queue->QueueAvgDpc );
  1978. }
  1979. RELEASE_DPC_SPIN_LOCK( &queue->SpinLock );
  1980. }
  1981. #endif // MULTIPROCESSOR