Source code of Windows XP (NT5)
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.

2239 lines
66 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fsddisp.c
  5. Abstract:
  6. This module implements the File System Driver for the LAN Manager
  7. server.
  8. Author:
  9. David Treadwell (davidtr) 20-May-1990
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "wmikm.h"
  14. #include "fsddisp.tmh"
  15. #pragma hdrstop
  16. #define BugCheckFileId SRV_FILE_FSDDISP
  17. #define CHANGE_HEURISTIC(heuristic) \
  18. (newValues->HeuristicsChangeMask & SRV_HEUR_ ## heuristic) != 0
  19. // Used for WMI event tracing
  20. //
  21. UNICODE_STRING SrvDeviceName;
  22. UNICODE_STRING SrvRegistryPath;
  23. ULONG SrvWmiInitialized = FALSE;
  24. ULONG SrvWmiEnableLevel = 0;
  25. ULONG SrvWmiEnableFlags = 0;
  26. TRACEHANDLE LoggerHandle = 0;
  27. GUID SrvCounterGuid = /* f7c3b22a-5992-44d6-968b-d3757dbab6f7 */
  28. { 0xf7c3b22a, 0x5992, 0x44d6, 0x96, 0x8b, 0xd3, 0x75, 0x7d, 0xba, 0xb6, 0xf7 };
  29. GUID SrvControlGuid = /* 3121cf5d-c5e6-4f37-be86-57083590c333 */
  30. { 0x3121cf5d, 0xc5e6, 0x4f37, 0xbe, 0x86, 0x57, 0x08, 0x35, 0x90, 0xc3, 0x33 };
  31. GUID SrvEventGuid = /* e09074ae-0a98-4805-9a41-a8940af97086 */
  32. { 0xe09074ae, 0x0a98, 0x4805, 0x9a, 0x41, 0xa8, 0x94, 0x0a, 0xf9, 0x70, 0x86 };
  33. WMIGUIDREGINFO SrvPerfGuidList[] =
  34. {
  35. { & SrvCounterGuid, 1, 0 },
  36. { & SrvControlGuid, 0, WMIREG_FLAG_TRACED_GUID
  37. | WMIREG_FLAG_TRACE_CONTROL_GUID }
  38. };
  39. #define SrvPerfGuidCount (sizeof(SrvPerfGuidList) / sizeof(WMIGUIDREGINFO))
  40. typedef struct _SRV_WMI_EVENT_TRACE {
  41. EVENT_TRACE_HEADER EventHeader;
  42. MOF_FIELD MofField[3];
  43. } SRV_WMI_EVENT_TRACE, * PSRV_WMI_EVENT_TRACE;
  44. //
  45. // Forward declarations
  46. //
  47. STATIC
  48. NTSTATUS
  49. SrvFsdDispatchFsControl (
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN PIRP Irp,
  52. IN PIO_STACK_LOCATION IrpSp
  53. );
  54. VOID
  55. QueueConfigurationIrp (
  56. IN PIRP Irp,
  57. IN PIO_WORKITEM pIoWorkItem
  58. );
  59. NTSTATUS
  60. SrvQueryWmiRegInfo(
  61. IN PDEVICE_OBJECT DeviceObject,
  62. OUT ULONG *RegFlags,
  63. OUT PUNICODE_STRING InstanceName,
  64. OUT PUNICODE_STRING *RegistryPath,
  65. OUT PUNICODE_STRING MofResourceName,
  66. OUT PDEVICE_OBJECT *Pdo
  67. );
  68. NTSTATUS
  69. SrvQueryWmiDataBlock(
  70. IN PDEVICE_OBJECT DeviceObject,
  71. IN PIRP Irp,
  72. IN ULONG GuidIndex,
  73. IN ULONG InstanceIndex,
  74. IN ULONG InstanceCount,
  75. IN OUT PULONG InstanceLengthArray,
  76. IN ULONG BufferAvail,
  77. OUT PUCHAR Buffer
  78. );
  79. #ifdef ALLOC_PRAGMA
  80. #pragma alloc_text( PAGE, SrvFsdDispatch )
  81. #pragma alloc_text( PAGE, SrvFsdDispatchFsControl )
  82. #pragma alloc_text( PAGE, QueueConfigurationIrp )
  83. #pragma alloc_text( PAGE, SrvWmiTraceEvent )
  84. #pragma alloc_text( PAGE, SrvQueryWmiRegInfo )
  85. #pragma alloc_text( PAGE, SrvQueryWmiDataBlock )
  86. #pragma alloc_text( PAGE, SrvWmiDispatch )
  87. #endif
  88. // These 2 routines can be called at DISPATCH_LEVEL, so they are non-paged
  89. // NONPAGED - SrvWmiStartContext
  90. // NONPAGED - SrvWmiEndContext
  91. void
  92. SrvWmiInitContext(
  93. PWORK_CONTEXT WorkContext
  94. )
  95. {
  96. if (! SrvWmiInitialized) {
  97. return;
  98. }
  99. if ( SRV_WMI_LEVEL( SPARSE ) ) {
  100. WorkContext->PreviousSMB = EVENT_TYPE_SMB_LAST_EVENT;
  101. WorkContext->bAlreadyTrace = FALSE;
  102. WorkContext->ElapseKCPU = 0;
  103. WorkContext->ElapseUCPU = 0;
  104. WorkContext->FileNameSize = 0;
  105. WorkContext->ClientAddr = 0;
  106. WorkContext->FileObject = NULL;
  107. WorkContext->G_StartTime.QuadPart =
  108. (ULONGLONG) WmiGetClock(WMICT_DEFAULT, NULL);
  109. }
  110. }
  111. void
  112. SrvWmiStartContext(
  113. PWORK_CONTEXT WorkContext
  114. )
  115. {
  116. LARGE_INTEGER ThreadTime;
  117. if (! SrvWmiInitialized) {
  118. return;
  119. }
  120. if ( SRV_WMI_LEVEL( SPARSE ) ) {
  121. if (WorkContext->G_StartTime.QuadPart == 0) {
  122. WorkContext->G_StartTime.QuadPart =
  123. (ULONGLONG) WmiGetClock(WMICT_DEFAULT, NULL);
  124. }
  125. }
  126. if ( SRV_WMI_LEVEL( VERBOSE ) ) {
  127. ThreadTime.QuadPart = (ULONGLONG) WmiGetClock(WMICT_THREAD, NULL);
  128. WorkContext->KCPUStart = ThreadTime.HighPart;
  129. WorkContext->UCPUStart = ThreadTime.LowPart;
  130. }
  131. }
  132. void
  133. SrvWmiEndContext(
  134. PWORK_CONTEXT WorkContext
  135. )
  136. {
  137. LARGE_INTEGER TimeEnd;
  138. BOOL NotDispatch = (KeGetCurrentIrql() < DISPATCH_LEVEL);
  139. if (! SrvWmiInitialized) {
  140. return;
  141. }
  142. if ( SRV_WMI_LEVEL( SPARSE ) ) {
  143. if ( NotDispatch && WorkContext && WorkContext->Rfcb && WorkContext->Rfcb->Lfcb) {
  144. WorkContext->FileObject = WorkContext->Rfcb->Lfcb->FileObject;
  145. }
  146. }
  147. if ( (SrvWmiEnableFlags == SRV_WMI_FLAG_CAPACITY) && SRV_WMI_LEVEL( VERBOSE ) ) {
  148. TimeEnd.QuadPart = (ULONGLONG) WmiGetClock(WMICT_THREAD, NULL);
  149. WorkContext->ElapseKCPU = TimeEnd.HighPart - WorkContext->KCPUStart;
  150. WorkContext->ElapseUCPU = TimeEnd.LowPart - WorkContext->UCPUStart;
  151. if( NotDispatch )
  152. {
  153. if (WorkContext && WorkContext->Rfcb
  154. && WorkContext->Rfcb->Lfcb
  155. && WorkContext->Rfcb->Lfcb->Mfcb
  156. && WorkContext->Rfcb->Lfcb->Mfcb->FileName.Buffer
  157. && WorkContext->Rfcb->Lfcb->Mfcb->FileName.Length > 0)
  158. {
  159. LPWSTR strFileName = WorkContext->Rfcb->Lfcb->Mfcb->FileName.Buffer;
  160. WorkContext->FileNameSize =
  161. (USHORT) ((wcslen(strFileName) + 1) * sizeof(WCHAR));
  162. if (WorkContext->FileNameSize > 1024 * sizeof(WCHAR)) {
  163. WorkContext->FileNameSize = 1024 * sizeof(WCHAR);
  164. }
  165. RtlCopyMemory(WorkContext->strFileName,
  166. strFileName,
  167. WorkContext->FileNameSize);
  168. WorkContext->strFileName[1023] = L'\0';
  169. }
  170. }
  171. else
  172. {
  173. WorkContext->strFileName[0] = L'\0';
  174. }
  175. }
  176. }
  177. void
  178. SrvWmiTraceEvent(
  179. PWORK_CONTEXT WorkContext
  180. )
  181. {
  182. PAGED_CODE();
  183. if (! SrvWmiInitialized) {
  184. return;
  185. }
  186. if ( (SrvWmiEnableFlags == SRV_WMI_FLAG_CAPACITY) && SRV_WMI_LEVEL( SPARSE ) ) {
  187. NTSTATUS status;
  188. SRV_WMI_EVENT_TRACE Wnode;
  189. if (WorkContext->PreviousSMB >= EVENT_TYPE_SMB_LAST_EVENT) {
  190. return;
  191. }
  192. if (WorkContext->Connection->DirectHostIpx) {
  193. WorkContext->ClientAddr =
  194. WorkContext->Connection->IpxAddress.NetworkAddress;
  195. }
  196. else {
  197. WorkContext->ClientAddr =
  198. WorkContext->Connection->ClientIPAddress;
  199. }
  200. RtlZeroMemory(& Wnode, sizeof(SRV_WMI_EVENT_TRACE));
  201. if (WorkContext->FileNameSize > 0) {
  202. Wnode.EventHeader.Size = sizeof(SRV_WMI_EVENT_TRACE);
  203. }
  204. else {
  205. Wnode.EventHeader.Size = sizeof(EVENT_TRACE_HEADER)
  206. + sizeof(MOF_FIELD);
  207. }
  208. Wnode.EventHeader.Flags = WNODE_FLAG_TRACED_GUID
  209. | WNODE_FLAG_USE_GUID_PTR
  210. | WNODE_FLAG_USE_MOF_PTR;
  211. Wnode.EventHeader.GuidPtr = (ULONGLONG) & SrvEventGuid;
  212. Wnode.EventHeader.Class.Type = WorkContext->PreviousSMB;
  213. ((PWNODE_HEADER) (& Wnode.EventHeader))->HistoricalContext =
  214. LoggerHandle;
  215. Wnode.MofField[0].Length = sizeof(LARGE_INTEGER) // G_StartTime
  216. + sizeof(ULONG) // ElapseKCPU
  217. + sizeof(ULONG) // ElapseUCPU
  218. + sizeof(ULONG) // ClientAddr
  219. + sizeof(PFILE_OBJECT); // FileObject
  220. Wnode.MofField[0].DataPtr = (ULONGLONG) (& WorkContext->G_StartTime);
  221. if (WorkContext->FileNameSize > 0) {
  222. Wnode.MofField[1].Length = sizeof(USHORT);
  223. Wnode.MofField[1].DataPtr =
  224. (ULONGLONG) (& WorkContext->FileNameSize);
  225. Wnode.MofField[2].Length = WorkContext->FileNameSize;
  226. Wnode.MofField[2].DataPtr =
  227. (ULONGLONG) (WorkContext->strFileName);
  228. }
  229. // Call TraceLogger to write this event
  230. //
  231. status = IoWMIWriteEvent((PVOID) & Wnode);
  232. if (!NT_SUCCESS(status)) {
  233. DbgPrint("SrvWmiTraceEvent(0x%08X,%d) fails 0x%08X\n",
  234. WorkContext, WorkContext->PreviousSMB, status);
  235. }
  236. }
  237. }
  238. NTSTATUS
  239. SrvQueryWmiRegInfo(
  240. IN PDEVICE_OBJECT DeviceObject,
  241. OUT ULONG *RegFlags,
  242. OUT PUNICODE_STRING InstanceName,
  243. OUT PUNICODE_STRING *RegistryPath,
  244. OUT PUNICODE_STRING MofResourceName,
  245. OUT PDEVICE_OBJECT *Pdo
  246. )
  247. /*++
  248. Routine Description:
  249. This routine is a callback into the driver to retrieve information about
  250. the guids being registered.
  251. Implementations of this routine may be in paged memory
  252. Arguments:
  253. DeviceObject is the device whose registration information is needed
  254. *RegFlags returns with a set of flags that describe all of the guids being
  255. registered for this device. If the device wants enable and disable
  256. collection callbacks before receiving queries for the registered
  257. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  258. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  259. the instance name is determined from the PDO associated with the
  260. device object. Note that the PDO must have an associated devnode. If
  261. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  262. name for the device. These flags are ORed into the flags specified
  263. by the GUIDREGINFO for each guid.
  264. InstanceName returns with the instance name for the guids if
  265. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  266. caller will call ExFreePool with the buffer returned.
  267. *RegistryPath returns with the registry path of the driver. This is
  268. required
  269. MofResourceName returns with the name of the MOF resource attached to
  270. the binary file. If the driver does not have a mof resource attached
  271. then this can be returned unmodified. If a value is returned then
  272. it is NOT freed.
  273. The MOF file is assumed to be already included in wmicore.mof
  274. *Pdo returns with the device object for the PDO associated with this
  275. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  276. *RegFlags.
  277. Return Value:
  278. status
  279. --*/
  280. {
  281. PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)
  282. DeviceObject->DeviceExtension;
  283. PAGED_CODE();
  284. if (! SrvWmiInitialized) {
  285. return STATUS_DEVICE_NOT_READY;
  286. }
  287. pDeviceExtension->TestCounter ++;
  288. * RegFlags = WMIREG_FLAG_EXPENSIVE;
  289. InstanceName->MaximumLength = SrvDeviceName.Length
  290. + sizeof(UNICODE_NULL);
  291. InstanceName->Buffer = ExAllocatePool(PagedPool,
  292. InstanceName->MaximumLength);
  293. if (InstanceName->Buffer != NULL) {
  294. InstanceName->Length = InstanceName->MaximumLength
  295. - sizeof(UNICODE_NULL);
  296. RtlCopyUnicodeString(InstanceName, & SrvDeviceName);
  297. }
  298. else {
  299. InstanceName->MaximumLength = InstanceName->Length = 0;
  300. }
  301. MofResourceName->MaximumLength = 0;
  302. MofResourceName->Length = 0;
  303. MofResourceName->Buffer = NULL;
  304. * RegistryPath = & SrvRegistryPath;
  305. return STATUS_SUCCESS;
  306. }
  307. NTSTATUS
  308. SrvQueryWmiDataBlock(
  309. IN PDEVICE_OBJECT DeviceObject,
  310. IN PIRP Irp,
  311. IN ULONG GuidIndex,
  312. IN ULONG InstanceIndex,
  313. IN ULONG InstanceCount,
  314. IN OUT PULONG InstanceLengthArray,
  315. IN ULONG BufferAvail,
  316. OUT PUCHAR Buffer
  317. )
  318. /*++
  319. Routine Description:
  320. This routine is a callback into the driver to query for the contents of
  321. all instances of a data block. When the driver has finished filling the
  322. data block it must call WmiCompleteRequest to complete the irp. The
  323. driver can return STATUS_PENDING if the irp cannot be completed
  324. immediately.
  325. Arguments:
  326. DeviceObject is the device whose data block is being queried
  327. Irp is the Irp that makes this request
  328. GuidIndex is the index into the list of guids provided when the
  329. device registered
  330. InstanceCount is the number of instnaces expected to be returned for
  331. the data block.
  332. InstanceLengthArray is a pointer to an array of ULONG that returns the
  333. lengths of each instance of the data block. If this is NULL then
  334. there was not enough space in the output buffer to fufill the request
  335. so the irp should be completed with the buffer needed.
  336. BufferAvail on entry has the maximum size available to write the data
  337. blocks.
  338. Buffer on return is filled with the returned data blocks. Note that each
  339. instance of the data block must be aligned on a 8 byte boundry.
  340. Return Value:
  341. status
  342. --*/
  343. {
  344. NTSTATUS Status = STATUS_SUCCESS;
  345. PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)
  346. DeviceObject->DeviceExtension;
  347. ULONG SizeNeeded = sizeof(ULONG);
  348. PAGED_CODE();
  349. if (! SrvWmiInitialized) {
  350. return STATUS_DEVICE_NOT_READY;
  351. }
  352. pDeviceExtension->TestCounter ++;
  353. if (GuidIndex == 0) {
  354. * InstanceLengthArray = SizeNeeded;
  355. * ((PULONG) Buffer) = pDeviceExtension->TestCounter;
  356. }
  357. else {
  358. Status = STATUS_WMI_GUID_NOT_FOUND;
  359. }
  360. Status = WmiCompleteRequest(DeviceObject,
  361. Irp,
  362. Status,
  363. SizeNeeded,
  364. IO_NO_INCREMENT);
  365. return Status;
  366. }
  367. NTSTATUS
  368. SrvWmiDispatch(
  369. IN PDEVICE_OBJECT DeviceObject,
  370. IN PIRP Irp
  371. )
  372. {
  373. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  374. ULONG BufferSize = irpSp->Parameters.WMI.BufferSize;
  375. PVOID Buffer = irpSp->Parameters.WMI.Buffer;
  376. ULONG ReturnSize = 0;
  377. NTSTATUS Status = STATUS_SUCCESS;
  378. PWNODE_HEADER pWnode = NULL;
  379. PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)
  380. DeviceObject->DeviceExtension;
  381. SYSCTL_IRP_DISPOSITION disposition;
  382. PAGED_CODE();
  383. switch (irpSp->MinorFunction) {
  384. case IRP_MN_ENABLE_EVENTS:
  385. pWnode = (PWNODE_HEADER) Buffer;
  386. if (BufferSize >= sizeof(WNODE_HEADER)) {
  387. LoggerHandle = pWnode->HistoricalContext;
  388. InterlockedExchange(& SrvWmiEnableLevel,
  389. ((PTRACE_ENABLE_CONTEXT) (& LoggerHandle))->Level + 1);
  390. InterlockedExchange(& SrvWmiEnableFlags,
  391. ((PTRACE_ENABLE_CONTEXT) (& LoggerHandle))->EnableFlags );
  392. }
  393. Irp->IoStatus.Status = Status;
  394. Irp->IoStatus.Information = ReturnSize;
  395. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  396. break;
  397. case IRP_MN_DISABLE_EVENTS:
  398. InterlockedExchange(& SrvWmiEnableLevel, 0);
  399. LoggerHandle = 0;
  400. Irp->IoStatus.Status = Status;
  401. Irp->IoStatus.Information = ReturnSize;
  402. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  403. break;
  404. default:
  405. Status = WmiSystemControl(& pDeviceExtension->WmiLibContext,
  406. DeviceObject,
  407. Irp,
  408. & disposition);
  409. switch(disposition) {
  410. case IrpProcessed:
  411. break;
  412. case IrpNotCompleted:
  413. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  414. break;
  415. case IrpForward:
  416. case IrpNotWmi:
  417. default:
  418. ASSERT(FALSE);
  419. Irp->IoStatus.Status = Status = STATUS_NOT_SUPPORTED;
  420. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  421. break;
  422. }
  423. break;
  424. }
  425. return Status;
  426. }
  427. NTSTATUS
  428. SrvFsdDispatch (
  429. IN PDEVICE_OBJECT DeviceObject,
  430. IN PIRP Irp
  431. )
  432. /*++
  433. Routine Description:
  434. This is the dispatch routine for the LAN Manager server FSD. At the
  435. present time, the server FSD does not accept any I/O requests.
  436. Arguments:
  437. DeviceObject - Pointer to device object for target device
  438. Irp - Pointer to I/O request packet
  439. Return Value:
  440. NTSTATUS -- Indicates whether the request was successfully queued.
  441. --*/
  442. {
  443. NTSTATUS status = STATUS_SUCCESS;
  444. PIO_STACK_LOCATION irpSp;
  445. PIO_WORKITEM pWorkItem;
  446. PAGED_CODE( );
  447. DeviceObject; // prevent compiler warnings
  448. if( SrvSvcProcess == NULL &&
  449. SeSinglePrivilegeCheck( SeExports->SeLoadDriverPrivilege, Irp->RequestorMode ) ) {
  450. //
  451. // This is the first fsctl to the server from a process having
  452. // driver load/unload privileges -- it must be from
  453. // the service controller. Remember the process id of the
  454. // service controller to validate future fsctls
  455. //
  456. SrvSvcProcess = IoGetCurrentProcess();
  457. }
  458. irpSp = IoGetCurrentIrpStackLocation( Irp );
  459. #if defined( _WIN64 )
  460. // There is no reason for us to support downlevel clients because all communication with the
  461. // server (that is not network packets) goes through the Server Service via RPC resulting in
  462. // it being serialized and interpreted correctly. If we get IOCTL's called directly, it must
  463. // be a hack attempt, so we're free to turn it away.
  464. if ( IoIs32bitProcess( Irp ) )
  465. {
  466. status = STATUS_NOT_SUPPORTED;
  467. Irp->IoStatus.Status = status;
  468. IoCompleteRequest( Irp, 2 );
  469. return status;
  470. }
  471. #endif
  472. switch ( irpSp->MajorFunction ) {
  473. case IRP_MJ_CREATE:
  474. FsRtlEnterFileSystem();
  475. ACQUIRE_LOCK( &SrvConfigurationLock );
  476. do {
  477. if( SrvOpenCount == 0 ) {
  478. //
  479. // This is the first open. Let's not allow it if the server
  480. // seems to be in a weird state.
  481. //
  482. if( SrvFspActive != FALSE || SrvFspTransitioning != FALSE ) {
  483. //
  484. // How can this be? Better not let anybody in, since we're sick
  485. //
  486. status = STATUS_ACCESS_DENIED;
  487. break;
  488. }
  489. } else if( SrvFspActive && SrvFspTransitioning ) {
  490. //
  491. // We currently have some open handles, but
  492. // we are in the middle of terminating. Don't let new
  493. // opens in
  494. //
  495. status = STATUS_ACCESS_DENIED;
  496. break;
  497. }
  498. SrvOpenCount++;
  499. } while( 0 );
  500. RELEASE_LOCK( &SrvConfigurationLock );
  501. FsRtlExitFileSystem();
  502. break;
  503. case IRP_MJ_CLEANUP:
  504. //
  505. // Stop SmbTrace if the one closing is the client who started it.
  506. //
  507. SmbTraceStop( irpSp->FileObject, SMBTRACE_SERVER );
  508. break;
  509. case IRP_MJ_CLOSE:
  510. FsRtlEnterFileSystem();
  511. ACQUIRE_LOCK( &SrvConfigurationLock );
  512. if( --SrvOpenCount == 0 ) {
  513. if( SrvFspActive && !SrvFspTransitioning ) {
  514. //
  515. // Uh oh. This is our last close, and we think
  516. // we're still running. We can't run sensibly
  517. // without srvsvc to help out. Suicide time!
  518. //
  519. pWorkItem = IoAllocateWorkItem( SrvDeviceObject );
  520. if( !pWorkItem )
  521. {
  522. status = STATUS_INSUFFICIENT_RESOURCES;
  523. RELEASE_LOCK( &SrvConfigurationLock );
  524. FsRtlExitFileSystem();
  525. goto exit;
  526. }
  527. SrvXsActive = FALSE;
  528. SrvFspTransitioning = TRUE;
  529. IoMarkIrpPending( Irp );
  530. QueueConfigurationIrp( Irp, pWorkItem );
  531. RELEASE_LOCK( &SrvConfigurationLock );
  532. status = STATUS_PENDING;
  533. FsRtlExitFileSystem();
  534. goto exit;
  535. }
  536. }
  537. RELEASE_LOCK( &SrvConfigurationLock );
  538. FsRtlExitFileSystem();
  539. break;
  540. case IRP_MJ_FILE_SYSTEM_CONTROL:
  541. status = SrvFsdDispatchFsControl( DeviceObject, Irp, irpSp );
  542. goto exit;
  543. case IRP_MJ_SYSTEM_CONTROL:
  544. if (SrvWmiInitialized) {
  545. status = SrvWmiDispatch(DeviceObject, Irp);
  546. goto exit;
  547. }
  548. // else fall through default processing
  549. //
  550. default:
  551. IF_DEBUG(ERRORS) {
  552. SrvPrint1(
  553. "SrvFsdDispatch: Invalid major function %lx\n",
  554. irpSp->MajorFunction
  555. );
  556. }
  557. status = STATUS_NOT_IMPLEMENTED;
  558. break;
  559. }
  560. Irp->IoStatus.Status = status;
  561. IoCompleteRequest( Irp, 2 );
  562. exit:
  563. return status;
  564. } // SrvFsdDispatch
  565. NTSTATUS
  566. SrvFsdDispatchFsControl (
  567. IN PDEVICE_OBJECT DeviceObject,
  568. IN PIRP Irp,
  569. IN PIO_STACK_LOCATION IrpSp
  570. )
  571. /*++
  572. Routine Description:
  573. This routine handles device IO control requests to the server,
  574. including starting the server, stopping the server, and more.
  575. Arguments:
  576. DeviceObject - Pointer to device object for target device
  577. Irp - Pointer to I/O request packet
  578. IrpSp - Pointer to the current IRP stack location
  579. Return Value:
  580. NTSTATUS -- Indicates whether the request was successfully handled.
  581. --*/
  582. {
  583. NTSTATUS status;
  584. ULONG code;
  585. PIO_WORKITEM pWorkItem;
  586. DeviceObject; // prevent compiler warnings
  587. //
  588. // Initialize the I/O status block.
  589. //
  590. Irp->IoStatus.Status = STATUS_PENDING;
  591. Irp->IoStatus.Information = 0;
  592. FsRtlEnterFileSystem();
  593. //
  594. // Process the request if possible.
  595. //
  596. code = IrpSp->Parameters.FileSystemControl.FsControlCode;
  597. //
  598. // Only the serice controller can issue most of the FSCTL requests.
  599. //
  600. if( Irp->RequestorMode != KernelMode &&
  601. IoGetCurrentProcess() != SrvSvcProcess ) {
  602. if( code != FSCTL_SRV_SEND_DATAGRAM &&
  603. code != FSCTL_SRV_GET_QUEUE_STATISTICS &&
  604. code != FSCTL_SRV_GET_STATISTICS &&
  605. code != FSCTL_SRV_IPX_SMART_CARD_START &&
  606. code != FSCTL_SRV_SHARE_STATE_CHANGE &&
  607. code != FSCTL_SRV_GET_CHALLENGE &&
  608. code != FSCTL_SRV_START_SMBTRACE &&
  609. code != FSCTL_SRV_SMBTRACE_FREE_SMB &&
  610. code != FSCTL_SRV_END_SMBTRACE &&
  611. code != FSCTL_SRV_INTERNAL_TEST_REAUTH) {
  612. status = STATUS_ACCESS_DENIED;
  613. goto exit_without_lock;
  614. }
  615. }
  616. //
  617. // Acquire the configuration lock.
  618. //
  619. ACQUIRE_LOCK( &SrvConfigurationLock );
  620. switch ( code ) {
  621. case FSCTL_SRV_STARTUP: {
  622. PSERVER_REQUEST_PACKET srp;
  623. ULONG srpLength;
  624. PVOID inputBuffer;
  625. ULONG inputBufferLength;
  626. PDEVICE_EXTENSION pDeviceExtension;
  627. PWMILIB_CONTEXT pWmiLibContext;
  628. //
  629. // Get a pointer to the SRP that describes the set info request
  630. // for the startup server configuration, and the buffer that
  631. // contains this information.
  632. //
  633. srp = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
  634. srpLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  635. inputBuffer = Irp->UserBuffer;
  636. inputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  637. //
  638. // If the server FSP is already started, or is in the process of
  639. // starting up, reject this request.
  640. //
  641. if ( SrvFspActive || SrvFspTransitioning ) {
  642. //IF_DEBUG(ERRORS) {
  643. // SrvPrint0( "LAN Manager server FSP already started.\n" );
  644. //}
  645. srp->ErrorCode = NERR_ServiceInstalled;
  646. status = STATUS_SUCCESS;
  647. goto exit_with_lock;
  648. }
  649. //
  650. // Make sure that the buffer was large enough to be an SRP.
  651. //
  652. if ( srpLength < sizeof(SERVER_REQUEST_PACKET) ) {
  653. status = STATUS_INVALID_PARAMETER;
  654. goto exit_with_lock;
  655. }
  656. //
  657. // If a domain name was specified in the SRP, the buffer field
  658. // contains an offset rather than a pointer. Convert the offset
  659. // to a pointer and verify that that it is a legal pointer.
  660. //
  661. OFFSET_TO_POINTER( srp->Name1.Buffer, srp );
  662. if ( !POINTER_IS_VALID( srp->Name1.Buffer, srp, srpLength ) ) {
  663. status = STATUS_ACCESS_VIOLATION;
  664. goto exit_with_lock;
  665. }
  666. //
  667. // If a server name was specified in the SRP, the buffer field
  668. // contains an offset rather than a pointer. Convert the offset
  669. // to a pointer and verify that that it is a legal pointer.
  670. //
  671. OFFSET_TO_POINTER( srp->Name2.Buffer, srp );
  672. if ( !POINTER_IS_VALID( srp->Name2.Buffer, srp, srpLength ) ) {
  673. status = STATUS_ACCESS_VIOLATION;
  674. goto exit_with_lock;
  675. }
  676. //
  677. // Call SrvNetServerSetInfo to set the initial server configuration
  678. // information.
  679. //
  680. status = SrvNetServerSetInfo(
  681. srp,
  682. inputBuffer,
  683. inputBufferLength
  684. );
  685. //
  686. // Indicate that the server is starting up. This prevents
  687. // further startup requests from being issued.
  688. //
  689. SrvFspTransitioning = TRUE;
  690. // Setup device extension for Perf counter registration and register
  691. // with WMI here
  692. //
  693. pDeviceExtension = (PDEVICE_EXTENSION) SrvDeviceObject->DeviceExtension;
  694. RtlZeroMemory(pDeviceExtension, sizeof(DEVICE_EXTENSION));
  695. pDeviceExtension->pDeviceObject = SrvDeviceObject;
  696. pWmiLibContext = & pDeviceExtension->WmiLibContext;
  697. RtlZeroMemory(pWmiLibContext, sizeof(WMILIB_CONTEXT));
  698. pWmiLibContext->GuidCount = SrvPerfGuidCount;
  699. pWmiLibContext->GuidList = SrvPerfGuidList;
  700. pWmiLibContext->QueryWmiDataBlock = SrvQueryWmiDataBlock;
  701. pWmiLibContext->QueryWmiRegInfo = SrvQueryWmiRegInfo;
  702. SrvWmiInitialized = TRUE;
  703. status = IoWMIRegistrationControl(
  704. SrvDeviceObject, WMIREG_ACTION_REGISTER);
  705. if (!NT_SUCCESS(status)) {
  706. DbgPrint("SRV: Failed to register for WMI support\n");
  707. }
  708. break;
  709. }
  710. case FSCTL_SRV_SHUTDOWN: {
  711. //
  712. // If the server is not running, or if it is in the process
  713. // of shutting down, ignore this request.
  714. //
  715. if ( !SrvFspActive || SrvFspTransitioning ) {
  716. //
  717. // If there is more than one handle open to the server
  718. // device (i.e., any handles other than the server service's
  719. // handle), return a special status code to the caller (who
  720. // should be the server service). This tells the caller to
  721. // NOT unload the driver, in order prevent weird situations
  722. // where the driver is sort of unloaded, so it can't be used
  723. // but also can't be reloaded, thus preventing the server
  724. // from being restarted.
  725. //
  726. if ( SrvOpenCount != 1 ) {
  727. status = STATUS_SERVER_HAS_OPEN_HANDLES;
  728. } else {
  729. status = STATUS_SUCCESS;
  730. }
  731. goto exit_with_lock;
  732. }
  733. if (SrvWmiInitialized) {
  734. // Deregister WMI
  735. //
  736. SrvWmiInitialized = FALSE;
  737. IoWMIRegistrationControl(SrvDeviceObject, WMIREG_ACTION_DEREGISTER);
  738. }
  739. //
  740. // Indicate that the server is shutting down. This prevents
  741. // further requests from being issued until the server is
  742. // restarted.
  743. //
  744. SrvFspTransitioning = TRUE;
  745. //
  746. // If SmbTrace is running, stop it.
  747. //
  748. SmbTraceStop( NULL, SMBTRACE_SERVER );
  749. break;
  750. }
  751. case FSCTL_SRV_REGISTRY_CHANGE:
  752. case FSCTL_SRV_BEGIN_PNP_NOTIFICATIONS:
  753. case FSCTL_SRV_XACTSRV_CONNECT:
  754. {
  755. if( !SrvFspActive || SrvFspTransitioning ) {
  756. //IF_DEBUG(ERRORS) {
  757. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  758. //}
  759. status = STATUS_SERVER_NOT_STARTED;
  760. goto exit_with_lock;
  761. }
  762. break;
  763. }
  764. case FSCTL_SRV_XACTSRV_DISCONNECT: {
  765. //
  766. // If the server is not running, or if it is in the process
  767. // of shutting down, ignore this request.
  768. //
  769. if ( !SrvFspActive || SrvFspTransitioning ) {
  770. //IF_DEBUG(ERRORS) {
  771. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  772. //}
  773. status = STATUS_SUCCESS;
  774. goto exit_with_lock;
  775. }
  776. break;
  777. }
  778. case FSCTL_SRV_IPX_SMART_CARD_START: {
  779. //
  780. // If the server is not running, or if it is in the process of
  781. // shutting down, ignore this request.
  782. //
  783. if( !SrvFspActive || SrvFspTransitioning ) {
  784. status = STATUS_SERVER_NOT_STARTED;
  785. goto exit_with_lock;
  786. }
  787. //
  788. // Make sure the caller is a driver
  789. //
  790. if( Irp->RequestorMode != KernelMode ) {
  791. status = STATUS_ACCESS_DENIED;
  792. goto exit_with_lock;
  793. }
  794. //
  795. // Make sure the buffer is big enough
  796. //
  797. if( IrpSp->Parameters.FileSystemControl.InputBufferLength <
  798. sizeof( SrvIpxSmartCard ) ) {
  799. status = STATUS_BUFFER_TOO_SMALL;
  800. goto exit_with_lock;
  801. }
  802. if( SrvIpxSmartCard.Open == NULL ) {
  803. PSRV_IPX_SMART_CARD pSipx;
  804. //
  805. // Load up the pointers
  806. //
  807. pSipx = (PSRV_IPX_SMART_CARD)(Irp->AssociatedIrp.SystemBuffer);
  808. if( pSipx == NULL ) {
  809. status = STATUS_INVALID_PARAMETER;
  810. goto exit_with_lock;
  811. }
  812. if( pSipx->Read && pSipx->Close && pSipx->DeRegister && pSipx->Open ) {
  813. IF_DEBUG( SIPX ) {
  814. KdPrint(( "Accepting entry points for IPX Smart Card:\n" ));
  815. KdPrint(( " Open %p, Read %p, Close %p, DeRegister %p",
  816. SrvIpxSmartCard.Open,
  817. SrvIpxSmartCard.Read,
  818. SrvIpxSmartCard.Close,
  819. SrvIpxSmartCard.DeRegister
  820. ));
  821. }
  822. //
  823. // First set our entry point
  824. //
  825. pSipx->ReadComplete = SrvIpxSmartCardReadComplete;
  826. //
  827. // Now accept the card's entry points.
  828. //
  829. SrvIpxSmartCard.Read = pSipx->Read;
  830. SrvIpxSmartCard.Close= pSipx->Close;
  831. SrvIpxSmartCard.DeRegister = pSipx->DeRegister;
  832. SrvIpxSmartCard.Open = pSipx->Open;
  833. status = STATUS_SUCCESS;
  834. } else {
  835. status = STATUS_INVALID_PARAMETER;
  836. }
  837. } else {
  838. status = STATUS_DEVICE_ALREADY_ATTACHED;
  839. }
  840. goto exit_with_lock;
  841. break;
  842. }
  843. case FSCTL_SRV_SEND_DATAGRAM:
  844. {
  845. PVOID systemBuffer;
  846. ULONG systemBufferLength;
  847. PVOID buffer1;
  848. ULONG buffer1Length;
  849. PVOID buffer2;
  850. ULONG buffer2Length;
  851. PSERVER_REQUEST_PACKET srp;
  852. //
  853. // Ignore this request if the server is not active.
  854. //
  855. if ( !SrvFspActive || SrvFspTransitioning ) {
  856. status = STATUS_SUCCESS;
  857. goto exit_with_lock;
  858. }
  859. //
  860. // Determine the input buffer lengths, and make sure that the
  861. // first buffer is large enough to be an SRP.
  862. //
  863. buffer1Length = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  864. buffer2Length = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  865. //
  866. // Make sure that the buffer was large enough to be a SRP.
  867. //
  868. if ( buffer1Length < sizeof(SERVER_REQUEST_PACKET) ) {
  869. status = STATUS_INVALID_PARAMETER;
  870. goto exit_with_lock;
  871. }
  872. // Make sure the lengths are nominally reasonable.
  873. //
  874. if( buffer1Length >= MAXUSHORT ||
  875. buffer2Length >= MAXUSHORT ) {
  876. status = STATUS_INVALID_PARAMETER;
  877. goto exit_with_lock;
  878. }
  879. //
  880. // Make the first buffer size is properly aligned so that the second
  881. // buffer will be aligned as well.
  882. //
  883. buffer1Length = ALIGN_UP( buffer1Length, PVOID );
  884. systemBufferLength = buffer1Length + buffer2Length;
  885. //
  886. // Make sure the lengths are nominally reasonable.
  887. //
  888. if( buffer1Length >= MAXUSHORT ||
  889. buffer2Length >= MAXUSHORT ||
  890. systemBufferLength == 0 ) {
  891. status = STATUS_INVALID_PARAMETER;
  892. goto exit_with_lock;
  893. }
  894. if( Irp->RequestorMode != KernelMode ) {
  895. try {
  896. ProbeForRead( IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
  897. buffer1Length, sizeof( CHAR )
  898. );
  899. if( buffer2Length ) {
  900. ProbeForRead( Irp->UserBuffer, buffer2Length, sizeof( CHAR ) );
  901. }
  902. } except( EXCEPTION_EXECUTE_HANDLER ) {
  903. status = GetExceptionCode();
  904. goto exit_with_lock;
  905. }
  906. }
  907. //
  908. // Allocate a single buffer that will hold both input buffers.
  909. //
  910. systemBuffer = ExAllocatePoolWithTagPriority( PagedPool, systemBufferLength, BlockTypeMisc, LowPoolPriority );
  911. if ( systemBuffer == NULL ) {
  912. status = STATUS_INSUFF_SERVER_RESOURCES;
  913. goto exit_with_lock;
  914. }
  915. buffer1 = systemBuffer;
  916. buffer2 = (PCHAR)systemBuffer + buffer1Length;
  917. //
  918. // Copy the information into the buffers.
  919. //
  920. try {
  921. RtlCopyMemory(
  922. buffer1,
  923. IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
  924. IrpSp->Parameters.FileSystemControl.InputBufferLength
  925. );
  926. if ( buffer2Length > 0 ) {
  927. RtlCopyMemory( buffer2, Irp->UserBuffer, buffer2Length );
  928. }
  929. } except( EXCEPTION_EXECUTE_HANDLER ) {
  930. status = GetExceptionCode();
  931. ExFreePool( buffer1 );
  932. goto exit_with_lock;
  933. }
  934. //
  935. // If a name was specified in the SRP, the buffer field will
  936. // contain an offset rather than a pointer. Convert the offset
  937. // to a pointer and verify that that it is a legal pointer.
  938. //
  939. srp = buffer1;
  940. OFFSET_TO_POINTER( srp->Name1.Buffer, srp );
  941. if ( !POINTER_IS_VALID( srp->Name1.Buffer, srp, buffer1Length ) ) {
  942. status = STATUS_ACCESS_VIOLATION;
  943. ExFreePool( buffer1 );
  944. goto exit_with_lock;
  945. }
  946. OFFSET_TO_POINTER( srp->Name2.Buffer, srp );
  947. if ( !POINTER_IS_VALID( srp->Name2.Buffer, srp, buffer1Length ) ) {
  948. status = STATUS_ACCESS_VIOLATION;
  949. ExFreePool( buffer1 );
  950. goto exit_with_lock;
  951. }
  952. Irp->AssociatedIrp.SystemBuffer = systemBuffer;
  953. break;
  954. }
  955. case FSCTL_SRV_SHARE_STATE_CHANGE:
  956. {
  957. ULONG srpLength;
  958. PSERVER_REQUEST_PACKET srp;
  959. PSHARE share;
  960. if ( !SrvFspActive || SrvFspTransitioning ) {
  961. status = STATUS_SUCCESS;
  962. goto exit_with_lock;
  963. }
  964. srp = Irp->AssociatedIrp.SystemBuffer;
  965. srpLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  966. //
  967. // Make sure that the buffer was large enough to be a SRP.
  968. //
  969. if ( srpLength < sizeof(SERVER_REQUEST_PACKET) ||
  970. srp->Name1.Length == 0) {
  971. status = STATUS_INVALID_PARAMETER;
  972. goto exit_with_lock;
  973. }
  974. //
  975. // Adjust the buffer pointer to the srp address
  976. //
  977. (ULONG_PTR) (srp->Name1.Buffer) += (ULONG_PTR) srp;
  978. if( (PCHAR) (srp->Name1.Buffer) < (PCHAR) srp ||
  979. srp->Name1.Length > srpLength ||
  980. (PCHAR) (srp->Name1.Buffer) > (PCHAR)srp + srpLength - srp->Name1.Length ||
  981. (((ULONG_PTR)(srp->Name1.Buffer) & ((sizeof(WCHAR)) - 1)) != 0) ) {
  982. status = STATUS_ACCESS_VIOLATION;
  983. goto exit_with_lock;
  984. }
  985. ACQUIRE_LOCK( &SrvShareLock );
  986. share = SrvFindShare( &srp->Name1 );
  987. if ( share != NULL) {
  988. share->IsDfs = ((srp->Flags & SRP_SET_SHARE_IN_DFS) != 0);
  989. status = STATUS_SUCCESS;
  990. } else {
  991. status = STATUS_OBJECT_NAME_NOT_FOUND;
  992. }
  993. RELEASE_LOCK( &SrvShareLock );
  994. goto exit_with_lock;
  995. break;
  996. }
  997. case FSCTL_SRV_CHANGE_DOMAIN_NAME:
  998. {
  999. ULONG srpLength;
  1000. PSERVER_REQUEST_PACKET srp;
  1001. PSHARE share;
  1002. PLIST_ENTRY listEntry;
  1003. PENDPOINT endpoint;
  1004. if ( !SrvFspActive || SrvFspTransitioning ) {
  1005. status = STATUS_SUCCESS;
  1006. goto exit_with_lock;
  1007. }
  1008. srp = Irp->AssociatedIrp.SystemBuffer;
  1009. srpLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  1010. //
  1011. // Make sure that the buffer was large enough to be a SRP.
  1012. //
  1013. if ( srpLength < sizeof(SERVER_REQUEST_PACKET) ||
  1014. srp->Name1.Length == 0) {
  1015. status = STATUS_INVALID_PARAMETER;
  1016. goto exit_with_lock;
  1017. }
  1018. //
  1019. // Adjust the buffer pointer to the srp address
  1020. //
  1021. (UINT_PTR) (srp->Name1.Buffer) += (UINT_PTR) srp;
  1022. (UINT_PTR) (srp->Name2.Buffer) += (UINT_PTR) srp;
  1023. if( (PCHAR) (srp->Name1.Buffer) < (PCHAR) srp ||
  1024. srp->Name1.Length > srpLength ||
  1025. (PCHAR) (srp->Name1.Buffer) > (PCHAR)srp + srpLength - srp->Name1.Length ||
  1026. (((UINT_PTR)(srp->Name1.Buffer) & ((sizeof(WCHAR)) - 1)) != 0) ) {
  1027. status = STATUS_ACCESS_VIOLATION;
  1028. goto exit_with_lock;
  1029. }
  1030. if( (PCHAR) (srp->Name2.Buffer) < (PCHAR) srp ||
  1031. srp->Name2.Length > srpLength ||
  1032. (PCHAR) (srp->Name2.Buffer) > (PCHAR)srp + srpLength - srp->Name2.Length ||
  1033. (((UINT_PTR)(srp->Name2.Buffer) & ((sizeof(WCHAR)) - 1)) != 0) ) {
  1034. status = STATUS_ACCESS_VIOLATION;
  1035. goto exit_with_lock;
  1036. }
  1037. //
  1038. // Run the endpoints and change the domain name for any endpoint having
  1039. // the original domain name. Note that the endpoint's domain name string buffers
  1040. // have already been allocated to the largest possible domain name.
  1041. //
  1042. ACQUIRE_LOCK( &SrvEndpointLock );
  1043. for( listEntry = SrvEndpointList.ListHead.Flink;
  1044. listEntry != &SrvEndpointList.ListHead;
  1045. listEntry = listEntry->Flink
  1046. ) {
  1047. endpoint = CONTAINING_RECORD(
  1048. listEntry,
  1049. ENDPOINT,
  1050. GlobalEndpointListEntry
  1051. );
  1052. if( GET_BLOCK_STATE(endpoint) == BlockStateActive ) {
  1053. if( RtlEqualUnicodeString( &srp->Name1, &endpoint->DomainName, TRUE ) ) {
  1054. //
  1055. // Update the UNICODE domain name string
  1056. //
  1057. RtlCopyUnicodeString( &endpoint->DomainName, &srp->Name2 );
  1058. //
  1059. // Update the Oem domain name string
  1060. //
  1061. endpoint->OemDomainName.Length =
  1062. (SHORT)RtlUnicodeStringToOemSize( &endpoint->DomainName );
  1063. ASSERT( endpoint->OemDomainName.Length <=
  1064. endpoint->OemDomainName.MaximumLength );
  1065. RtlUnicodeStringToOemString(
  1066. &endpoint->OemDomainName,
  1067. &endpoint->DomainName,
  1068. FALSE // no allocate
  1069. );
  1070. }
  1071. }
  1072. }
  1073. RELEASE_LOCK( &SrvEndpointLock );
  1074. break;
  1075. }
  1076. case FSCTL_SRV_CHANGE_DNS_DOMAIN_NAME:
  1077. {
  1078. ULONG srpLength;
  1079. PSERVER_REQUEST_PACKET srp;
  1080. PSHARE share;
  1081. PLIST_ENTRY listEntry;
  1082. PENDPOINT endpoint;
  1083. PUNICODE_STRING pStr;
  1084. if ( !SrvFspActive || SrvFspTransitioning ) {
  1085. status = STATUS_SUCCESS;
  1086. goto exit_with_lock;
  1087. }
  1088. srp = Irp->AssociatedIrp.SystemBuffer;
  1089. srpLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  1090. //
  1091. // Make sure that the buffer was large enough to be a SRP.
  1092. //
  1093. if ( srpLength < sizeof(SERVER_REQUEST_PACKET) ||
  1094. srp->Name1.Length == 0) {
  1095. status = STATUS_INVALID_PARAMETER;
  1096. goto exit_with_lock;
  1097. }
  1098. //
  1099. // Adjust the buffer pointer to the srp address
  1100. //
  1101. (UINT_PTR) (srp->Name1.Buffer) += (UINT_PTR) srp;
  1102. (UINT_PTR) (srp->Name2.Buffer) += (UINT_PTR) srp;
  1103. if( (PCHAR) (srp->Name1.Buffer) < (PCHAR) srp ||
  1104. srp->Name1.Length > srpLength ||
  1105. (PCHAR) (srp->Name1.Buffer) > (PCHAR)srp + srpLength - srp->Name1.Length ||
  1106. (((UINT_PTR)(srp->Name1.Buffer) & ((sizeof(WCHAR)) - 1)) != 0) ) {
  1107. status = STATUS_ACCESS_VIOLATION;
  1108. goto exit_with_lock;
  1109. }
  1110. if( (PCHAR) (srp->Name2.Buffer) < (PCHAR) srp ||
  1111. srp->Name2.Length > srpLength ||
  1112. (PCHAR) (srp->Name2.Buffer) > (PCHAR)srp + srpLength - srp->Name2.Length ||
  1113. (((UINT_PTR)(srp->Name2.Buffer) & ((sizeof(WCHAR)) - 1)) != 0) ) {
  1114. status = STATUS_ACCESS_VIOLATION;
  1115. goto exit_with_lock;
  1116. }
  1117. if( RtlEqualUnicodeString( &srp->Name1, &srp->Name2, TRUE ) )
  1118. {
  1119. // The DNS name is equal to the Netbios name, so avoid the check
  1120. ACQUIRE_LOCK( &SrvEndpointLock );
  1121. if( SrvDnsDomainName )
  1122. {
  1123. DEALLOCATE_NONPAGED_POOL( SrvDnsDomainName );
  1124. SrvDnsDomainName = NULL;
  1125. }
  1126. RELEASE_LOCK( &SrvEndpointLock );
  1127. status = STATUS_SUCCESS;
  1128. }
  1129. else
  1130. {
  1131. //
  1132. // Change the DNS domain name
  1133. //
  1134. pStr = (PUNICODE_STRING)ALLOCATE_NONPAGED_POOL( sizeof(UNICODE_STRING) + srp->Name2.Length, BlockTypeMisc );
  1135. if( !pStr )
  1136. {
  1137. status = STATUS_INSUFFICIENT_RESOURCES;
  1138. goto exit_with_lock;
  1139. }
  1140. pStr->MaximumLength = pStr->Length = srp->Name2.Length;
  1141. pStr->Buffer = (PWSTR)(pStr+1);
  1142. RtlCopyMemory( pStr->Buffer, srp->Name2.Buffer, srp->Name2.Length );
  1143. ACQUIRE_LOCK( &SrvEndpointLock );
  1144. if( SrvDnsDomainName )
  1145. {
  1146. DEALLOCATE_NONPAGED_POOL( SrvDnsDomainName );
  1147. }
  1148. SrvDnsDomainName = pStr;
  1149. RELEASE_LOCK( &SrvEndpointLock );
  1150. status = STATUS_SUCCESS;
  1151. }
  1152. break;
  1153. }
  1154. case FSCTL_SRV_GET_QUEUE_STATISTICS:
  1155. {
  1156. PSRV_QUEUE_STATISTICS qstats;
  1157. SRV_QUEUE_STATISTICS tmpqstats;
  1158. PWORK_QUEUE queue;
  1159. LONG timeIncrement = (LONG)KeQueryTimeIncrement();
  1160. //
  1161. // Make sure the server is active.
  1162. //
  1163. if ( !SrvFspActive || SrvFspTransitioning ) {
  1164. status = STATUS_SERVER_NOT_STARTED;
  1165. goto exit_with_lock;
  1166. }
  1167. if ( IrpSp->Parameters.FileSystemControl.OutputBufferLength <
  1168. (SrvNumberOfProcessors+1) * sizeof( *qstats ) ) {
  1169. status = STATUS_BUFFER_TOO_SMALL;
  1170. goto exit_with_lock;
  1171. }
  1172. qstats = Irp->AssociatedIrp.SystemBuffer;
  1173. //
  1174. // Get the data for the normal processor queues
  1175. //
  1176. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++, qstats++ ) {
  1177. tmpqstats.QueueLength = KeReadStateQueue( &queue->Queue );
  1178. tmpqstats.ActiveThreads = queue->Threads - queue->AvailableThreads;
  1179. tmpqstats.AvailableThreads = queue->Threads;
  1180. tmpqstats.FreeWorkItems = queue->FreeWorkItems; // no lock!
  1181. tmpqstats.StolenWorkItems = queue->StolenWorkItems; // no lock!
  1182. tmpqstats.NeedWorkItem = queue->NeedWorkItem;
  1183. tmpqstats.CurrentClients = queue->CurrentClients;
  1184. tmpqstats.BytesReceived.QuadPart = queue->stats.BytesReceived;
  1185. tmpqstats.BytesSent.QuadPart = queue->stats.BytesSent;
  1186. tmpqstats.ReadOperations.QuadPart = queue->stats.ReadOperations;
  1187. tmpqstats.BytesRead.QuadPart = queue->stats.BytesRead;
  1188. tmpqstats.WriteOperations.QuadPart = queue->stats.WriteOperations;
  1189. tmpqstats.BytesWritten.QuadPart = queue->stats.BytesWritten;
  1190. tmpqstats.TotalWorkContextBlocksQueued = queue->stats.WorkItemsQueued;
  1191. tmpqstats.TotalWorkContextBlocksQueued.Count *= STATISTICS_SMB_INTERVAL;
  1192. tmpqstats.TotalWorkContextBlocksQueued.Time.QuadPart *= timeIncrement;
  1193. RtlCopyMemory( qstats, &tmpqstats, sizeof(tmpqstats) );
  1194. }
  1195. //
  1196. // Get the data for the blocking work queue
  1197. //
  1198. tmpqstats.QueueLength = KeReadStateQueue( &SrvBlockingWorkQueue.Queue );
  1199. tmpqstats.ActiveThreads = SrvBlockingWorkQueue.Threads -
  1200. SrvBlockingWorkQueue.AvailableThreads;
  1201. tmpqstats.AvailableThreads = SrvBlockingWorkQueue.Threads;
  1202. tmpqstats.FreeWorkItems = SrvBlockingWorkQueue.FreeWorkItems; // no lock!
  1203. tmpqstats.StolenWorkItems = SrvBlockingWorkQueue.StolenWorkItems; // no lock!
  1204. tmpqstats.NeedWorkItem = SrvBlockingWorkQueue.NeedWorkItem;
  1205. tmpqstats.CurrentClients = SrvBlockingWorkQueue.CurrentClients;
  1206. tmpqstats.BytesReceived.QuadPart = SrvBlockingWorkQueue.stats.BytesReceived;
  1207. tmpqstats.BytesSent.QuadPart = SrvBlockingWorkQueue.stats.BytesSent;
  1208. tmpqstats.ReadOperations.QuadPart = SrvBlockingWorkQueue.stats.ReadOperations;
  1209. tmpqstats.BytesRead.QuadPart = SrvBlockingWorkQueue.stats.BytesRead;
  1210. tmpqstats.WriteOperations.QuadPart = SrvBlockingWorkQueue.stats.WriteOperations;
  1211. tmpqstats.BytesWritten.QuadPart = SrvBlockingWorkQueue.stats.BytesWritten;
  1212. tmpqstats.TotalWorkContextBlocksQueued
  1213. = SrvBlockingWorkQueue.stats.WorkItemsQueued;
  1214. tmpqstats.TotalWorkContextBlocksQueued.Count *= STATISTICS_SMB_INTERVAL;
  1215. tmpqstats.TotalWorkContextBlocksQueued.Time.QuadPart *= timeIncrement;
  1216. RtlCopyMemory( qstats, &tmpqstats, sizeof(tmpqstats) );
  1217. Irp->IoStatus.Information = (SrvNumberOfProcessors + 1) * sizeof( *qstats );
  1218. status = STATUS_SUCCESS;
  1219. goto exit_with_lock;
  1220. break;
  1221. }
  1222. case FSCTL_SRV_GET_STATISTICS:
  1223. //
  1224. // Make sure that the server is active.
  1225. //
  1226. if ( !SrvFspActive || SrvFspTransitioning ) {
  1227. //IF_DEBUG(ERRORS) {
  1228. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1229. //}
  1230. status = STATUS_SERVER_NOT_STARTED;
  1231. goto exit_with_lock;
  1232. }
  1233. {
  1234. SRV_STATISTICS tmpStatistics;
  1235. ULONG size;
  1236. //
  1237. // Make sure that the user buffer is large enough to hold some of the
  1238. // statistics database.
  1239. //
  1240. size = MIN( IrpSp->Parameters.FileSystemControl.OutputBufferLength,
  1241. sizeof( tmpStatistics ) );
  1242. if ( size == 0 ) {
  1243. status = STATUS_BUFFER_TOO_SMALL;
  1244. goto exit_with_lock;
  1245. }
  1246. //
  1247. // Copy the statistics database to the user buffer. Store
  1248. // the statistics in a temporary buffer so we can convert
  1249. // the tick count stored to system time.
  1250. //
  1251. SrvUpdateStatisticsFromQueues( &tmpStatistics );
  1252. tmpStatistics.TotalWorkContextBlocksQueued.Time.QuadPart *=
  1253. (LONG)KeQueryTimeIncrement();
  1254. RtlCopyMemory(
  1255. Irp->AssociatedIrp.SystemBuffer,
  1256. &tmpStatistics,
  1257. size
  1258. );
  1259. Irp->IoStatus.Information = size;
  1260. }
  1261. status = STATUS_SUCCESS;
  1262. goto exit_with_lock;
  1263. #if SRVDBG_STATS || SRVDBG_STATS2
  1264. case FSCTL_SRV_GET_DEBUG_STATISTICS:
  1265. //
  1266. // Make sure that the server is active.
  1267. //
  1268. if ( !SrvFspActive || SrvFspTransitioning ) {
  1269. //IF_DEBUG(ERRORS) {
  1270. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1271. //}
  1272. status = STATUS_SERVER_NOT_STARTED;
  1273. goto exit_with_lock;
  1274. }
  1275. {
  1276. PSRV_STATISTICS_DEBUG stats;
  1277. //
  1278. // Make sure that the user buffer is large enough to hold the
  1279. // statistics database.
  1280. //
  1281. if ( IrpSp->Parameters.FileSystemControl.OutputBufferLength <
  1282. FIELD_OFFSET(SRV_STATISTICS_DEBUG,QueueStatistics) ) {
  1283. status = STATUS_BUFFER_TOO_SMALL;
  1284. goto exit_with_lock;
  1285. }
  1286. //
  1287. // Acquire the statistics lock, then copy the statistics database
  1288. // to the user buffer.
  1289. //
  1290. stats = (PSRV_STATISTICS_DEBUG)Irp->AssociatedIrp.SystemBuffer;
  1291. RtlCopyMemory(
  1292. stats,
  1293. &SrvDbgStatistics,
  1294. FIELD_OFFSET(SRV_STATISTICS_DEBUG,QueueStatistics) );
  1295. Irp->IoStatus.Information =
  1296. FIELD_OFFSET(SRV_STATISTICS_DEBUG,QueueStatistics);
  1297. if ( IrpSp->Parameters.FileSystemControl.OutputBufferLength >=
  1298. sizeof(SrvDbgStatistics) ) {
  1299. PWORK_QUEUE queue;
  1300. ULONG i, j;
  1301. i = 0;
  1302. stats->QueueStatistics[i].Depth = 0;
  1303. stats->QueueStatistics[i].Threads = 0;
  1304. #if SRVDBG_STATS2
  1305. stats->QueueStatistics[i].ItemsQueued = 0;
  1306. stats->QueueStatistics[i].MaximumDepth = 0;
  1307. #endif
  1308. for( queue = SrvWorkQueues; queue < eSrvWorkQueues; queue++ ) {
  1309. stats->QueueStatistics[i].Depth += KeReadStateQueue( &queue->Queue );
  1310. stats->QueueStatistics[i].Threads += queue->Threads;
  1311. #if SRVDBG_STATS2
  1312. stats->QueueStatistics[i].ItemsQueued += queue->ItemsQueued;
  1313. stats->QueueStatistics[i].MaximumDepth += queue->MaximumDepth + 1;
  1314. #endif
  1315. }
  1316. Irp->IoStatus.Information = sizeof(SrvDbgStatistics);
  1317. }
  1318. }
  1319. status = STATUS_SUCCESS;
  1320. goto exit_with_lock;
  1321. #endif // SRVDBG_STATS || SRVDBG_STATS2
  1322. //
  1323. // The follwing APIs must be processed in the server FSP because
  1324. // they open or close handles.
  1325. //
  1326. case FSCTL_SRV_NET_FILE_CLOSE:
  1327. case FSCTL_SRV_NET_SERVER_XPORT_ADD:
  1328. case FSCTL_SRV_NET_SERVER_XPORT_DEL:
  1329. case FSCTL_SRV_NET_SESSION_DEL:
  1330. case FSCTL_SRV_NET_SHARE_ADD:
  1331. case FSCTL_SRV_NET_SHARE_DEL:
  1332. {
  1333. PSERVER_REQUEST_PACKET srp;
  1334. PVOID buffer1;
  1335. PVOID buffer2;
  1336. PVOID systemBuffer;
  1337. ULONG buffer1Length;
  1338. ULONG buffer2Length;
  1339. ULONG systemBufferLength;
  1340. //
  1341. // Get the server request packet pointer.
  1342. //
  1343. srp = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
  1344. //
  1345. // If the server is not running, or if it is in the process
  1346. // of shutting down, reject this request.
  1347. //
  1348. if ( !SrvFspActive || SrvFspTransitioning ) {
  1349. //IF_DEBUG(ERRORS) {
  1350. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1351. //}
  1352. srp->ErrorCode = NERR_ServerNotStarted;
  1353. status = STATUS_SUCCESS;
  1354. goto exit_with_lock;
  1355. }
  1356. //
  1357. // Determine the input buffer lengths, and make sure that the
  1358. // first buffer is large enough to be an SRP.
  1359. //
  1360. buffer1Length = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  1361. buffer2Length = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
  1362. if ( buffer1Length < sizeof(SERVER_REQUEST_PACKET) ) {
  1363. status = STATUS_INVALID_PARAMETER;
  1364. goto exit_with_lock;
  1365. }
  1366. //
  1367. // Make the first buffer size is properly aligned so that the second
  1368. // buffer will be aligned as well.
  1369. //
  1370. buffer1Length = ALIGN_UP( buffer1Length, PVOID );
  1371. //
  1372. // Allocate a single buffer that will hold both input buffers.
  1373. // Note that the SRP part of the first buffer is copied back
  1374. // to the user as an output buffer.
  1375. //
  1376. systemBufferLength = buffer1Length + buffer2Length;
  1377. if( buffer1Length > SrvMaxFsctlBufferSize ||
  1378. buffer2Length > SrvMaxFsctlBufferSize ) {
  1379. status = STATUS_INVALID_PARAMETER;
  1380. goto exit_with_lock;
  1381. }
  1382. systemBuffer = ExAllocatePoolWithTagPriority( PagedPool, systemBufferLength, BlockTypeMisc, LowPoolPriority );
  1383. if ( systemBuffer == NULL ) {
  1384. status = STATUS_INSUFF_SERVER_RESOURCES;
  1385. goto exit_with_lock;
  1386. }
  1387. buffer1 = systemBuffer;
  1388. buffer2 = (PCHAR)systemBuffer + buffer1Length;
  1389. //
  1390. // Copy the information into the buffers.
  1391. //
  1392. RtlCopyMemory(
  1393. buffer1,
  1394. srp,
  1395. IrpSp->Parameters.FileSystemControl.InputBufferLength
  1396. );
  1397. if ( buffer2Length > 0 ) {
  1398. RtlCopyMemory( buffer2, Irp->UserBuffer, buffer2Length );
  1399. }
  1400. //
  1401. // If a name was specified in the SRP, the buffer field will
  1402. // contain an offset rather than a pointer. Convert the offset
  1403. // to a pointer and verify that that it is a legal pointer.
  1404. //
  1405. srp = buffer1;
  1406. OFFSET_TO_POINTER( srp->Name1.Buffer, srp );
  1407. if ( !POINTER_IS_VALID( srp->Name1.Buffer, srp, buffer1Length ) ) {
  1408. status = STATUS_ACCESS_VIOLATION;
  1409. ExFreePool( buffer1 );
  1410. goto exit_with_lock;
  1411. }
  1412. OFFSET_TO_POINTER( srp->Name2.Buffer, srp );
  1413. if ( !POINTER_IS_VALID( srp->Name2.Buffer, srp, buffer1Length ) ) {
  1414. status = STATUS_ACCESS_VIOLATION;
  1415. ExFreePool( buffer1 );
  1416. goto exit_with_lock;
  1417. }
  1418. //
  1419. // Set up pointers in the IRP. The system buffer points to the
  1420. // buffer we just allocated to contain the input buffers. User
  1421. // buffer points to the SRP from the server service. This
  1422. // allows the SRP to be used as an output buffer-- the number of
  1423. // bytes specified by the Information field of the IO status
  1424. // block are copied from the system buffer to the user buffer at
  1425. // IO completion.
  1426. //
  1427. Irp->AssociatedIrp.SystemBuffer = systemBuffer;
  1428. Irp->UserBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
  1429. //
  1430. // Set up other fields in the IRP so that the SRP is copied from
  1431. // the system buffer to the user buffer, and the system buffer
  1432. // is deallocated by IO completion.
  1433. //
  1434. Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER |
  1435. IRP_INPUT_OPERATION;
  1436. Irp->IoStatus.Information = sizeof(SERVER_REQUEST_PACKET);
  1437. break;
  1438. }
  1439. //
  1440. // The following APIs should be processed in the server FSP because
  1441. // they reference and dereference structures, which could lead to
  1442. // handles being closed. However, it was too hard to change this
  1443. // (because of the need to return a separate SRP and data buffer) at
  1444. // the time this was realized (just before Product 1 shipment), so
  1445. // they are processed in the FSD, and all calls to NtClose attach to
  1446. // the server process first if necessary.
  1447. //
  1448. case FSCTL_SRV_NET_CONNECTION_ENUM:
  1449. case FSCTL_SRV_NET_FILE_ENUM:
  1450. case FSCTL_SRV_NET_SERVER_DISK_ENUM:
  1451. case FSCTL_SRV_NET_SERVER_XPORT_ENUM:
  1452. case FSCTL_SRV_NET_SESSION_ENUM:
  1453. case FSCTL_SRV_NET_SHARE_ENUM:
  1454. //
  1455. // These APIs are processed here in the server FSD.
  1456. //
  1457. case FSCTL_SRV_NET_SERVER_SET_INFO:
  1458. case FSCTL_SRV_NET_SHARE_SET_INFO:
  1459. case FSCTL_SRV_NET_STATISTICS_GET:
  1460. {
  1461. PSERVER_REQUEST_PACKET srp;
  1462. ULONG buffer1Length;
  1463. //
  1464. // Get the server request packet pointer.
  1465. //
  1466. srp = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
  1467. buffer1Length = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  1468. //
  1469. // If the server is not running, or if it is in the process
  1470. // of shutting down, reject this request.
  1471. //
  1472. if ( !SrvFspActive || SrvFspTransitioning ) {
  1473. //IF_DEBUG(ERRORS) {
  1474. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1475. //}
  1476. srp->ErrorCode = NERR_ServerNotStarted;
  1477. status = STATUS_SUCCESS;
  1478. goto exit_with_lock;
  1479. }
  1480. //
  1481. // Increment the count of API requests in the server FSD.
  1482. //
  1483. SrvApiRequestCount++;
  1484. //
  1485. // Make sure that the buffer was large enough to be an SRP.
  1486. //
  1487. if ( buffer1Length < sizeof(SERVER_REQUEST_PACKET) ) {
  1488. status = STATUS_INVALID_PARAMETER;
  1489. goto exit_with_lock;
  1490. }
  1491. //
  1492. // If a name was specified in the SRP, the buffer field will
  1493. // contain an offset rather than a pointer. Convert the offset
  1494. // to a pointer and verify that that it is a legal pointer.
  1495. //
  1496. OFFSET_TO_POINTER( srp->Name1.Buffer, srp );
  1497. if ( !POINTER_IS_VALID( srp->Name1.Buffer, srp, buffer1Length ) ) {
  1498. status = STATUS_ACCESS_VIOLATION;
  1499. goto exit_with_lock;
  1500. }
  1501. OFFSET_TO_POINTER( srp->Name2.Buffer, srp );
  1502. if ( !POINTER_IS_VALID( srp->Name2.Buffer, srp, buffer1Length ) ) {
  1503. status = STATUS_ACCESS_VIOLATION;
  1504. goto exit_with_lock;
  1505. }
  1506. //
  1507. // We don't need the configuration lock any more.
  1508. //
  1509. RELEASE_LOCK( &SrvConfigurationLock );
  1510. //
  1511. // Dispatch the API request to the appripriate API processing
  1512. // routine. All these API requests are handled in the FSD.
  1513. //
  1514. status = SrvApiDispatchTable[ SRV_API_INDEX(code) ](
  1515. srp,
  1516. Irp->UserBuffer,
  1517. IrpSp->Parameters.FileSystemControl.OutputBufferLength
  1518. );
  1519. //
  1520. // Decrement the count of outstanding API requests in the
  1521. // server. Hold the configuration lock while doing this, as it
  1522. // protects the API count variable.
  1523. //
  1524. ACQUIRE_LOCK( &SrvConfigurationLock );
  1525. SrvApiRequestCount--;
  1526. //
  1527. // Check to see whether the server is transitioning from started
  1528. // to not started. If so, and if this is the last API request
  1529. // to be completed, then set the API completion event which the
  1530. // shutdown code is waiting on.
  1531. //
  1532. // Since we checked SrvFspTransitioning at the start of the
  1533. // request, we know that the shutdown came after we started
  1534. // processing the API. If SrvApiRequestCount is 0, then there
  1535. // are no other threads in the FSD processing API requests.
  1536. // Therefore, it is safe for the shutdown code to proceed with
  1537. // the knowledge that no other thread in the server is
  1538. // operating.
  1539. //
  1540. if ( SrvFspTransitioning && SrvApiRequestCount == 0 ) {
  1541. KeSetEvent( &SrvApiCompletionEvent, 0, FALSE );
  1542. }
  1543. goto exit_with_lock;
  1544. }
  1545. case FSCTL_SRV_START_SMBTRACE:
  1546. if ( SmbTraceActive[SMBTRACE_SERVER] ) {
  1547. status = STATUS_SHARING_VIOLATION;
  1548. goto exit_with_lock;
  1549. }
  1550. if ( !SrvFspActive || SrvFspTransitioning ) {
  1551. status = STATUS_SERVER_NOT_STARTED;
  1552. goto exit_with_lock;
  1553. }
  1554. break; // FSP continues the processing.
  1555. case FSCTL_SRV_END_SMBTRACE:
  1556. //
  1557. // If the server is not running, or if it is in the process
  1558. // of shutting down, reject this request.
  1559. //
  1560. if ( !SrvFspActive || SrvFspTransitioning ) {
  1561. status = STATUS_SERVER_NOT_STARTED;
  1562. goto exit_with_lock;
  1563. }
  1564. //
  1565. // Attempt to stop SmbTrace. It will likely return
  1566. // STATUS_PENDING, indicating that it is in the process
  1567. // of shutting down. STATUS_PENDING is a poor value
  1568. // to return (according to an assertion in io\iosubs.c)
  1569. // so we convert it to success. Better would be for
  1570. // SmbTraceStop to wait until it has successfully stopped.
  1571. //
  1572. status = SmbTraceStop( NULL, SMBTRACE_SERVER );
  1573. //
  1574. // Complete the request with success.
  1575. //
  1576. status = STATUS_SUCCESS;
  1577. goto exit_with_lock;
  1578. case FSCTL_SRV_PAUSE:
  1579. //
  1580. // If the server is not running, or if it is in the process
  1581. // of shutting down, reject this request.
  1582. //
  1583. if ( !SrvFspActive || SrvFspTransitioning ) {
  1584. //IF_DEBUG(ERRORS) {
  1585. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1586. //}
  1587. status = STATUS_SERVER_NOT_STARTED;
  1588. goto exit_with_lock;
  1589. }
  1590. SrvPaused = TRUE;
  1591. status = STATUS_SUCCESS;
  1592. goto exit_with_lock;
  1593. case FSCTL_SRV_CONTINUE:
  1594. //
  1595. // If the server is not running, or if it is in the process
  1596. // of shutting down, reject this request.
  1597. //
  1598. if ( !SrvFspActive || SrvFspTransitioning ) {
  1599. //IF_DEBUG(ERRORS) {
  1600. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1601. //}
  1602. status = STATUS_SERVER_NOT_STARTED;
  1603. goto exit_with_lock;
  1604. }
  1605. SrvPaused = FALSE;
  1606. status = STATUS_SUCCESS;
  1607. goto exit_with_lock;
  1608. case FSCTL_SRV_GET_CHALLENGE:
  1609. {
  1610. PLIST_ENTRY sessionEntry;
  1611. PLUID inputLuid;
  1612. PSESSION session;
  1613. //
  1614. // If the server is not running, or if it is in the process
  1615. // of shutting down, reject this request.
  1616. //
  1617. if ( !SrvFspActive || SrvFspTransitioning ) {
  1618. //IF_DEBUG(ERRORS) {
  1619. // SrvPrint0( "LAN Manager server FSP not started.\n" );
  1620. //}
  1621. status = STATUS_SERVER_NOT_STARTED;
  1622. goto exit_with_lock;
  1623. }
  1624. if ( IrpSp->Parameters.FileSystemControl.InputBufferLength <
  1625. sizeof(LUID) ||
  1626. IrpSp->Parameters.FileSystemControl.OutputBufferLength <
  1627. sizeof(session->NtUserSessionKey) ) {
  1628. status = STATUS_BUFFER_TOO_SMALL;
  1629. goto exit_with_lock;
  1630. }
  1631. RELEASE_LOCK( &SrvConfigurationLock );
  1632. inputLuid = (PLUID)Irp->AssociatedIrp.SystemBuffer;
  1633. //
  1634. // Acquire the lock that protects the session list and walk the
  1635. // list looking for a user token that matches the one specified
  1636. // in the input buffer.
  1637. //
  1638. ACQUIRE_LOCK( SrvSessionList.Lock );
  1639. for ( sessionEntry = SrvSessionList.ListHead.Flink;
  1640. sessionEntry != &SrvSessionList.ListHead;
  1641. sessionEntry = sessionEntry->Flink ) {
  1642. session = CONTAINING_RECORD(
  1643. sessionEntry,
  1644. SESSION,
  1645. GlobalSessionListEntry
  1646. );
  1647. if ( RtlEqualLuid( inputLuid, &session->LogonId ) ) {
  1648. //
  1649. // We found a match. Write the NT user session key into
  1650. // the output buffer.
  1651. //
  1652. RtlCopyMemory(
  1653. Irp->AssociatedIrp.SystemBuffer,
  1654. session->NtUserSessionKey,
  1655. sizeof(session->NtUserSessionKey)
  1656. );
  1657. RELEASE_LOCK( SrvSessionList.Lock );
  1658. Irp->IoStatus.Information = sizeof(session->NtUserSessionKey);
  1659. status = STATUS_SUCCESS;
  1660. goto exit_without_lock;
  1661. }
  1662. }
  1663. RELEASE_LOCK( SrvSessionList.Lock );
  1664. //
  1665. // There was no matching token in our session list. Fail the
  1666. // request.
  1667. //
  1668. status = STATUS_NO_TOKEN;
  1669. goto exit_without_lock;
  1670. }
  1671. case FSCTL_SRV_INTERNAL_TEST_REAUTH:
  1672. {
  1673. PSRV_REAUTH_TEST pReauthData;
  1674. ULONG BufferLength;
  1675. pReauthData = (PSRV_REAUTH_TEST)Irp->AssociatedIrp.SystemBuffer;
  1676. BufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
  1677. // Make sure the buffer size is good
  1678. if( BufferLength < sizeof(SRV_REAUTH_TEST) )
  1679. {
  1680. status = STATUS_INVALID_PARAMETER;
  1681. goto exit_with_lock;
  1682. }
  1683. // Pull out the parameters
  1684. SessionInvalidateCommand = pReauthData->InvalidateCommand;
  1685. SessionInvalidateMod = pReauthData->InvalidateModulo;
  1686. status = STATUS_SUCCESS;
  1687. goto exit_with_lock;
  1688. }
  1689. default:
  1690. INTERNAL_ERROR(
  1691. ERROR_LEVEL_EXPECTED,
  1692. "SrvFsdDispatchFsControl: Invalid I/O control "
  1693. "code received: %lx\n",
  1694. IrpSp->Parameters.FileSystemControl.FsControlCode,
  1695. NULL
  1696. );
  1697. status = STATUS_INVALID_PARAMETER;
  1698. goto exit_with_lock;
  1699. }
  1700. pWorkItem = IoAllocateWorkItem( SrvDeviceObject );
  1701. if( !pWorkItem )
  1702. {
  1703. status = STATUS_INSUFFICIENT_RESOURCES;
  1704. goto exit_with_lock;
  1705. }
  1706. //
  1707. // Queue the request to the FSP for processing.
  1708. //
  1709. // *** Note that the request must be queued while the configuration
  1710. // lock is held in order to prevent an add/delete/etc request
  1711. // from checking the server state before a shutdown request, but
  1712. // being queued after that request.
  1713. //
  1714. IoMarkIrpPending( Irp );
  1715. QueueConfigurationIrp( Irp, pWorkItem );
  1716. RELEASE_LOCK( &SrvConfigurationLock );
  1717. FsRtlExitFileSystem();
  1718. return STATUS_PENDING;
  1719. exit_with_lock:
  1720. RELEASE_LOCK( &SrvConfigurationLock );
  1721. exit_without_lock:
  1722. FsRtlExitFileSystem();
  1723. Irp->IoStatus.Status = status;
  1724. IoCompleteRequest( Irp, 2 );
  1725. return status;
  1726. } // SrvFsdDispatchFsControl
  1727. VOID
  1728. QueueConfigurationIrp (
  1729. IN PIRP Irp,
  1730. IN PIO_WORKITEM pWorkItem
  1731. )
  1732. {
  1733. PAGED_CODE( );
  1734. InterlockedIncrement( (PLONG)&SrvConfigurationIrpsInProgress );
  1735. SrvInsertTailList(
  1736. &SrvConfigurationWorkQueue,
  1737. &Irp->Tail.Overlay.ListEntry
  1738. );
  1739. IoQueueWorkItem( pWorkItem, SrvConfigurationThread, DelayedWorkQueue, (PVOID)pWorkItem );
  1740. } // QueueConfigurationIrp