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.

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