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.

3475 lines
88 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. io.c
  5. Abstract:
  6. !!! Need to handle inability to allocate IRP.
  7. !!! Need to modify to accept file object pointer, not file handle,
  8. to avoid unnecessary translations.
  9. Author:
  10. Chuck Lenzmeier (chuckl) 28-Oct-1989
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "io.tmh"
  15. #pragma hdrstop
  16. #define BugCheckFileId SRV_FILE_IO
  17. //
  18. // Forward declarations
  19. //
  20. PIRP
  21. BuildCoreOfSyncIoRequest (
  22. IN HANDLE FileHandle,
  23. IN PFILE_OBJECT FileObject OPTIONAL,
  24. IN PKEVENT Event,
  25. IN PIO_STATUS_BLOCK IoStatusBlock,
  26. IN OUT PDEVICE_OBJECT *DeviceObject
  27. );
  28. NTSTATUS
  29. StartIoAndWait (
  30. IN PIRP Irp,
  31. IN PDEVICE_OBJECT DeviceObject,
  32. IN PKEVENT Event,
  33. IN PIO_STATUS_BLOCK IoStatusBlock
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text( PAGE, BuildCoreOfSyncIoRequest )
  37. #pragma alloc_text( PAGE, StartIoAndWait )
  38. #pragma alloc_text( PAGE, SrvBuildFlushRequest )
  39. #pragma alloc_text( PAGE, SrvBuildLockRequest )
  40. #pragma alloc_text( PAGE, SrvBuildMailslotWriteRequest )
  41. #pragma alloc_text( PAGE, SrvBuildReadOrWriteRequest )
  42. #pragma alloc_text( PAGE, SrvBuildNotifyChangeRequest )
  43. #pragma alloc_text( PAGE, SrvIssueAssociateRequest )
  44. #pragma alloc_text( PAGE, SrvIssueDisconnectRequest )
  45. #pragma alloc_text( PAGE, SrvIssueTdiAction )
  46. #pragma alloc_text( PAGE, SrvIssueTdiQuery )
  47. #pragma alloc_text( PAGE, SrvIssueQueryDirectoryRequest )
  48. #pragma alloc_text( PAGE, SrvIssueQueryEaRequest )
  49. #pragma alloc_text( PAGE, SrvIssueSendDatagramRequest )
  50. #pragma alloc_text( PAGE, SrvIssueSetClientProcessRequest )
  51. #pragma alloc_text( PAGE, SrvIssueSetEaRequest )
  52. #pragma alloc_text( PAGE, SrvIssueSetEventHandlerRequest )
  53. #pragma alloc_text( PAGE, SrvIssueUnlockRequest )
  54. #pragma alloc_text( PAGE, SrvIssueUnlockSingleRequest )
  55. #pragma alloc_text( PAGE, SrvIssueWaitForOplockBreak )
  56. #pragma alloc_text( PAGE, SrvQuerySendEntryPoint )
  57. #ifdef INCLUDE_SMB_IFMODIFIED
  58. #pragma alloc_text( PAGE, SrvIssueQueryUsnInfoRequest )
  59. #endif
  60. #endif
  61. #if 0
  62. NOT PAGEABLE -- SrvBuildIoControlRequest
  63. #endif
  64. STATIC
  65. PIRP
  66. BuildCoreOfSyncIoRequest (
  67. IN HANDLE FileHandle,
  68. IN PFILE_OBJECT FileObject OPTIONAL,
  69. IN PKEVENT Event,
  70. IN PIO_STATUS_BLOCK IoStatusBlock,
  71. IN OUT PDEVICE_OBJECT *DeviceObject
  72. )
  73. /*++
  74. Routine Description:
  75. This (local) function builds the request-independent portion of
  76. an I/O request packet for an I/O operation that will be performed
  77. synchronously. It initializes a kernel event object, references
  78. the target file object, and allocates and initializes an IRP.
  79. Arguments:
  80. FileHandle - Supplies a handle to the target file object.
  81. FileObject - Optionall supplies a pointer to the target file object.
  82. Event - Supplies a pointer to a kernel event object. This routine
  83. initializes the event.
  84. IoStatusBlock - Supplies a pointer to an I/O status block. This
  85. pointer is placed in the IRP.
  86. DeviceObject - Supplies or receives the address of the device object
  87. associated with the target file object. This address is
  88. subsequently used by StartIoAndWait. *DeviceObject must be
  89. valid or NULL on entry if FileObject != NULL.
  90. Return Value:
  91. PIRP - Returns a pointer to the constructed IRP.
  92. --*/
  93. {
  94. NTSTATUS status;
  95. PIRP irp;
  96. PIO_STACK_LOCATION irpSp;
  97. PAGED_CODE();
  98. //
  99. // Initialize the kernel event that will signal I/O completion.
  100. //
  101. KeInitializeEvent( Event, SynchronizationEvent, FALSE );
  102. //
  103. // Get the file object corresponding to the directory's handle.
  104. // Referencing the file object every time is necessary because the
  105. // IO completion routine dereferneces it.
  106. //
  107. if ( ARGUMENT_PRESENT(FileObject) ) {
  108. ObReferenceObject(FileObject);
  109. } else {
  110. *DeviceObject = NULL;
  111. status = ObReferenceObjectByHandle(
  112. FileHandle,
  113. 0L, // DesiredAccess
  114. NULL, // ObjectType
  115. KernelMode,
  116. (PVOID *)&FileObject,
  117. NULL
  118. );
  119. if ( !NT_SUCCESS(status) ) {
  120. return NULL;
  121. }
  122. }
  123. //
  124. // Set the file object event to a non-signaled state.
  125. //
  126. KeClearEvent( &FileObject->Event );
  127. //
  128. // Attempt to allocate and initialize the I/O Request Packet (IRP)
  129. // for this operation.
  130. //
  131. if ( *DeviceObject == NULL ) {
  132. *DeviceObject = IoGetRelatedDeviceObject( FileObject );
  133. }
  134. irp = IoAllocateIrp( (*DeviceObject)->StackSize, TRUE );
  135. if ( irp == NULL ) {
  136. ULONG packetSize = sizeof(IRP) +
  137. ((*DeviceObject)->StackSize * sizeof(IO_STACK_LOCATION));
  138. INTERNAL_ERROR(
  139. ERROR_LEVEL_EXPECTED,
  140. "BuildCoreOfSyncIoRequest: Failed to allocate IRP",
  141. NULL,
  142. NULL
  143. );
  144. SrvLogError(
  145. SrvDeviceObject,
  146. EVENT_SRV_NO_NONPAGED_POOL,
  147. STATUS_INSUFFICIENT_RESOURCES,
  148. &packetSize,
  149. sizeof(ULONG),
  150. NULL,
  151. 0
  152. );
  153. return NULL;
  154. }
  155. //
  156. // Fill in the service independent parameters in the IRP.
  157. //
  158. irp->MdlAddress = NULL;
  159. irp->Flags = (LONG)IRP_SYNCHRONOUS_API;
  160. irp->RequestorMode = KernelMode;
  161. irp->PendingReturned = FALSE;
  162. irp->UserIosb = IoStatusBlock;
  163. irp->UserEvent = Event;
  164. irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  165. irp->AssociatedIrp.SystemBuffer = NULL;
  166. irp->UserBuffer = NULL;
  167. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  168. irp->Tail.Overlay.OriginalFileObject = FileObject;
  169. irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  170. irp->IoStatus.Status = 0;
  171. irp->IoStatus.Information = 0;
  172. //
  173. // Put the file object pointer in the stack location.
  174. //
  175. irpSp = IoGetNextIrpStackLocation( irp );
  176. irpSp->FileObject = FileObject;
  177. irpSp->DeviceObject = *DeviceObject;
  178. return irp;
  179. } // BuildCoreOfSyncIoRequest
  180. STATIC
  181. NTSTATUS
  182. StartIoAndWait (
  183. IN PIRP Irp,
  184. IN PDEVICE_OBJECT DeviceObject,
  185. IN PKEVENT Event,
  186. IN PIO_STATUS_BLOCK IoStatusBlock
  187. )
  188. /*++
  189. Routine Description:
  190. This (local) function passes a fully built I/O request packet to the
  191. target driver, then waits for the driver to complete the request.
  192. Arguments:
  193. Irp - Supplies a pointer to the I/O request packet.
  194. DeviceObject - Supplies a pointer to the target device object.
  195. Event - Supplies a pointer to a kernel event object. This routine
  196. waits for the I/O to complete using this event.
  197. IoStatusBlock - Supplies a pointer to an I/O status block. The
  198. Status field of this structure becomes the return status of
  199. this function.
  200. Return Value:
  201. NTSTATUS - Either an error status returned by the driver from
  202. IoCallDriver, indicating that the driver rejected the request,
  203. or the I/O status placed in the I/O status block by the driver
  204. at I/O completion.
  205. --*/
  206. {
  207. NTSTATUS status;
  208. KIRQL oldIrql;
  209. PAGED_CODE();
  210. //
  211. // Queue the IRP to the thread and pass it to the driver.
  212. //
  213. IoQueueThreadIrp( Irp );
  214. status = IoCallDriver( DeviceObject, Irp );
  215. //
  216. // If necessary, wait for the I/O to complete.
  217. //
  218. if ( status == STATUS_PENDING ) {
  219. KeWaitForSingleObject(
  220. Event,
  221. UserRequest,
  222. KernelMode, // don't let stack be paged -- event is on stack!
  223. FALSE,
  224. NULL
  225. );
  226. }
  227. //
  228. // If the request was successfully queued, get the final I/O status.
  229. //
  230. if ( NT_SUCCESS(status) ) {
  231. status = IoStatusBlock->Status;
  232. }
  233. return status;
  234. } // StartIoAndWait
  235. PIRP
  236. SrvBuildIoControlRequest (
  237. IN OUT PIRP Irp OPTIONAL,
  238. IN PFILE_OBJECT FileObject OPTIONAL,
  239. IN PVOID Context,
  240. IN UCHAR MajorFunction,
  241. IN ULONG IoControlCode,
  242. IN PVOID MainBuffer,
  243. IN ULONG InputBufferLength,
  244. IN PVOID AuxiliaryBuffer OPTIONAL,
  245. IN ULONG OutputBufferLength,
  246. IN OUT PMDL Mdl OPTIONAL,
  247. IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL
  248. )
  249. /*++
  250. Routine Description:
  251. This function builds an I/O request packet for a device or
  252. file system I/O control request.
  253. *** This routine sure takes a lot of arguments!
  254. Arguments:
  255. Irp - Supplies a pointer to an IRP. If NULL, this routine allocates
  256. an IRP and returns its address. Otherwise, it supplies the
  257. address of an IRP allocated by the caller.
  258. FileObject - Supplies a pointer the file object to which this
  259. request is directed. This pointer is copied into the IRP, so
  260. that the called driver can find its file-based context. NOTE
  261. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  262. that the file object is not deleted while the I/O operation is
  263. in progress. The server accomplishes this by incrementing a
  264. reference count in a local block to account for the I/O; the
  265. local block in turn references the file object.
  266. If this parameter is omitted, it is the responsiblity of the
  267. calling program to load the file object address before starting
  268. the I/O.
  269. Context - Supplies a PVOID value that is passed to the completion
  270. routine.
  271. MajorFunction - The major function that we are calling. Currently
  272. this most be one of IRP_MJ_FILE_SYSTEM_CONTROL or
  273. IRP_MJ_DEVICE_IO_CONTROL.
  274. IoControlCode - Supplies the control code for the operation.
  275. MainBuffer - Supplies the address of the main buffer. This must
  276. be a system virtual address, and the buffer must be locked in
  277. memory. If ControlCode specifies a method 0 request, the actual
  278. length of the buffer must be the greater of InputBufferLength
  279. and OutputBufferLength.
  280. InputBufferLength - Supplies the length of the input buffer.
  281. AuxiliaryBuffer - Supplies the address of the auxiliary buffer. If the
  282. control code method is 0, this is a buffered I/O buffer, but the
  283. data returned by the called driver in the system buffer is not
  284. automatically copied into the auxiliary buffer. Instead, the
  285. auxiliary data ends up in MainBuffer. If the caller wishes the
  286. data to be in AuxiliaryBuffer, it must copy the data at some point
  287. after the completion routine runs.
  288. If the control code method is 1 or 2, this parameter is ignored;
  289. instead, the Mdl parameter is used to obtain the starting
  290. virtual address of the buffer.
  291. OutputBufferLength - Supplies the length of the output buffer. Note
  292. that this parameter must be specified even when the Mdl
  293. parameter is specified.
  294. Mdl - If the control code method is 1 or 2, indicating direct I/O on
  295. the "output" buffer, this parameter is used to supply a pointer
  296. to an MDL describing a buffer. Mdl must not be NULL, and the
  297. AuxiliaryBuffer parameter is ignored. The buffer must reside in
  298. the system virtual address space (for the benefit of the
  299. transport provider). If the buffer is not already locked, this
  300. routine locks it. It is the calling program's responsibility to
  301. unlock the buffer and (potentially) deallocate the MDL after the
  302. I/O is complete.
  303. This parameter is ignored if the control method is not 1 or 2.
  304. CompletionRoutine - An optional IO completion routine. If none
  305. is specified, SrvFsdIoCompletionRoutine is used.
  306. Return Value:
  307. PIRP - Returns a pointer to the constructed IRP. If the Irp
  308. parameter was not NULL on input, the function return value will
  309. be the same value (so it is safe to discard the return value in
  310. this case). It is the responsibility of the calling program to
  311. deallocate the IRP after the I/O request is complete.
  312. --*/
  313. {
  314. CLONG method;
  315. PDEVICE_OBJECT deviceObject;
  316. PIO_STACK_LOCATION irpSp;
  317. ASSERT( MajorFunction == IRP_MJ_DEVICE_CONTROL ||
  318. MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL ||
  319. MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL );
  320. //
  321. // Get the method with which the buffers are being passed.
  322. //
  323. if ((MajorFunction == IRP_MJ_DEVICE_CONTROL) ||
  324. (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)) {
  325. method = IoControlCode & 3;
  326. } else {
  327. method = 4;
  328. }
  329. if ( ARGUMENT_PRESENT(Irp) ) {
  330. if( Irp->AssociatedIrp.SystemBuffer &&
  331. (Irp->Flags & IRP_DEALLOCATE_BUFFER) ) {
  332. ExFreePool( Irp->AssociatedIrp.SystemBuffer );
  333. Irp->Flags &= ~IRP_DEALLOCATE_BUFFER;
  334. }
  335. }
  336. //
  337. // If the FileObject parameter was specified, obtain the address of
  338. // the device object and allocate the IRP based on the stack size
  339. // for that device. Otherwise, allocate the IRP based on the
  340. // server's receive IRP stack size.
  341. //
  342. if ( ARGUMENT_PRESENT(FileObject) ) {
  343. //
  344. // Allocate an IRP, if necessary. The stack size is one higher
  345. // than that of the target device, to allow for the caller's
  346. // completion routine.
  347. //
  348. deviceObject = IoGetRelatedDeviceObject( FileObject );
  349. if ( ARGUMENT_PRESENT(Irp) ) {
  350. ASSERT( Irp->StackCount >= deviceObject->StackSize );
  351. } else {
  352. //
  353. // Get the address of the target device object.
  354. //
  355. Irp = IoAllocateIrp( SrvReceiveIrpStackSize, FALSE );
  356. if ( Irp == NULL ) {
  357. //
  358. // Unable to allocate an IRP. Inform the caller.
  359. //
  360. return NULL;
  361. }
  362. }
  363. } else {
  364. deviceObject = NULL;
  365. if ( !ARGUMENT_PRESENT(Irp) ) {
  366. Irp = IoAllocateIrp( SrvReceiveIrpStackSize, FALSE );
  367. if ( Irp == NULL ) {
  368. return NULL;
  369. }
  370. }
  371. }
  372. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  373. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  374. DEBUG Irp->RequestorMode = KernelMode;
  375. Irp->IoStatus.Status = 0;
  376. Irp->IoStatus.Information = 0;
  377. //
  378. // Get a pointer to the next stack location. This one is used to
  379. // hold the parameters for the device I/O control request.
  380. //
  381. irpSp = IoGetNextIrpStackLocation( Irp );
  382. //
  383. // Set up the completion routine.
  384. //
  385. IoSetCompletionRoutine(
  386. Irp,
  387. (ARGUMENT_PRESENT( CompletionRoutine ) ?
  388. CompletionRoutine : SrvFsdIoCompletionRoutine),
  389. Context,
  390. TRUE,
  391. TRUE,
  392. TRUE
  393. );
  394. irpSp->MajorFunction = MajorFunction;
  395. irpSp->MinorFunction = 0;
  396. if ( MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL ) {
  397. irpSp->MinorFunction = (UCHAR)IoControlCode;
  398. }
  399. irpSp->FileObject = FileObject;
  400. irpSp->DeviceObject = deviceObject;
  401. //
  402. // Copy the caller's parameters to the service-specific portion of the
  403. // IRP for those parameters that are the same for all three methods.
  404. //
  405. if ( MajorFunction == IRP_MJ_DEVICE_CONTROL ) {
  406. irpSp->Parameters.DeviceIoControl.OutputBufferLength =
  407. OutputBufferLength;
  408. irpSp->Parameters.DeviceIoControl.InputBufferLength =
  409. InputBufferLength;
  410. irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
  411. } else if ( MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL ) {
  412. if ( IoControlCode == TDI_RECEIVE ) {
  413. PTDI_REQUEST_KERNEL_RECEIVE parameters =
  414. (PTDI_REQUEST_KERNEL_RECEIVE)&irpSp->Parameters;
  415. parameters->ReceiveLength = OutputBufferLength;
  416. parameters->ReceiveFlags = 0;
  417. method = 1;
  418. } else if ( IoControlCode == TDI_ACCEPT ) {
  419. PTDI_REQUEST_KERNEL_ACCEPT parameters =
  420. (PTDI_REQUEST_KERNEL_ACCEPT)&irpSp->Parameters;
  421. parameters->RequestConnectionInformation = NULL;
  422. parameters->ReturnConnectionInformation = NULL;
  423. method = 0;
  424. } else {
  425. ASSERTMSG( "Invalid TDI request type", 0 );
  426. }
  427. } else {
  428. irpSp->Parameters.FileSystemControl.OutputBufferLength =
  429. OutputBufferLength;
  430. irpSp->Parameters.FileSystemControl.InputBufferLength =
  431. InputBufferLength;
  432. irpSp->Parameters.FileSystemControl.FsControlCode = IoControlCode;
  433. }
  434. //
  435. // Based on the method by which the buffers are being passed,
  436. // describe a system buffer and optionally build an MDL.
  437. //
  438. switch ( method ) {
  439. case 0:
  440. //
  441. // For this case, InputBuffer must be large enough to contain
  442. // both the input and the output buffers.
  443. //
  444. Irp->MdlAddress = NULL;
  445. Irp->AssociatedIrp.SystemBuffer = MainBuffer;
  446. Irp->UserBuffer = AuxiliaryBuffer;
  447. //
  448. // !!! Does Irp->Flags need to be set? Isn't this only looked
  449. // at by I/O competion, which we bypass?
  450. //
  451. Irp->Flags = (ULONG)IRP_BUFFERED_IO;
  452. if ( ARGUMENT_PRESENT(AuxiliaryBuffer) ) {
  453. Irp->Flags |= IRP_INPUT_OPERATION;
  454. }
  455. break;
  456. case 1:
  457. case 2:
  458. //
  459. // For these two cases, InputBuffer is the buffered I/O "system
  460. // buffer". Build an MDL for either read or write access,
  461. // depending on the method, for the output buffer.
  462. //
  463. Irp->MdlAddress = Mdl;
  464. Irp->AssociatedIrp.SystemBuffer = MainBuffer;
  465. // !!! Ditto above about setting Flags.
  466. Irp->Flags = (ULONG)IRP_BUFFERED_IO;
  467. break;
  468. case 3:
  469. //
  470. // For this case, do nothing. Everything is up to the driver.
  471. // Simply give the driver a copy of the caller's parameters and
  472. // let the driver do everything itself.
  473. //
  474. Irp->MdlAddress = NULL;
  475. Irp->AssociatedIrp.SystemBuffer = NULL;
  476. Irp->UserBuffer = AuxiliaryBuffer;
  477. Irp->Flags = 0;
  478. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = MainBuffer;
  479. break;
  480. case 4:
  481. //
  482. // This is the case for file system io request. Both MainBuffer
  483. // and AuxiliaryBuffer are locked system buffers.
  484. //
  485. Irp->MdlAddress = NULL;
  486. Irp->Flags = 0;
  487. Irp->AssociatedIrp.SystemBuffer = MainBuffer;
  488. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = AuxiliaryBuffer;
  489. break;
  490. }
  491. return Irp;
  492. } // SrvBuildIoControlRequest
  493. VOID
  494. SrvBuildFlushRequest (
  495. IN PIRP Irp,
  496. IN PFILE_OBJECT FileObject,
  497. IN PVOID Context OPTIONAL
  498. )
  499. /*++
  500. Routine Description:
  501. This function builds an I/O request packet for a flush request.
  502. Arguments:
  503. Irp - Supplies a pointer to an IRP.
  504. FileObject - Supplies a pointer the file object to which this
  505. request is directed. This pointer is copied into the IRP, so
  506. that the called driver can find its file-based context. NOTE
  507. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  508. that the file object is not deleted while the I/O operation is
  509. in progress. The server accomplishes this by incrementing a
  510. reference count in a local block to account for the I/O; the
  511. local block in turn references the file object.
  512. Context - Supplies a PVOID value that is passed to the completion
  513. routine.
  514. Return Value:
  515. None.
  516. --*/
  517. {
  518. PDEVICE_OBJECT deviceObject;
  519. PIO_STACK_LOCATION irpSp;
  520. PAGED_CODE( );
  521. deviceObject = IoGetRelatedDeviceObject( FileObject );
  522. ASSERT( Irp->StackCount >= deviceObject->StackSize );
  523. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  524. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  525. DEBUG Irp->RequestorMode = KernelMode;
  526. Irp->IoStatus.Status = 0;
  527. Irp->IoStatus.Information = 0;
  528. //
  529. // Get a pointer to the next stack location. This one is used to
  530. // hold the parameters for the read request. Fill in the
  531. // service-dependent parameters for the request.
  532. //
  533. irpSp = IoGetNextIrpStackLocation( Irp );
  534. //
  535. // Set up the completion routine.
  536. //
  537. IoSetCompletionRoutine(
  538. Irp,
  539. SrvFsdIoCompletionRoutine,
  540. Context,
  541. TRUE,
  542. TRUE,
  543. TRUE
  544. );
  545. irpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
  546. irpSp->FileObject = FileObject;
  547. irpSp->DeviceObject = deviceObject;
  548. irpSp->Flags = 0;
  549. return;
  550. } // SrvBuildFlushRequest
  551. VOID
  552. SrvBuildLockRequest (
  553. IN PIRP Irp,
  554. IN PFILE_OBJECT FileObject,
  555. IN PVOID Context OPTIONAL,
  556. IN LARGE_INTEGER ByteOffset,
  557. IN LARGE_INTEGER Length,
  558. IN ULONG Key,
  559. IN BOOLEAN FailImmediately,
  560. IN BOOLEAN ExclusiveLock
  561. )
  562. /*++
  563. Routine Description:
  564. This function builds an I/O request packet for a lock request.
  565. Arguments:
  566. Irp - Supplies a pointer to an IRP.
  567. FileObject - Supplies a pointer the file object to which this
  568. request is directed. This pointer is copied into the IRP, so
  569. that the called driver can find its file-based context. NOTE
  570. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  571. that the file object is not deleted while the I/O operation is
  572. in progress. The server accomplishes this by incrementing a
  573. reference count in a local block to account for the I/O; the
  574. local block in turn references the file object.
  575. Context - Supplies a PVOID value that is passed to the completion
  576. routine.
  577. StartingBlock - the block number of the beginning of the locked
  578. range.
  579. ByteOffset - the offset within block of the beginning of the locked
  580. range.
  581. Length - the length of the locked range.
  582. Key - the key value to be associated with the lock.
  583. Return Value:
  584. None.
  585. --*/
  586. {
  587. PDEVICE_OBJECT deviceObject;
  588. PIO_STACK_LOCATION irpSp;
  589. PAGED_CODE( );
  590. deviceObject = IoGetRelatedDeviceObject( FileObject );
  591. ASSERT( Irp->StackCount >= deviceObject->StackSize );
  592. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  593. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  594. DEBUG Irp->RequestorMode = KernelMode;
  595. Irp->IoStatus.Status = 0;
  596. Irp->IoStatus.Information = 0;
  597. //
  598. // Get a pointer to the next stack location. This one is used to
  599. // hold the parameters for the read request. Fill in the
  600. // service-dependent parameters for the request.
  601. //
  602. irpSp = IoGetNextIrpStackLocation( Irp );
  603. //
  604. // Set up the completion routine.
  605. //
  606. IoSetCompletionRoutine(
  607. Irp,
  608. SrvFsdIoCompletionRoutine,
  609. Context,
  610. TRUE,
  611. TRUE,
  612. TRUE
  613. );
  614. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  615. irpSp->MinorFunction = IRP_MN_LOCK;
  616. irpSp->FileObject = FileObject;
  617. irpSp->DeviceObject = deviceObject;
  618. irpSp->Flags = 0;
  619. if ( FailImmediately ) {
  620. irpSp->Flags = SL_FAIL_IMMEDIATELY;
  621. }
  622. if ( ExclusiveLock ) {
  623. irpSp->Flags |= SL_EXCLUSIVE_LOCK;
  624. }
  625. ((PWORK_CONTEXT)Context)->Parameters2.LockLength = Length;
  626. irpSp->Parameters.LockControl.Length = &((PWORK_CONTEXT)Context)->Parameters2.LockLength;
  627. irpSp->Parameters.LockControl.Key = Key;
  628. irpSp->Parameters.LockControl.ByteOffset = ByteOffset;
  629. return;
  630. } // SrvBuildLockRequest
  631. NTSTATUS
  632. SrvMdlCompletionRoutine (
  633. IN PDEVICE_OBJECT DeviceObject,
  634. IN PIRP Irp,
  635. IN PVOID Context
  636. )
  637. {
  638. DeviceObject; Irp; Context;
  639. return STATUS_MORE_PROCESSING_REQUIRED;
  640. }
  641. NTSTATUS
  642. SrvIssueMdlCompleteRequest (
  643. IN PWORK_CONTEXT WorkContext OPTIONAL,
  644. IN PFILE_OBJECT FileObject OPTIONAL,
  645. IN PMDL Mdl,
  646. IN UCHAR Function,
  647. IN PLARGE_INTEGER ByteOffset,
  648. IN ULONG Length
  649. )
  650. {
  651. PIRP irp;
  652. PIO_STACK_LOCATION irpSp;
  653. PFILE_OBJECT fileObject = FileObject ? FileObject : WorkContext->Rfcb->Lfcb->FileObject;
  654. PDEVICE_OBJECT deviceObject = IoGetRelatedDeviceObject( fileObject );
  655. KEVENT userEvent;
  656. NTSTATUS status;
  657. IO_STATUS_BLOCK ioStatusBlock;
  658. if( (irp = IoAllocateIrp( deviceObject->StackSize, TRUE )) == NULL ) {
  659. return STATUS_INSUFFICIENT_RESOURCES;
  660. }
  661. // Reference the file object
  662. ObReferenceObject( fileObject );
  663. KeInitializeEvent( &userEvent, SynchronizationEvent, FALSE );
  664. KeClearEvent( &userEvent );
  665. irp->MdlAddress = Mdl;
  666. irp->Flags = IRP_SYNCHRONOUS_API;
  667. irp->UserEvent = &userEvent;
  668. irp->UserIosb = &ioStatusBlock;
  669. irp->RequestorMode = KernelMode;
  670. irp->PendingReturned = FALSE;
  671. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  672. irp->Tail.Overlay.OriginalFileObject = fileObject;
  673. irp->IoStatus.Status = 0;
  674. irp->IoStatus.Information = 0;
  675. irpSp = IoGetNextIrpStackLocation( irp );
  676. irpSp->FileObject = fileObject;
  677. irpSp->DeviceObject = deviceObject;
  678. irpSp->Flags = 0;
  679. irpSp->MinorFunction = IRP_MN_MDL | IRP_MN_COMPLETE;
  680. irpSp->MajorFunction = Function;
  681. if( Function == IRP_MJ_WRITE ) {
  682. irpSp->Parameters.Write.ByteOffset = *ByteOffset;
  683. irpSp->Parameters.Write.Length = Length;
  684. } else {
  685. irpSp->Parameters.Read.ByteOffset = *ByteOffset;
  686. irpSp->Parameters.Read.Length = Length;
  687. }
  688. status = IoCallDriver( deviceObject, irp );
  689. if (status == STATUS_PENDING) {
  690. (VOID) KeWaitForSingleObject( &userEvent,
  691. UserRequest,
  692. KernelMode,
  693. FALSE,
  694. (PLARGE_INTEGER) NULL );
  695. status = ioStatusBlock.Status;
  696. }
  697. ASSERT( status == STATUS_SUCCESS );
  698. return status;
  699. }
  700. VOID
  701. SrvBuildMailslotWriteRequest (
  702. IN PIRP Irp,
  703. IN PFILE_OBJECT FileObject,
  704. IN PVOID Context OPTIONAL,
  705. IN PVOID Buffer OPTIONAL,
  706. IN ULONG Length
  707. )
  708. /*++
  709. Routine Description:
  710. This function builds an I/O request packet for a mailslot write
  711. request.
  712. Arguments:
  713. Irp - Supplies a pointer to an IRP.
  714. FileObject - Supplies a pointer the file object to which this
  715. request is directed. This pointer is copied into the IRP, so
  716. that the called driver can find its file-based context. NOTE
  717. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  718. that the file object is not deleted while the I/O operation is
  719. in progress. The server accomplishes this by incrementing a
  720. reference count in a local block to account for the I/O; the
  721. local block in turn references the file object.
  722. Context - Supplies a PVOID value that is passed to the completion
  723. routine.
  724. Buffer - Supplies the system virtual address of the write
  725. buffer.
  726. Length - Supplies the length of the write.
  727. Return Value:
  728. None.
  729. --*/
  730. {
  731. PDEVICE_OBJECT deviceObject;
  732. PIO_STACK_LOCATION irpSp;
  733. PAGED_CODE( );
  734. deviceObject = IoGetRelatedDeviceObject( FileObject );
  735. ASSERT( Irp->StackCount >= deviceObject->StackSize );
  736. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  737. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  738. DEBUG Irp->RequestorMode = KernelMode;
  739. Irp->IoStatus.Status = 0;
  740. Irp->IoStatus.Information = 0;
  741. //
  742. // Get a pointer to the next stack location. This one is used to
  743. // hold the parameters for the read request.
  744. //
  745. irpSp = IoGetNextIrpStackLocation( Irp );
  746. //
  747. // Set up the completion routine.
  748. //
  749. IoSetCompletionRoutine(
  750. Irp,
  751. SrvFsdIoCompletionRoutine,
  752. Context,
  753. TRUE,
  754. TRUE,
  755. TRUE
  756. );
  757. irpSp->MajorFunction = IRP_MJ_WRITE;
  758. irpSp->MinorFunction = 0;
  759. irpSp->FileObject = FileObject;
  760. irpSp->DeviceObject = deviceObject;
  761. //
  762. // Set the write buffer.
  763. //
  764. //Irp->AssociatedIrp.SystemBuffer = Buffer;
  765. Irp->UserBuffer = Buffer;
  766. Irp->Flags = IRP_BUFFERED_IO;
  767. //
  768. // Set the write parameters.
  769. //
  770. irpSp->Parameters.Write.Length = Length;
  771. return;
  772. } // SrvBuildMailslotWriteRequest
  773. VOID
  774. SrvBuildReadOrWriteRequest (
  775. IN OUT PIRP Irp,
  776. IN PFILE_OBJECT FileObject,
  777. IN PVOID Context OPTIONAL,
  778. IN UCHAR MajorFunction,
  779. IN UCHAR MinorFunction,
  780. IN PVOID Buffer OPTIONAL,
  781. IN ULONG Length,
  782. IN OUT PMDL Mdl OPTIONAL,
  783. IN LARGE_INTEGER ByteOffset,
  784. IN ULONG Key OPTIONAL
  785. )
  786. /*++
  787. Routine Description:
  788. This function builds an I/O request packet for a read or write
  789. request.
  790. Arguments:
  791. Irp - Supplies a pointer to an IRP.
  792. FileObject - Supplies a pointer the file object to which this
  793. request is directed. This pointer is copied into the IRP, so
  794. that the called driver can find its file-based context. NOTE
  795. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  796. that the file object is not deleted while the I/O operation is
  797. in progress. The server accomplishes this by incrementing a
  798. reference count in a local block to account for the I/O; the
  799. local block in turn references the file object.
  800. Context - Supplies a PVOID value that is passed to the completion
  801. routine.
  802. MajorFunction - Indicates the function to be performed. Must be
  803. either IRP_MJ_READ or IRP_MJ_WRITE.
  804. MinorFunction - Qualifies the function to be performed. (For
  805. example, issued at DPC level, MDL read, etc.)
  806. Buffer - Supplies the system virtual address of the read or write
  807. buffer. This parameter is ignored when MinorFunction is
  808. IRP_MN_*_MDL_*. Otherwise, the buffer must be mapped in the
  809. system virtual address space in order to support buffered I/O
  810. devices and other device drivers that need to look at the user
  811. data. This routine always treats the buffer as a direct I/O
  812. buffer, locking it for I/O with an MDL. It does, however, set
  813. up the IRP appropriately for the device type.
  814. If the Mdl parameter is NULL, this routine locks the buffer in
  815. memory for the I/O. It is then the responsibility of the
  816. calling program to unlock the buffer and deallocate the MDL
  817. after the I/O is complete.
  818. Length - Supplies the length of the read or write.
  819. Mdl - This parameter is used to supply a pointer to an MDL
  820. describing a buffer. It is ignored when MinorFunction is
  821. IRP_MN_MDL_*. Otherwise, Mdl must not be NULL. The buffer must
  822. reside in the system virtual address space (for the benefit of
  823. buffered I/O devices/drivers). If the buffer is not already
  824. locked, this routine locks it. It is the calling program's
  825. responsibility to unlock the buffer and (potentially) deallocate
  826. the MDL after the I/O is complete.
  827. ByteOffset - the offset within the file of the beginning of the read
  828. or write.
  829. Key - the key value to be associated with the read or write.
  830. Return Value:
  831. None.
  832. --*/
  833. {
  834. PDEVICE_OBJECT deviceObject;
  835. PIO_STACK_LOCATION irpSp;
  836. PAGED_CODE( );
  837. if( Irp->AssociatedIrp.SystemBuffer &&
  838. (Irp->Flags & IRP_DEALLOCATE_BUFFER) ) {
  839. ExFreePool( Irp->AssociatedIrp.SystemBuffer );
  840. Irp->Flags &= ~IRP_DEALLOCATE_BUFFER;
  841. }
  842. //
  843. // Obtain the address of the device object and allocate the IRP
  844. // based on the stack size for that device.
  845. //
  846. deviceObject = IoGetRelatedDeviceObject( FileObject );
  847. ASSERT( Irp->StackCount >= deviceObject->StackSize );
  848. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  849. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  850. DEBUG Irp->RequestorMode = KernelMode;
  851. Irp->IoStatus.Status = 0;
  852. Irp->IoStatus.Information = 0;
  853. //
  854. // Get a pointer to the next stack location. This one is used to
  855. // hold the parameters for the read request.
  856. //
  857. irpSp = IoGetNextIrpStackLocation( Irp );
  858. //
  859. // Set up the completion routine.
  860. //
  861. IoSetCompletionRoutine(
  862. Irp,
  863. SrvFsdIoCompletionRoutine,
  864. Context,
  865. TRUE,
  866. TRUE,
  867. TRUE
  868. );
  869. irpSp->MajorFunction = MajorFunction;
  870. irpSp->MinorFunction = MinorFunction;
  871. irpSp->FileObject = FileObject;
  872. irpSp->DeviceObject = deviceObject;
  873. //
  874. // This routine used to handle MDL read/write completion, but it
  875. // doesn't now.
  876. //
  877. ASSERT( IRP_MN_DPC == 1 );
  878. ASSERT( IRP_MN_MDL == 2 );
  879. ASSERT( IRP_MN_MDL_DPC == 3 );
  880. ASSERT( IRP_MN_COMPLETE_MDL == 6 );
  881. ASSERT( IRP_MN_COMPLETE_MDL_DPC == 7 );
  882. ASSERT( (MinorFunction & 4) == 0 );
  883. //
  884. // Set the parameters according to whether this is a read or a write
  885. // operation. Notice that these parameters must be set even if the
  886. // driver has not specified buffered or direct I/O.
  887. //
  888. if ( MajorFunction == IRP_MJ_WRITE ) {
  889. irpSp->Parameters.Write.ByteOffset = ByteOffset;
  890. irpSp->Parameters.Write.Length = Length;
  891. irpSp->Parameters.Write.Key = Key;
  892. } else {
  893. irpSp->Parameters.Read.ByteOffset = ByteOffset;
  894. irpSp->Parameters.Read.Length = Length;
  895. irpSp->Parameters.Read.Key = Key;
  896. }
  897. //
  898. // Indicate to the file system that this operation can be handled
  899. // synchronously. Basically, this means that the file system can
  900. // use the server's thread to fault pages in, etc. This avoids
  901. // having to context switch to a file system thread.
  902. //
  903. Irp->Flags = IRP_SYNCHRONOUS_API;
  904. //
  905. // If this is the start of an MDL-based read or write, we simply
  906. // need to put the supplied MDL address in the IRP. This optional
  907. // MDL address can provide a partial chain for a read or write that
  908. // was partially satisfied using the fast I/O path.
  909. //
  910. if ( (MinorFunction & IRP_MN_MDL) != 0 ) {
  911. Irp->MdlAddress = Mdl;
  912. DEBUG Irp->UserBuffer = NULL;
  913. DEBUG Irp->AssociatedIrp.SystemBuffer = NULL;
  914. return;
  915. }
  916. //
  917. // Normal ("copy") read or write.
  918. //
  919. ASSERT( Buffer != NULL );
  920. ASSERT( Mdl != NULL );
  921. //
  922. // If the target device does buffered I/O, load the address of the
  923. // caller's buffer as the "system buffered I/O buffer". If the
  924. // target device does direct I/O, load the MDL address. If it does
  925. // neither, load both the user buffer address and the MDL address.
  926. // (This is necessary to support file systems, such as HPFS, that
  927. // sometimes treat the I/O as buffered and sometimes treat it as
  928. // direct.)
  929. //
  930. if ( (deviceObject->Flags & DO_BUFFERED_IO) != 0 ) {
  931. Irp->AssociatedIrp.SystemBuffer = Buffer;
  932. if ( MajorFunction == IRP_MJ_WRITE ) {
  933. Irp->Flags |= IRP_BUFFERED_IO;
  934. } else {
  935. Irp->Flags |= IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
  936. }
  937. } else if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  938. Irp->MdlAddress = Mdl;
  939. } else {
  940. Irp->UserBuffer = Buffer;
  941. Irp->MdlAddress = Mdl;
  942. }
  943. return;
  944. } // SrvBuildReadOrWriteRequest
  945. PIRP
  946. SrvBuildNotifyChangeRequest (
  947. IN OUT PIRP Irp,
  948. IN PFILE_OBJECT FileObject,
  949. IN PVOID Context OPTIONAL,
  950. IN ULONG CompletionFilter,
  951. IN PVOID Buffer,
  952. IN ULONG BufferLength,
  953. IN BOOLEAN WatchTree
  954. )
  955. /*++
  956. Routine Description:
  957. This function builds an I/O request packet for a notify change request.
  958. Arguments:
  959. Irp - Supplies a pointer to an IRP.
  960. FileObject - Supplies a pointer the file object to which this
  961. request is directed. This pointer is copied into the IRP, so
  962. that the called driver can find its file-based context. NOTE
  963. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  964. that the file object is not deleted while the I/O operation is
  965. in progress. The server accomplishes this by incrementing a
  966. reference count in a local block to account for the I/O; the
  967. local block in turn references the file object.
  968. Context - Supplies a PVOID value that is passed to the completion
  969. routine.
  970. CompletionFilter - Specifies which directory changes will cause the
  971. File sytsem to complete the IRP.
  972. Buffer - The buffer to receive the directory change data.
  973. BufferLength - The size, in bytes, of the buffer.
  974. WatchTree - If TRUE, recursively watch all subdirectories for changes.
  975. Return Value:
  976. PIRP - Returns a pointer to the constructed IRP. If the Irp
  977. parameter was not NULL on input, the function return value will
  978. be the same value (so it is safe to discard the return value in
  979. this case). It is the responsibility of the calling program to
  980. deallocate the IRP after the I/O request is complete.
  981. --*/
  982. {
  983. PDEVICE_OBJECT deviceObject;
  984. PIO_STACK_LOCATION irpSp;
  985. PMDL mdl;
  986. PAGED_CODE( );
  987. if( Irp->AssociatedIrp.SystemBuffer &&
  988. (Irp->Flags & IRP_DEALLOCATE_BUFFER) ) {
  989. ExFreePool( Irp->AssociatedIrp.SystemBuffer );
  990. Irp->Flags &= ~IRP_DEALLOCATE_BUFFER;
  991. }
  992. //
  993. // Obtain the address of the device object and initialize the IRP.
  994. //
  995. deviceObject = IoGetRelatedDeviceObject( FileObject );
  996. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  997. Irp->Tail.Overlay.Thread = PROCESSOR_TO_QUEUE()->IrpThread;
  998. Irp->RequestorMode = KernelMode;
  999. Irp->MdlAddress = NULL;
  1000. Irp->IoStatus.Status = 0;
  1001. Irp->IoStatus.Information = 0;
  1002. //
  1003. // Get a pointer to the next stack location. This one is used to
  1004. // hold the parameters for the read request. Fill in the
  1005. // service-dependent parameters for the request.
  1006. //
  1007. irpSp = IoGetNextIrpStackLocation( Irp );
  1008. //
  1009. // Set up the completion routine.
  1010. //
  1011. IoSetCompletionRoutine(
  1012. Irp,
  1013. SrvFsdIoCompletionRoutine,
  1014. Context,
  1015. TRUE,
  1016. TRUE,
  1017. TRUE
  1018. );
  1019. irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
  1020. irpSp->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
  1021. irpSp->FileObject = FileObject;
  1022. irpSp->DeviceObject = deviceObject;
  1023. irpSp->Flags = 0;
  1024. if (WatchTree) {
  1025. irpSp->Flags = SL_WATCH_TREE;
  1026. }
  1027. irpSp->Parameters.NotifyDirectory.Length = BufferLength;
  1028. irpSp->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
  1029. if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  1030. mdl = IoAllocateMdl(
  1031. Buffer,
  1032. BufferLength,
  1033. FALSE,
  1034. FALSE,
  1035. Irp // stores MDL address in irp->MdlAddress
  1036. );
  1037. if ( mdl == NULL ) {
  1038. //
  1039. // Unable to allocate an MDL. Fail the I/O.
  1040. //
  1041. return NULL;
  1042. }
  1043. try {
  1044. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1045. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1046. IoFreeMdl( mdl );
  1047. return NULL;
  1048. }
  1049. Irp->AssociatedIrp.SystemBuffer = NULL;
  1050. Irp->UserBuffer = NULL;
  1051. } else {
  1052. Irp->AssociatedIrp.SystemBuffer = Buffer;
  1053. Irp->UserBuffer = NULL;
  1054. }
  1055. //
  1056. // Return a pointer to the IRP.
  1057. //
  1058. return Irp;
  1059. } // SrvBuildNotifyChangeRequest
  1060. NTSTATUS
  1061. SrvIssueAssociateRequest (
  1062. IN PFILE_OBJECT FileObject,
  1063. IN PDEVICE_OBJECT *DeviceObject,
  1064. IN HANDLE AddressFileHandle
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. This function issues an I/O request packet for a TdiAssociateAddress
  1069. request. It builds an I/O request packet, passes the IRP to the
  1070. driver (using IoCallDriver), and waits for the I/O to complete.
  1071. Arguments:
  1072. FileObject - pointer to file object for a connection.
  1073. DeviceObject - pointer to pointer to device object for a connection.
  1074. AddressFileHandle - handle to an address endpoint.
  1075. Return Value:
  1076. NTSTATUS - the status of the operation. Either the return value of
  1077. IoCallDriver, if the driver didn't accept the request, or the
  1078. value returned by the driver in the I/O status block.
  1079. --*/
  1080. {
  1081. PIRP irp;
  1082. PIO_STACK_LOCATION irpSp;
  1083. PTDI_REQUEST_KERNEL_ASSOCIATE parameters;
  1084. KEVENT event;
  1085. IO_STATUS_BLOCK iosb;
  1086. PAGED_CODE( );
  1087. //
  1088. // Allocate an IRP and fill in the service-independent parameters
  1089. // for the request.
  1090. //
  1091. irp = BuildCoreOfSyncIoRequest(
  1092. NULL,
  1093. FileObject,
  1094. &event,
  1095. &iosb,
  1096. DeviceObject
  1097. );
  1098. if ( irp == NULL ) {
  1099. //
  1100. // Unable to allocate an IRP. Fail the I/O.
  1101. //
  1102. return STATUS_INSUFF_SERVER_RESOURCES;
  1103. }
  1104. //
  1105. // Fill in the service-dependent parameters for the request.
  1106. //
  1107. irpSp = IoGetNextIrpStackLocation( irp );
  1108. parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&irpSp->Parameters;
  1109. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1110. irpSp->MinorFunction = TDI_ASSOCIATE_ADDRESS;
  1111. parameters->AddressHandle = AddressFileHandle;
  1112. //
  1113. // Start the I/O, wait for it to complete, and return the final status.
  1114. //
  1115. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1116. } // SrvIssueAssociateRequest
  1117. NTSTATUS
  1118. SrvIssueDisconnectRequest (
  1119. IN PFILE_OBJECT FileObject,
  1120. IN PDEVICE_OBJECT *DeviceObject,
  1121. IN ULONG Flags
  1122. )
  1123. /*++
  1124. Routine Description:
  1125. This function issues an I/O request packet for a TdiDisconnect
  1126. request. It builds an I/O request packet, passes the IRP to the
  1127. driver (using IoCallDriver), and waits for the I/O to complete.
  1128. Arguments:
  1129. FileObject - pointer to file object for a connection.
  1130. DeviceObject - pointer to pointer to device object for a connection.
  1131. Flags -
  1132. Return Value:
  1133. NTSTATUS - the status of the operation. Either the return value of
  1134. IoCallDriver, if the driver didn't accept the request, or the
  1135. value returned by the driver in the I/O status block.
  1136. --*/
  1137. {
  1138. PIRP irp;
  1139. PIO_STACK_LOCATION irpSp;
  1140. PTDI_REQUEST_KERNEL parameters;
  1141. KEVENT event;
  1142. IO_STATUS_BLOCK iosb;
  1143. PAGED_CODE( );
  1144. //
  1145. // Allocate an IRP and fill in the service-independent parameters
  1146. // for the request.
  1147. //
  1148. irp = BuildCoreOfSyncIoRequest(
  1149. NULL,
  1150. FileObject,
  1151. &event,
  1152. &iosb,
  1153. DeviceObject
  1154. );
  1155. if ( irp == NULL ) {
  1156. //
  1157. // Unable to allocate an IRP. Fail the I/O.
  1158. //
  1159. return STATUS_INSUFF_SERVER_RESOURCES;
  1160. }
  1161. //
  1162. // Fill in the service-dependent parameters for the request.
  1163. //
  1164. irpSp = IoGetNextIrpStackLocation( irp );
  1165. parameters = (PTDI_REQUEST_KERNEL)&irpSp->Parameters;
  1166. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1167. irpSp->MinorFunction = TDI_DISCONNECT;
  1168. parameters->RequestFlags = Flags;
  1169. //
  1170. // Start the I/O, wait for it to complete, and return the final status.
  1171. //
  1172. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1173. } // SrvIssueDisconnectRequest
  1174. NTSTATUS
  1175. SrvIssueTdiAction (
  1176. IN PFILE_OBJECT FileObject,
  1177. IN PDEVICE_OBJECT *DeviceObject,
  1178. IN PCHAR Buffer,
  1179. IN ULONG BufferLength
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. This function issues an I/O request packet for a TdiQueryInformation
  1184. (Query Adapter Status) request. It builds an I/O request packet,
  1185. passes the IRP to the driver (using IoCallDriver), and waits for the
  1186. I/O to complete.
  1187. Arguments:
  1188. FileObject - pointer to file object for a connection.
  1189. DeviceObject - pointer to pointer to device object for a connection.
  1190. Return Value:
  1191. NTSTATUS - the status of the operation. Either the return value of
  1192. IoCallDriver, if the driver didn't accept the request, or the
  1193. value returned by the driver in the I/O status block.
  1194. --*/
  1195. {
  1196. PIRP irp;
  1197. PIO_STACK_LOCATION irpSp;
  1198. KEVENT event;
  1199. IO_STATUS_BLOCK iosb;
  1200. PMDL mdl;
  1201. PAGED_CODE( );
  1202. //
  1203. // Allocate and build an MDL that we'll use to describe the output
  1204. // buffer for the request.
  1205. //
  1206. mdl = IoAllocateMdl( Buffer, BufferLength, FALSE, FALSE, NULL );
  1207. if ( mdl == NULL ) {
  1208. return STATUS_INSUFF_SERVER_RESOURCES;
  1209. }
  1210. try {
  1211. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1212. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1213. IoFreeMdl( mdl );
  1214. return GetExceptionCode();
  1215. }
  1216. //
  1217. // Allocate an IRP and fill in the service-independent parameters
  1218. // for the request.
  1219. //
  1220. irp = BuildCoreOfSyncIoRequest(
  1221. NULL,
  1222. FileObject,
  1223. &event,
  1224. &iosb,
  1225. DeviceObject
  1226. );
  1227. if ( irp == NULL ) {
  1228. //
  1229. // Unable to allocate an IRP. Fail the I/O.
  1230. //
  1231. MmUnlockPages( mdl );
  1232. IoFreeMdl( mdl );
  1233. return STATUS_INSUFF_SERVER_RESOURCES;
  1234. }
  1235. //
  1236. // Fill in the service-dependent parameters for the request.
  1237. //
  1238. irpSp = IoGetNextIrpStackLocation( irp );
  1239. TdiBuildAction(
  1240. irp,
  1241. *DeviceObject,
  1242. FileObject,
  1243. NULL,
  1244. NULL,
  1245. mdl
  1246. );
  1247. //
  1248. // Start the I/O, wait for it to complete, and return the final status.
  1249. //
  1250. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1251. } // SrvIssueTdiAction
  1252. NTSTATUS
  1253. SrvIssueTdiQuery (
  1254. IN PFILE_OBJECT FileObject,
  1255. IN PDEVICE_OBJECT *DeviceObject,
  1256. IN PCHAR Buffer,
  1257. IN ULONG BufferLength,
  1258. IN ULONG QueryType
  1259. )
  1260. /*++
  1261. Routine Description:
  1262. This function issues an I/O request packet for a TdiQueryInformation
  1263. (Query Adapter Status) request. It builds an I/O request packet,
  1264. passes the IRP to the driver (using IoCallDriver), and waits for the
  1265. I/O to complete.
  1266. Arguments:
  1267. FileObject - pointer to file object for a connection.
  1268. DeviceObject - pointer to pointer to device object for a connection.
  1269. Return Value:
  1270. NTSTATUS - the status of the operation. Either the return value of
  1271. IoCallDriver, if the driver didn't accept the request, or the
  1272. value returned by the driver in the I/O status block.
  1273. --*/
  1274. {
  1275. PIRP irp;
  1276. PIO_STACK_LOCATION irpSp;
  1277. KEVENT event;
  1278. IO_STATUS_BLOCK iosb;
  1279. PMDL mdl;
  1280. PAGED_CODE( );
  1281. //
  1282. // Allocate and build an MDL that we'll use to describe the output
  1283. // buffer for the request.
  1284. //
  1285. mdl = IoAllocateMdl( Buffer, BufferLength, FALSE, FALSE, NULL );
  1286. if ( mdl == NULL ) {
  1287. return STATUS_INSUFF_SERVER_RESOURCES;
  1288. }
  1289. try {
  1290. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1291. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1292. IoFreeMdl( mdl );
  1293. return GetExceptionCode();
  1294. }
  1295. //
  1296. // Allocate an IRP and fill in the service-independent parameters
  1297. // for the request.
  1298. //
  1299. irp = BuildCoreOfSyncIoRequest(
  1300. NULL,
  1301. FileObject,
  1302. &event,
  1303. &iosb,
  1304. DeviceObject
  1305. );
  1306. if ( irp == NULL ) {
  1307. //
  1308. // Unable to allocate an IRP. Fail the I/O.
  1309. //
  1310. MmUnlockPages( mdl );
  1311. IoFreeMdl( mdl );
  1312. return STATUS_INSUFF_SERVER_RESOURCES;
  1313. }
  1314. //
  1315. // Fill in the service-dependent parameters for the request.
  1316. //
  1317. irpSp = IoGetNextIrpStackLocation( irp );
  1318. TdiBuildQueryInformation(
  1319. irp,
  1320. *DeviceObject,
  1321. FileObject,
  1322. NULL,
  1323. NULL,
  1324. QueryType,
  1325. mdl
  1326. );
  1327. //
  1328. // Start the I/O, wait for it to complete, and return the final status.
  1329. //
  1330. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1331. } // SrvIssueTdiQuery
  1332. NTSTATUS
  1333. SrvIssueQueryDirectoryRequest (
  1334. IN HANDLE FileHandle,
  1335. IN PCHAR Buffer,
  1336. IN ULONG Length,
  1337. IN FILE_INFORMATION_CLASS FileInformationClass,
  1338. IN PUNICODE_STRING FileName OPTIONAL,
  1339. IN PULONG FileIndex OPTIONAL,
  1340. IN BOOLEAN RestartScan,
  1341. IN BOOLEAN SingleEntriesOnly
  1342. )
  1343. /*++
  1344. Routine Description:
  1345. This function issues an I/O request packet for a query directory
  1346. request. It builds an I/O request packet, passes the IRP to the
  1347. driver (using IoCallDriver), and waits for the I/O to complete.
  1348. Arguments:
  1349. FileHandle - handle to a directory open with FILE_LIST_DIRECTORY
  1350. access.
  1351. Buffer - supplies the system virtual address of the buffer. The
  1352. buffer must be in nonpaged pool.
  1353. Length - supplies the length of the buffer.
  1354. FileInformationClass - Specfies the type of information that is to be
  1355. returned about the files in the specified directory.
  1356. FileName - an optional pointer to a file name. If FileIndex is NULL,
  1357. then this is the search specification, i.e. the template that
  1358. files must match in order to be returned. If FileIndex is
  1359. non-NULL, then this is the name of a file after which to resume
  1360. a search.
  1361. FileIndex - if specified, the index of a file after which to resume
  1362. the search (first file returned is the one after the one
  1363. corresponding to the index).
  1364. RestartScan - Supplies a BOOLEAN value that, if TRUE, indicates that the
  1365. scan should be restarted from the beginning.
  1366. SingleEntriesOnly - Supplies a BOOLEAN value that, if TRUE, indicates that
  1367. the scan should ask only for one entry at a time.
  1368. Return Value:
  1369. NTSTATUS - the status of the operation. Either the return value of
  1370. IoCallDriver, if the driver didn't accept the request, or the
  1371. value returned by the driver in the I/O status block.
  1372. --*/
  1373. {
  1374. ULONG actualBufferLength;
  1375. PIRP irp;
  1376. PIO_STACK_LOCATION irpSp;
  1377. KEVENT event;
  1378. IO_STATUS_BLOCK iosb;
  1379. PDEVICE_OBJECT deviceObject;
  1380. PUNICODE_STRING fileNameString;
  1381. PMDL mdl;
  1382. PAGED_CODE( );
  1383. //
  1384. // Reject rewind requests if debugging for it. If a file index is
  1385. // specified, this must be a rewind request, so reject the request.
  1386. //
  1387. IF_DEBUG(BRUTE_FORCE_REWIND) {
  1388. if ( ARGUMENT_PRESENT( FileIndex ) ) {
  1389. return STATUS_NOT_IMPLEMENTED;
  1390. }
  1391. }
  1392. //
  1393. // Copy the file name into the end of the specified buffer, setting
  1394. // the actualBufferLength accordingly.
  1395. //
  1396. if ( !ARGUMENT_PRESENT(FileName) || FileName->Length == 0 ) {
  1397. actualBufferLength = Length;
  1398. fileNameString = NULL;
  1399. } else {
  1400. //
  1401. // *** Remember that the string must be longword-aligned!
  1402. //
  1403. actualBufferLength = (Length - FileName->Length -
  1404. sizeof(UNICODE_STRING)) & ~(sizeof(PVOID)-1);
  1405. fileNameString = (PUNICODE_STRING)( Buffer + actualBufferLength );
  1406. RtlCopyMemory(
  1407. fileNameString + 1,
  1408. FileName->Buffer,
  1409. FileName->Length
  1410. );
  1411. fileNameString->Length = FileName->Length;
  1412. fileNameString->MaximumLength = FileName->Length;
  1413. fileNameString->Buffer = (PWCH)(fileNameString + 1);
  1414. }
  1415. //
  1416. // Allocate an IRP and fill in the service-independent parameters
  1417. // for the request.
  1418. //
  1419. irp = BuildCoreOfSyncIoRequest(
  1420. FileHandle,
  1421. NULL,
  1422. &event,
  1423. &iosb,
  1424. &deviceObject
  1425. );
  1426. if ( irp == NULL ) {
  1427. //
  1428. // Unable to allocate an IRP. Fail the I/O.
  1429. //
  1430. return STATUS_INSUFF_SERVER_RESOURCES;
  1431. }
  1432. //
  1433. // Fill in the service-dependent parameters for the request.
  1434. //
  1435. irpSp = IoGetNextIrpStackLocation( irp );
  1436. irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
  1437. irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
  1438. irpSp->Parameters.QueryDirectory.FileName = (PSTRING)fileNameString;
  1439. irpSp->Parameters.QueryDirectory.FileIndex =
  1440. (ULONG)( ARGUMENT_PRESENT( FileIndex ) ? *FileIndex : 0 );
  1441. irpSp->Parameters.QueryDirectory.Length = actualBufferLength;
  1442. irpSp->Parameters.QueryDirectory.FileInformationClass =
  1443. FileInformationClass;
  1444. //
  1445. // Set the flags in the stack location.
  1446. //
  1447. irpSp->Flags = 0;
  1448. if ( ARGUMENT_PRESENT( FileIndex ) ) {
  1449. IF_DEBUG( SEARCH ) {
  1450. KdPrint(("SrvIssueQueryDirectoryRequest: SL_INDEX_SPECIFIED\n" ));
  1451. }
  1452. irpSp->Flags |= SL_INDEX_SPECIFIED;
  1453. }
  1454. if ( RestartScan ) {
  1455. IF_DEBUG( SEARCH ) {
  1456. KdPrint(("SrvIssueQueryDirectoryRequest: SL_RESTART_SCAN\n" ));
  1457. }
  1458. irpSp->Flags |= SL_RESTART_SCAN;
  1459. }
  1460. if( SingleEntriesOnly ) {
  1461. IF_DEBUG( SEARCH ) {
  1462. KdPrint(("SrvIssueQueryDirectoryRequest: SL_RETURN_SINGLE_ENTRY\n" ));
  1463. }
  1464. irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
  1465. }
  1466. //
  1467. // The file system has been updated. Determine whether the driver wants
  1468. // buffered, direct, or "neither" I/O.
  1469. //
  1470. if ( (deviceObject->Flags & DO_BUFFERED_IO) != 0 ) {
  1471. //
  1472. // The file system wants buffered I/O. Pass the address of the
  1473. // "system buffer" in the IRP. Note that we don't want the buffer
  1474. // deallocated, nor do we want the I/O system to copy to a user
  1475. // buffer, so we don't set the corresponding flags in irp->Flags.
  1476. //
  1477. irp->AssociatedIrp.SystemBuffer = Buffer;
  1478. } else if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  1479. //
  1480. // The file system wants direct I/O. Allocate an MDL and lock the
  1481. // buffer into memory.
  1482. //
  1483. mdl = IoAllocateMdl(
  1484. Buffer,
  1485. actualBufferLength,
  1486. FALSE,
  1487. FALSE,
  1488. irp // stores MDL address in irp->MdlAddress
  1489. );
  1490. if ( mdl == NULL ) {
  1491. //
  1492. // Unable to allocate an MDL. Fail the I/O.
  1493. //
  1494. IoFreeIrp( irp );
  1495. return STATUS_INSUFF_SERVER_RESOURCES;
  1496. }
  1497. try {
  1498. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1499. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1500. IoFreeIrp( irp );
  1501. MmUnlockPages( mdl );
  1502. IoFreeMdl( mdl );
  1503. return GetExceptionCode();
  1504. }
  1505. } else {
  1506. //
  1507. // The file system wants "neither" I/O. Simply pass the address
  1508. // of the buffer.
  1509. //
  1510. // *** Note that if the file system decides to do this as buffered
  1511. // I/O, it will be wasting nonpaged pool, since our buffer is
  1512. // already in nonpaged pool. But since we're doing this as a
  1513. // synchronous request, the file system probably won't do that.
  1514. //
  1515. irp->UserBuffer = Buffer;
  1516. }
  1517. //
  1518. // Start the I/O, wait for it to complete, and return the final status.
  1519. //
  1520. return StartIoAndWait( irp, deviceObject, &event, &iosb );
  1521. } // SrvIssueQueryDirectoryRequest
  1522. NTSTATUS
  1523. SrvIssueQueryEaRequest (
  1524. IN HANDLE FileHandle,
  1525. IN PVOID Buffer,
  1526. IN ULONG Length,
  1527. IN PVOID EaList OPTIONAL,
  1528. IN ULONG EaListLength,
  1529. IN BOOLEAN RestartScan,
  1530. OUT PULONG EaErrorOffset OPTIONAL
  1531. )
  1532. /*++
  1533. Routine Description:
  1534. This function issues an I/O request packet for an EA query request.
  1535. It builds an I/O request packet, passes the IRP to the driver (using
  1536. IoCallDriver), and waits for the I/O to complete.
  1537. Arguments:
  1538. FileHandle - handle to a file open with FILE_READ_EA access.
  1539. Buffer - supplies the system virtual address of the buffer. The
  1540. buffer must be in nonpaged pool.
  1541. Length - supplies the length of the buffer.
  1542. EaList - supplies a pointer to a list of EAs to query. If omitted,
  1543. all EAs are returned.
  1544. EaListLength - supplies the length of EaList.
  1545. RestartScan - if TRUE, then the query of EAs is to start from the
  1546. beginning. Otherwise, continue from where we left off.
  1547. EaErrorOffset - if not NULL, returns the offset into EaList of an
  1548. invalid EA, if any.
  1549. Return Value:
  1550. NTSTATUS - the status of the operation. Either the return value of
  1551. IoCallDriver, if the driver didn't accept the request, or the
  1552. value returned by the driver in the I/O status block.
  1553. --*/
  1554. {
  1555. NTSTATUS status;
  1556. PIRP irp;
  1557. PIO_STACK_LOCATION irpSp;
  1558. KEVENT event;
  1559. IO_STATUS_BLOCK iosb;
  1560. PDEVICE_OBJECT deviceObject;
  1561. PMDL mdl;
  1562. PAGED_CODE( );
  1563. //
  1564. // Allocate an IRP and fill in the service-independent parameters
  1565. // for the request.
  1566. //
  1567. irp = BuildCoreOfSyncIoRequest(
  1568. FileHandle,
  1569. NULL,
  1570. &event,
  1571. &iosb,
  1572. &deviceObject
  1573. );
  1574. if ( irp == NULL ) {
  1575. //
  1576. // Unable to allocate an IRP. Fail the i/o.
  1577. //
  1578. return STATUS_INSUFF_SERVER_RESOURCES;
  1579. }
  1580. //
  1581. // Fill in the service-dependent parameters for the request.
  1582. //
  1583. irpSp = IoGetNextIrpStackLocation( irp );
  1584. irpSp->MajorFunction = IRP_MJ_QUERY_EA;
  1585. irpSp->MinorFunction = 0;
  1586. irpSp->Parameters.QueryEa.Length = Length;
  1587. irpSp->Parameters.QueryEa.EaList = EaList;
  1588. irpSp->Parameters.QueryEa.EaListLength = EaListLength;
  1589. irpSp->Parameters.QueryEa.EaIndex = 0L;
  1590. irpSp->Flags = (UCHAR)( RestartScan ? SL_RESTART_SCAN : 0 );
  1591. //
  1592. // The file system has been updated. Determine whether the
  1593. // driver wants buffered, direct, or "neither" I/O.
  1594. //
  1595. if ( (deviceObject->Flags & DO_BUFFERED_IO) != 0 ) {
  1596. //
  1597. // The file system wants buffered I/O. Pass the address of the
  1598. // "system buffer" in the IRP. Note that we don't want the buffer
  1599. // deallocated, nor do we want the I/O system to copy to a user
  1600. // buffer, so we don't set the corresponding flags in irp->Flags.
  1601. //
  1602. irp->AssociatedIrp.SystemBuffer = Buffer;
  1603. } else if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  1604. //
  1605. // The file system wants direct I/O. Allocate an MDL and lock the
  1606. // buffer into memory.
  1607. //
  1608. mdl = IoAllocateMdl(
  1609. Buffer,
  1610. Length,
  1611. FALSE,
  1612. FALSE,
  1613. irp // stores MDL address in irp->MdlAddress
  1614. );
  1615. if ( mdl == NULL ) {
  1616. //
  1617. // Unable to allocate an MDL. Fail the I/O.
  1618. //
  1619. IoFreeIrp( irp );
  1620. return STATUS_INSUFF_SERVER_RESOURCES;
  1621. }
  1622. try {
  1623. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1624. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1625. IoFreeIrp( irp );
  1626. IoFreeMdl( mdl );
  1627. return GetExceptionCode();
  1628. }
  1629. } else {
  1630. //
  1631. // The file system wants "neither" I/O. Simply pass the address
  1632. // of the buffer.
  1633. //
  1634. // *** Note that if the file system decides to do this as buffered
  1635. // I/O, it will be wasting nonpaged pool, since out buffer is
  1636. // already in nonpaged pool. But since we're doing this as a
  1637. // synchronous request, the file system probably won't do that.
  1638. //
  1639. irp->UserBuffer = Buffer;
  1640. }
  1641. //
  1642. // Start the I/O, wait for it to complete, and return the final
  1643. // status.
  1644. //
  1645. status = StartIoAndWait( irp, deviceObject, &event, &iosb );
  1646. if ( ARGUMENT_PRESENT(EaErrorOffset) ) {
  1647. *EaErrorOffset = (ULONG)iosb.Information;
  1648. }
  1649. return status;
  1650. } // SrvIssueQueryEaRequest
  1651. NTSTATUS
  1652. SrvIssueSendDatagramRequest (
  1653. IN PFILE_OBJECT FileObject,
  1654. IN PDEVICE_OBJECT *DeviceObject,
  1655. IN PTDI_CONNECTION_INFORMATION SendDatagramInformation,
  1656. IN PVOID Buffer,
  1657. IN ULONG Length
  1658. )
  1659. /*++
  1660. Routine Description:
  1661. This function issues an I/O request packet for a TDI Send Datagram
  1662. request. It builds an I/O request packet, passes the IRP to the
  1663. driver (using IoCallDriver), and waits for the I/O to complete.
  1664. Arguments:
  1665. FileObject - pointer to file object for an endpoint.
  1666. DeviceObject - pointer to pointer to device object for an endpoint.
  1667. SendDatagramInformation - pointer to a buffer describing the
  1668. target of the datagram.
  1669. Buffer - Supplies the system virtual address of the buffer. The
  1670. buffer must be in nonpaged pool.
  1671. Length - Supplies the length of the buffer.
  1672. Return Value:
  1673. NTSTATUS - the status of the operation. Either the return value of
  1674. IoCallDriver, if the driver didn't accept the request, or the
  1675. value returned by the driver in the I/O status block.
  1676. --*/
  1677. {
  1678. PIRP irp;
  1679. PIO_STACK_LOCATION irpSp;
  1680. PTDI_REQUEST_KERNEL_SENDDG parameters;
  1681. KEVENT event;
  1682. IO_STATUS_BLOCK iosb;
  1683. PMDL mdl;
  1684. PAGED_CODE( );
  1685. //
  1686. // Allocate an IRP and fill in the service-independent parameters
  1687. // for the request.
  1688. //
  1689. irp = BuildCoreOfSyncIoRequest(
  1690. NULL,
  1691. FileObject,
  1692. &event,
  1693. &iosb,
  1694. DeviceObject
  1695. );
  1696. if ( irp == NULL ) {
  1697. //
  1698. // Unable to allocate an IRP. Fail the i/o.
  1699. //
  1700. return STATUS_INSUFF_SERVER_RESOURCES;
  1701. }
  1702. //
  1703. // Fill in the service-dependent parameters for the request.
  1704. //
  1705. irpSp = IoGetNextIrpStackLocation( irp );
  1706. parameters = (PTDI_REQUEST_KERNEL_SENDDG)&irpSp->Parameters;
  1707. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1708. irpSp->MinorFunction = TDI_SEND_DATAGRAM;
  1709. parameters->SendLength = Length;
  1710. parameters->SendDatagramInformation = SendDatagramInformation;
  1711. //
  1712. // The file system wants direct I/O. Allocate an MDL and lock the
  1713. // buffer into memory.
  1714. //
  1715. mdl = IoAllocateMdl(
  1716. Buffer,
  1717. Length,
  1718. FALSE,
  1719. FALSE,
  1720. irp // stores MDL address in irp->MdlAddress
  1721. );
  1722. if ( mdl == NULL ) {
  1723. //
  1724. // Unable to allocate an MDL. Fail the I/O.
  1725. //
  1726. IoFreeIrp( irp );
  1727. return STATUS_INSUFF_SERVER_RESOURCES;
  1728. }
  1729. try {
  1730. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1731. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1732. IoFreeIrp( irp );
  1733. IoFreeMdl( mdl );
  1734. return GetExceptionCode();
  1735. }
  1736. //
  1737. // Start the I/O, wait for it to complete, and return the final
  1738. // status.
  1739. //
  1740. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1741. } // SrvIssueSendDatagramRequest
  1742. NTSTATUS
  1743. SrvIssueSetClientProcessRequest (
  1744. IN PFILE_OBJECT FileObject,
  1745. IN PDEVICE_OBJECT *DeviceObject,
  1746. IN PCONNECTION Connection,
  1747. IN PVOID ClientSession,
  1748. IN PVOID ClientProcess
  1749. )
  1750. /*++
  1751. Routine Description:
  1752. This function issues an I/O request packet for a named pipe Set
  1753. Client Process file system control function. It builds an I/O
  1754. request packet, passes the IRP to the driver (using IoCallDriver),
  1755. and waits for the I/O to complete.
  1756. Arguments:
  1757. FileObject - pointer to file object for a pipe.
  1758. DeviceObject - pointer to pointer to device object for a pipe.
  1759. ClientSession - A unique identifier for the client's session with
  1760. the server. Assigned by the server.
  1761. ClientProcess - A unique identifier for the client process.
  1762. Assigned by the redirector.
  1763. Return Value:
  1764. NTSTATUS - the status of the operation. Either the return value of
  1765. IoCallDriver, if the driver didn't accept the request, or the
  1766. value returned by the driver in the I/O status block.
  1767. --*/
  1768. {
  1769. PIRP irp;
  1770. PIO_STACK_LOCATION irpSp;
  1771. FILE_PIPE_CLIENT_PROCESS_BUFFER_EX clientIdBuffer;
  1772. KEVENT event;
  1773. IO_STATUS_BLOCK iosb;
  1774. UNICODE_STRING unicodeString;
  1775. NTSTATUS status;
  1776. PAGED_CODE( );
  1777. //
  1778. // Set the client ID in the FSCTL buffer.
  1779. //
  1780. clientIdBuffer.ClientSession = ClientSession;
  1781. clientIdBuffer.ClientProcess = ClientProcess;
  1782. // Set ClientComputerName in the buffer
  1783. // The Rtl function terminates the string, so leave enough room
  1784. unicodeString.Buffer = clientIdBuffer.ClientComputerBuffer;
  1785. unicodeString.MaximumLength =
  1786. (USHORT) ((FILE_PIPE_COMPUTER_NAME_LENGTH+1) * sizeof(WCHAR));
  1787. status = RtlOemStringToUnicodeString( &unicodeString,
  1788. &Connection->OemClientMachineNameString,
  1789. FALSE );
  1790. if (!NT_SUCCESS(status)) {
  1791. // Set length to zero in case conversion fails
  1792. unicodeString.Length = 0;
  1793. }
  1794. clientIdBuffer.ClientComputerNameLength = unicodeString.Length;
  1795. //
  1796. // Allocate an IRP and fill in the service-independent parameters
  1797. // for the request.
  1798. //
  1799. irp = BuildCoreOfSyncIoRequest(
  1800. NULL,
  1801. FileObject,
  1802. &event,
  1803. &iosb,
  1804. DeviceObject
  1805. );
  1806. if ( irp == NULL ) {
  1807. //
  1808. // Unable to allocate an IRP. Fail the i/o.
  1809. //
  1810. return STATUS_INSUFF_SERVER_RESOURCES;
  1811. }
  1812. //
  1813. // Fill in the service-dependent parameters for the request.
  1814. //
  1815. irpSp = IoGetNextIrpStackLocation( irp );
  1816. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  1817. irpSp->MinorFunction = IRP_MN_KERNEL_CALL;
  1818. irpSp->Parameters.FileSystemControl.OutputBufferLength = 0;
  1819. irpSp->Parameters.FileSystemControl.InputBufferLength =
  1820. sizeof( clientIdBuffer );
  1821. irpSp->Parameters.FileSystemControl.FsControlCode =
  1822. FSCTL_PIPE_SET_CLIENT_PROCESS;
  1823. irp->MdlAddress = NULL;
  1824. irp->AssociatedIrp.SystemBuffer = &clientIdBuffer;
  1825. irp->Flags |= IRP_BUFFERED_IO;
  1826. irp->UserBuffer = NULL;
  1827. //
  1828. // Start the I/O, wait for it to complete, and return the final
  1829. // status.
  1830. //
  1831. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  1832. } // SrvIssueSetClientProcessRequest
  1833. NTSTATUS
  1834. SrvIssueSetEaRequest (
  1835. IN HANDLE FileHandle,
  1836. IN PVOID Buffer,
  1837. IN ULONG Length,
  1838. OUT PULONG EaErrorOffset OPTIONAL
  1839. )
  1840. /*++
  1841. Routine Description:
  1842. This function issues an I/O request packet for an EA set request.
  1843. It builds an I/O request packet, passes the IRP to the driver (using
  1844. IoCallDriver), and waits for the I/O to complete.
  1845. WARNING! The server must walk the list of EAs to set if it
  1846. comes directly from a client. This is because the file system
  1847. trusts that this list is legitimate and could run into problems
  1848. if the list has an error.
  1849. Arguments:
  1850. FileHandle - handle to a file open with FILE_WRITE_EA access.
  1851. Buffer - Supplies the system virtual address of the buffer. The
  1852. buffer must be in nonpaged pool.
  1853. Length - Supplies the length of the buffer.
  1854. EaErrorOffset - if not NULL, returns the offset into EaList of an
  1855. invalid EA, if any.
  1856. Return Value:
  1857. NTSTATUS - the status of the operation. Either the return value of
  1858. IoCallDriver, if the driver didn't accept the request, or the
  1859. value returned by the driver in the I/O status block.
  1860. --*/
  1861. {
  1862. NTSTATUS status;
  1863. PIRP irp;
  1864. PIO_STACK_LOCATION irpSp;
  1865. KEVENT event;
  1866. IO_STATUS_BLOCK iosb;
  1867. PDEVICE_OBJECT deviceObject;
  1868. PMDL mdl;
  1869. PAGED_CODE( );
  1870. //
  1871. // Allocate an IRP and fill in the service-independent parameters
  1872. // for the request.
  1873. //
  1874. irp = BuildCoreOfSyncIoRequest(
  1875. FileHandle,
  1876. NULL,
  1877. &event,
  1878. &iosb,
  1879. &deviceObject
  1880. );
  1881. if ( irp == NULL ) {
  1882. //
  1883. // Unable to allocate an IRP. Fail the i/o.
  1884. //
  1885. return STATUS_INSUFF_SERVER_RESOURCES;
  1886. }
  1887. //
  1888. // Fill in the service-dependent parameters for the request.
  1889. //
  1890. irpSp = IoGetNextIrpStackLocation( irp );
  1891. irpSp->MajorFunction = IRP_MJ_SET_EA;
  1892. irpSp->MinorFunction = 0;
  1893. irpSp->Parameters.SetEa.Length = Length;
  1894. irpSp->Flags = 0;
  1895. //
  1896. // The file system has been updated. Determine whether the driver
  1897. // wants buffered, direct, or "neither" I/O.
  1898. //
  1899. if ( (deviceObject->Flags & DO_BUFFERED_IO) != 0 ) {
  1900. //
  1901. // The file system wants buffered I/O. Pass the address of the
  1902. // "system buffer" in the IRP. Note that we don't want the buffer
  1903. // deallocated, nor do we want the I/O system to copy to a user
  1904. // buffer, so we don't set the corresponding flags in irp->Flags.
  1905. //
  1906. irp->AssociatedIrp.SystemBuffer = Buffer;
  1907. } else if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  1908. //
  1909. // The file system wants direct I/O. Allocate an MDL and lock the
  1910. // buffer into memory.
  1911. //
  1912. mdl = IoAllocateMdl(
  1913. Buffer,
  1914. Length,
  1915. FALSE,
  1916. FALSE,
  1917. irp // stores MDL address in irp->MdlAddress
  1918. );
  1919. if ( mdl == NULL ) {
  1920. //
  1921. // Unable to allocate an MDL. Fail the I/O.
  1922. //
  1923. IoFreeIrp( irp );
  1924. return STATUS_INSUFF_SERVER_RESOURCES;
  1925. }
  1926. try {
  1927. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  1928. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1929. IoFreeIrp( irp );
  1930. IoFreeMdl( mdl );
  1931. return GetExceptionCode();
  1932. }
  1933. } else {
  1934. //
  1935. // The file system wants "neither" I/O. Simply pass the address
  1936. // of the buffer.
  1937. //
  1938. // *** Note that if the file system decides to do this as buffered
  1939. // I/O, it will be wasting nonpaged pool, since our buffer is
  1940. // already in nonpaged pool. But since we're doing this as a
  1941. // synchronous request, the file system probably won't do that.
  1942. //
  1943. irp->UserBuffer = Buffer;
  1944. }
  1945. //
  1946. // Start the I/O, wait for it to complete, and return the final
  1947. // status.
  1948. //
  1949. status = StartIoAndWait( irp, deviceObject, &event, &iosb );
  1950. if ( ARGUMENT_PRESENT(EaErrorOffset) ) {
  1951. *EaErrorOffset = (ULONG)iosb.Information;
  1952. }
  1953. return status;
  1954. } // SrvIssueSetEaRequest
  1955. NTSTATUS
  1956. SrvIssueSetEventHandlerRequest (
  1957. IN PFILE_OBJECT FileObject,
  1958. IN PDEVICE_OBJECT *DeviceObject,
  1959. IN ULONG EventType,
  1960. IN PVOID EventHandler,
  1961. IN PVOID EventContext
  1962. )
  1963. /*++
  1964. Routine Description:
  1965. This function issues an I/O request packet for a TdiSetEventHandler
  1966. request. It builds an I/O request packet, passes the IRP to the
  1967. driver (using IoCallDriver), and waits for the I/O to complete.
  1968. Arguments:
  1969. FileObject - pointer to file object for a connection.
  1970. DeviceObject - pointer to pointer to device object for a connection.
  1971. EventType -
  1972. EventHandler -
  1973. EventContext -
  1974. Return Value:
  1975. NTSTATUS - the status of the operation. Either the return value of
  1976. IoCallDriver, if the driver didn't accept the request, or the
  1977. value returned by the driver in the I/O status block.
  1978. --*/
  1979. {
  1980. PIRP irp;
  1981. PIO_STACK_LOCATION irpSp;
  1982. PTDI_REQUEST_KERNEL_SET_EVENT parameters;
  1983. KEVENT event;
  1984. IO_STATUS_BLOCK iosb;
  1985. PDEVICE_OBJECT deviceObject = NULL;
  1986. PAGED_CODE( );
  1987. //
  1988. // Allocate an IRP and fill in the service-independent parameters
  1989. // for the request.
  1990. //
  1991. irp = BuildCoreOfSyncIoRequest(
  1992. NULL,
  1993. FileObject,
  1994. &event,
  1995. &iosb,
  1996. DeviceObject
  1997. );
  1998. if ( irp == NULL ) {
  1999. //
  2000. // Unable to allocate an IRP. Fail the I/O.
  2001. //
  2002. return STATUS_INSUFF_SERVER_RESOURCES;
  2003. }
  2004. //
  2005. // Fill in the service-dependent parameters for the request.
  2006. //
  2007. irpSp = IoGetNextIrpStackLocation( irp );
  2008. parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&irpSp->Parameters;
  2009. irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  2010. irpSp->MinorFunction = TDI_SET_EVENT_HANDLER;
  2011. parameters->EventType = EventType;
  2012. parameters->EventHandler = EventHandler;
  2013. parameters->EventContext = EventContext;
  2014. //
  2015. // Start the I/O, wait for it to complete, and return the final status.
  2016. //
  2017. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  2018. } // SrvIssueSetEventHandlerRequest
  2019. NTSTATUS
  2020. SrvIssueUnlockRequest (
  2021. IN PFILE_OBJECT FileObject,
  2022. IN PDEVICE_OBJECT *DeviceObject,
  2023. IN UCHAR UnlockOperation,
  2024. IN LARGE_INTEGER ByteOffset,
  2025. IN LARGE_INTEGER Length,
  2026. IN ULONG Key
  2027. )
  2028. /*++
  2029. Routine Description:
  2030. This function issues an I/O request packet for an unlock request.
  2031. It builds an I/O request packet, passes the IRP to the driver
  2032. (using IoCallDriver), and waits for the I/O to complete.
  2033. Arguments:
  2034. FileObject - Pointer to the file object.
  2035. DeviceObject - Pointer to pointer to the related device object.
  2036. UnlockOperation - the minor function code describing the unlock
  2037. operation -- IRP_MN_UNLOCK_SINGLE or IRP_MN_UNLOCK_ALL_BY_KEY.
  2038. StartingBlock - the block number of the beginning of the locked
  2039. range. Ignored if UnlockOperation is IRP_MN_UNLOCK_ALL_BY_KEY.
  2040. ByteOffset - the offset within block of the beginning of the locked
  2041. range. Ignored if UnlockOperation is IRP_MN_UNLOCK_ALL_BY_KEY.
  2042. Length - the length of the locked range. Ignored if UnlockOperation
  2043. is IRP_MN_UNLOCK_ALL_BY_KEY.
  2044. Key - the key value used to obtain the lock.
  2045. Return Value:
  2046. NTSTATUS - the status of the operation. Either the return value of
  2047. IoCallDriver, if the driver didn't accept the request, or the
  2048. value returned by the driver in the I/O status block.
  2049. --*/
  2050. {
  2051. PIRP irp;
  2052. PIO_STACK_LOCATION irpSp;
  2053. KEVENT event;
  2054. IO_STATUS_BLOCK iosb;
  2055. PFAST_IO_DISPATCH fastIoDispatch;
  2056. PAGED_CODE( );
  2057. //
  2058. // Try the turbo unlock path first.
  2059. //
  2060. fastIoDispatch = (*DeviceObject)->DriverObject->FastIoDispatch;
  2061. if ( fastIoDispatch != NULL ) {
  2062. if ( (UnlockOperation == IRP_MN_UNLOCK_SINGLE) &&
  2063. (fastIoDispatch->FastIoUnlockSingle != NULL) ) {
  2064. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastUnlocksAttempted );
  2065. if ( fastIoDispatch->FastIoUnlockSingle(
  2066. FileObject,
  2067. &ByteOffset,
  2068. &Length,
  2069. IoGetCurrentProcess(),
  2070. Key,
  2071. &iosb,
  2072. *DeviceObject
  2073. ) ) {
  2074. return iosb.Status;
  2075. }
  2076. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastUnlocksFailed );
  2077. } else if ( (UnlockOperation == IRP_MN_UNLOCK_ALL_BY_KEY) &&
  2078. (fastIoDispatch->FastIoUnlockAllByKey != NULL) ) {
  2079. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastUnlocksAttempted );
  2080. if ( fastIoDispatch->FastIoUnlockAllByKey(
  2081. FileObject,
  2082. IoGetCurrentProcess(),
  2083. Key,
  2084. &iosb,
  2085. *DeviceObject
  2086. ) ) {
  2087. return iosb.Status;
  2088. }
  2089. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastUnlocksFailed );
  2090. }
  2091. }
  2092. //
  2093. // The turbo path failed or was unavailable. Allocate an IRP and
  2094. // fill in the service-independent parameters for the request.
  2095. //
  2096. irp = BuildCoreOfSyncIoRequest(
  2097. NULL,
  2098. FileObject,
  2099. &event,
  2100. &iosb,
  2101. DeviceObject
  2102. );
  2103. if ( irp == NULL ) {
  2104. //
  2105. // Unable to allocate an IRP. Fail the i/o.
  2106. //
  2107. return STATUS_INSUFF_SERVER_RESOURCES;
  2108. }
  2109. //
  2110. // Fill in the service-dependent parameters for the request.
  2111. //
  2112. irpSp = IoGetNextIrpStackLocation( irp );
  2113. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  2114. irpSp->MinorFunction = UnlockOperation;
  2115. irpSp->Parameters.LockControl.Length = &Length;
  2116. irpSp->Parameters.LockControl.Key = Key;
  2117. irpSp->Parameters.LockControl.ByteOffset = ByteOffset;
  2118. //
  2119. // Start the I/O, wait for it to complete, and return the final
  2120. // status.
  2121. //
  2122. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  2123. } // SrvIssueUnlockRequest
  2124. NTSTATUS
  2125. SrvIssueUnlockSingleRequest (
  2126. IN PFILE_OBJECT FileObject,
  2127. IN PDEVICE_OBJECT *DeviceObject,
  2128. IN LARGE_INTEGER ByteOffset,
  2129. IN LARGE_INTEGER Length,
  2130. IN ULONG Key
  2131. )
  2132. /*++
  2133. Routine Description:
  2134. This function issues an I/O request packet for an unlock single request.
  2135. It builds an I/O request packet, passes the IRP to the driver
  2136. (using IoCallDriver), and waits for the I/O to complete.
  2137. Arguments:
  2138. FileObject - Pointer to the file object.
  2139. DeviceObject - Pointer to pointer to the related device object.
  2140. StartingBlock - the block number of the beginning of the locked
  2141. range. Ignored if UnlockOperation is IRP_MN_UNLOCK_ALL_BY_KEY.
  2142. ByteOffset - the offset within block of the beginning of the locked
  2143. range. Ignored if UnlockOperation is IRP_MN_UNLOCK_ALL_BY_KEY.
  2144. Length - the length of the locked range. Ignored if UnlockOperation
  2145. is IRP_MN_UNLOCK_ALL_BY_KEY.
  2146. Key - the key value used to obtain the lock.
  2147. Return Value:
  2148. NTSTATUS - the status of the operation. Either the return value of
  2149. IoCallDriver, if the driver didn't accept the request, or the
  2150. value returned by the driver in the I/O status block.
  2151. --*/
  2152. {
  2153. PIRP irp;
  2154. PIO_STACK_LOCATION irpSp;
  2155. KEVENT event;
  2156. IO_STATUS_BLOCK iosb;
  2157. PAGED_CODE( );
  2158. //
  2159. // Allocate an IRP and fill in the service-independent
  2160. // parameters for the request.
  2161. //
  2162. irp = BuildCoreOfSyncIoRequest(
  2163. NULL,
  2164. FileObject,
  2165. &event,
  2166. &iosb,
  2167. DeviceObject
  2168. );
  2169. if ( irp == NULL ) {
  2170. //
  2171. // Unable to allocate an IRP. Fail the i/o.
  2172. //
  2173. return STATUS_INSUFF_SERVER_RESOURCES;
  2174. }
  2175. //
  2176. // Fill in the service-dependent parameters for the request.
  2177. //
  2178. irpSp = IoGetNextIrpStackLocation( irp );
  2179. irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
  2180. irpSp->MinorFunction = IRP_MN_UNLOCK_SINGLE;
  2181. irpSp->Parameters.LockControl.Length = &Length;
  2182. irpSp->Parameters.LockControl.Key = Key;
  2183. irpSp->Parameters.LockControl.ByteOffset = ByteOffset;
  2184. //
  2185. // Start the I/O, wait for it to complete, and return the final
  2186. // status.
  2187. //
  2188. return StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  2189. } // SrvIssueUnlockSingleRequest
  2190. NTSTATUS
  2191. SrvIssueWaitForOplockBreak (
  2192. IN HANDLE FileHandle,
  2193. PWAIT_FOR_OPLOCK_BREAK WaitForOplockBreak
  2194. )
  2195. /*++
  2196. Routine Description:
  2197. This function issues an I/O request packet for a wait for oplock
  2198. break request.
  2199. It builds an I/O request packet, passes the IRP to the driver
  2200. (using IoCallDriver), and waits for the I/O to complete.
  2201. Arguments:
  2202. FileHandle - handle to a file.
  2203. WaitForOplockBreak - Context information for this wait for oplock break.
  2204. Return Value:
  2205. NTSTATUS - the status of the operation. Either the return value of
  2206. IoCallDriver, if the driver didn't accept the request, or the
  2207. value returned by the driver in the I/O status block.
  2208. --*/
  2209. {
  2210. PIRP irp;
  2211. PIO_STACK_LOCATION irpSp;
  2212. KEVENT event;
  2213. IO_STATUS_BLOCK iosb;
  2214. PDEVICE_OBJECT deviceObject;
  2215. NTSTATUS status;
  2216. KIRQL oldIrql;
  2217. PAGED_CODE( );
  2218. //
  2219. // Allocate an IRP and fill in the service-independent parameters
  2220. // for the request.
  2221. //
  2222. irp = BuildCoreOfSyncIoRequest(
  2223. FileHandle,
  2224. NULL,
  2225. &event,
  2226. &iosb,
  2227. &deviceObject
  2228. );
  2229. if (irp == NULL) {
  2230. //
  2231. // Unable to allocate an IRP. Fail the i/o.
  2232. //
  2233. return STATUS_INSUFF_SERVER_RESOURCES;
  2234. }
  2235. //
  2236. // Fill in the service-dependent parameters for the request.
  2237. //
  2238. irpSp = IoGetNextIrpStackLocation( irp );
  2239. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  2240. irpSp->MinorFunction = 0;
  2241. irpSp->Parameters.FileSystemControl.OutputBufferLength = 0;
  2242. irpSp->Parameters.FileSystemControl.InputBufferLength = 0;
  2243. irpSp->Parameters.FileSystemControl.FsControlCode =
  2244. FSCTL_OPLOCK_BREAK_NOTIFY;
  2245. //
  2246. // Queue the WaitForOplockBreak block on the global list.
  2247. //
  2248. // We must hold the lock that protects wait for oplock breaks
  2249. // from the time we queue this wait for oplock break on the global
  2250. // list, to the time the IRP has actually been submitted. Otherwise
  2251. // the scavenger might wake up and attempt to cancel an IRP that
  2252. // has not yet been submitted.
  2253. //
  2254. WaitForOplockBreak->Irp = irp;
  2255. ACQUIRE_LOCK( &SrvOplockBreakListLock );
  2256. SrvInsertTailList(
  2257. &SrvWaitForOplockBreakList,
  2258. &WaitForOplockBreak->ListEntry
  2259. );
  2260. //
  2261. // The following code is a duplicate of the code from StartIoAndWait().
  2262. //
  2263. // Start the I/O, wait for it to complete, and return the final
  2264. // status.
  2265. //
  2266. //
  2267. // Queue the IRP to the thread and pass it to the driver.
  2268. //
  2269. IoQueueThreadIrp( irp );
  2270. status = IoCallDriver( deviceObject, irp );
  2271. RELEASE_LOCK( &SrvOplockBreakListLock );
  2272. //
  2273. // If necessary, wait for the I/O to complete.
  2274. //
  2275. if ( status == STATUS_PENDING ) {
  2276. KeWaitForSingleObject(
  2277. &event,
  2278. UserRequest,
  2279. KernelMode, // don't let stack be paged -- event is on stack!
  2280. FALSE,
  2281. NULL
  2282. );
  2283. }
  2284. //
  2285. // If the request was successfully queued, get the final I/O status.
  2286. //
  2287. if ( NT_SUCCESS(status) ) {
  2288. status = iosb.Status;
  2289. }
  2290. return status;
  2291. } // SrvIssueWaitForOplockBreak
  2292. VOID
  2293. SrvQuerySendEntryPoint(
  2294. IN PFILE_OBJECT FileObject,
  2295. IN PDEVICE_OBJECT *DeviceObject,
  2296. IN ULONG IoControlCode,
  2297. IN PVOID *EntryPoint
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. This function queries the transport for its send entry point.
  2302. Arguments:
  2303. FileObject - pointer to file object for a connection.
  2304. DeviceObject - pointer to pointer to device object for a connection.
  2305. EntryPoint -
  2306. Return Value:
  2307. NTSTATUS - the status of the operation. Either the return value of
  2308. IoCallDriver, if the driver didn't accept the request, or the
  2309. value returned by the driver in the I/O status block.
  2310. --*/
  2311. {
  2312. PIRP irp;
  2313. PIO_STACK_LOCATION irpSp;
  2314. KEVENT event;
  2315. IO_STATUS_BLOCK iosb;
  2316. NTSTATUS status;
  2317. PAGED_CODE( );
  2318. //
  2319. // Allocate an IRP and fill in the service-independent parameters
  2320. // for the request.
  2321. //
  2322. irp = BuildCoreOfSyncIoRequest(
  2323. NULL,
  2324. FileObject,
  2325. &event,
  2326. &iosb,
  2327. DeviceObject
  2328. );
  2329. if ( irp == NULL ) {
  2330. //
  2331. // Unable to allocate an IRP. Fail the I/O.
  2332. //
  2333. *EntryPoint = NULL;
  2334. return;
  2335. }
  2336. //
  2337. // Fill in the service-dependent parameters for the request.
  2338. //
  2339. irpSp = IoGetNextIrpStackLocation( irp );
  2340. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  2341. irpSp->MinorFunction = 0;
  2342. irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
  2343. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = EntryPoint;
  2344. //
  2345. // Start the I/O, wait for it to complete, and return the final status.
  2346. //
  2347. status = StartIoAndWait( irp, *DeviceObject, &event, &iosb );
  2348. if ( !NT_SUCCESS(status) ) {
  2349. *EntryPoint = NULL;
  2350. }
  2351. return;
  2352. } // SrvQuerySendEntryPoint
  2353. #ifdef INCLUDE_SMB_IFMODIFIED
  2354. NTSTATUS
  2355. SrvIssueQueryUsnInfoRequest (
  2356. IN PRFCB Rfcb,
  2357. IN BOOLEAN SubmitClose,
  2358. OUT PLARGE_INTEGER Usn,
  2359. OUT PLARGE_INTEGER FileRefNumber
  2360. )
  2361. /*++
  2362. Routine Description:
  2363. This function issues an I/O request packet for a USN query or close
  2364. request. It builds an I/O request packet, passes the IRP to the
  2365. driver (using IoCallDriver), and waits for the I/O to complete.
  2366. Arguments:
  2367. Rfcb - pointer to handle that we're querying
  2368. SubmitClose - do we submit a close USN record or just simply a USN query?
  2369. Usn & FileRefNumber - USN record results
  2370. Return Value:
  2371. NTSTATUS - the status of the operation. Either the return value of
  2372. IoCallDriver, if the driver didn't accept the request, or the
  2373. value returned by the driver in the I/O status block.
  2374. --*/
  2375. {
  2376. PIRP irp = NULL;
  2377. PMDL mdl = NULL;
  2378. PUSN_RECORD usnRecord = NULL;
  2379. PIO_STACK_LOCATION irpSp;
  2380. KEVENT event;
  2381. IO_STATUS_BLOCK iosb;
  2382. PDEVICE_OBJECT deviceObject;
  2383. NTSTATUS status;
  2384. ULONG sizeRequired;
  2385. PAGED_CODE( );
  2386. //
  2387. // if the share doesn't have a USN log, don't bother with this request
  2388. //
  2389. Usn->QuadPart = 0;
  2390. FileRefNumber->QuadPart = 0;
  2391. if (! Rfcb->Lfcb->TreeConnect->Share->UsnCapable ) {
  2392. return STATUS_SUCCESS;
  2393. }
  2394. deviceObject = Rfcb->Lfcb->DeviceObject;
  2395. //
  2396. // Allocate an IRP and fill in the service-independent parameters
  2397. // for the request.
  2398. //
  2399. irp = BuildCoreOfSyncIoRequest(
  2400. NULL,
  2401. Rfcb->Lfcb->FileObject,
  2402. &event,
  2403. &iosb,
  2404. &deviceObject
  2405. );
  2406. if ( irp == NULL ) {
  2407. //
  2408. // Unable to allocate an IRP. Fail the I/O.
  2409. //
  2410. status = STATUS_INSUFF_SERVER_RESOURCES;
  2411. goto exitGetUsn;
  2412. }
  2413. // if the client opened the file with the short name, we could end up
  2414. // having a buffer that's woefully too small. We'll bump the
  2415. // allocation up to a large amount so that we don't have to
  2416. // go back and do it again.
  2417. sizeRequired = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
  2418. sizeRequired += sizeof( USN_RECORD );
  2419. sizeRequired = QuadAlign( sizeRequired );
  2420. usnRecord = ALLOCATE_NONPAGED_POOL( sizeRequired, BlockTypeDataBuffer );
  2421. if ( usnRecord == NULL) {
  2422. IF_DEBUG(ERRORS) {
  2423. KdPrint(( "SrvGetUsnInfoForFile: unable to alloc block of size %u for handle 0x%x\n",
  2424. sizeRequired, Rfcb->Lfcb->FileObject ));
  2425. }
  2426. status = STATUS_INSUFF_SERVER_RESOURCES;
  2427. goto exitGetUsn;
  2428. }
  2429. //
  2430. // Fill in the service-dependent parameters for the request.
  2431. //
  2432. irpSp = IoGetNextIrpStackLocation( irp );
  2433. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  2434. irpSp->MinorFunction = 0;
  2435. irpSp->Parameters.FileSystemControl.FsControlCode = SubmitClose ? FSCTL_WRITE_USN_CLOSE_RECORD : FSCTL_READ_FILE_USN_DATA;
  2436. irpSp->Parameters.FileSystemControl.OutputBufferLength = sizeRequired;
  2437. irpSp->Parameters.FileSystemControl.InputBufferLength = 0;
  2438. irpSp->Parameters.FileSystemControl.Type3InputBuffer = NULL;
  2439. irp->MdlAddress = NULL;
  2440. irp->AssociatedIrp.SystemBuffer = NULL;
  2441. irp->UserBuffer = usnRecord;
  2442. //
  2443. // The file system has been updated. Determine whether the driver wants
  2444. // buffered, direct, or "neither" I/O.
  2445. //
  2446. if ( (deviceObject->Flags & DO_BUFFERED_IO) != 0 ) {
  2447. //
  2448. // The file system wants buffered I/O. Pass the address of the
  2449. // "system buffer" in the IRP. Note that we don't want the buffer
  2450. // deallocated, nor do we want the I/O system to copy to a user
  2451. // buffer, so we don't set the corresponding flags in irp->Flags.
  2452. //
  2453. irp->AssociatedIrp.SystemBuffer = usnRecord;
  2454. } else if ( (deviceObject->Flags & DO_DIRECT_IO) != 0 ) {
  2455. //
  2456. // The file system wants direct I/O. Allocate an MDL and lock the
  2457. // buffer into memory.
  2458. //
  2459. mdl = IoAllocateMdl(
  2460. usnRecord,
  2461. sizeRequired,
  2462. FALSE,
  2463. FALSE,
  2464. irp // stores MDL address in irp->MdlAddress
  2465. );
  2466. if ( mdl == NULL ) {
  2467. //
  2468. // Unable to allocate an MDL. Fail the I/O.
  2469. //
  2470. status = STATUS_INSUFF_SERVER_RESOURCES;
  2471. goto exitGetUsn;
  2472. }
  2473. try {
  2474. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  2475. } except( EXCEPTION_EXECUTE_HANDLER ) {
  2476. IoFreeIrp( irp );
  2477. MmUnlockPages( mdl );
  2478. IoFreeMdl( mdl );
  2479. irp = NULL;
  2480. status = GetExceptionCode();
  2481. goto exitGetUsn;
  2482. }
  2483. } else {
  2484. //
  2485. // The file system wants "neither" I/O. Simply pass the address
  2486. // of the buffer.
  2487. //
  2488. // *** Note that if the file system decides to do this as buffered
  2489. // I/O, it will be wasting nonpaged pool, since our buffer is
  2490. // already in nonpaged pool. But since we're doing this as a
  2491. // synchronous request, the file system probably won't do that.
  2492. //
  2493. irp->UserBuffer = usnRecord;
  2494. }
  2495. //
  2496. // Start the I/O, wait for it to complete, and return the final status.
  2497. //
  2498. status = StartIoAndWait( irp, deviceObject, &event, &iosb );
  2499. irp = NULL; // it was freed by call to IoCallDriver
  2500. if (NT_SUCCESS(status)) {
  2501. status = iosb.Status;
  2502. }
  2503. if (NT_SUCCESS(status)) {
  2504. Usn->QuadPart = usnRecord->Usn;
  2505. FileRefNumber->QuadPart = usnRecord->FileReferenceNumber;
  2506. } else {
  2507. ASSERT( status != STATUS_MORE_PROCESSING_REQUIRED );
  2508. ASSERT( status != STATUS_PENDING );
  2509. IF_DEBUG(ERRORS) {
  2510. KdPrint(( "SrvGetUsnInfoForFile: Query USN info failed: 0x%X for handle %u\n",
  2511. status, Rfcb->Lfcb->FileObject ));
  2512. }
  2513. if (status == STATUS_JOURNAL_NOT_ACTIVE ||
  2514. status == STATUS_INVALID_DEVICE_REQUEST) {
  2515. Rfcb->Lfcb->TreeConnect->Share->UsnCapable = FALSE;
  2516. }
  2517. }
  2518. exitGetUsn:
  2519. if (irp != NULL) {
  2520. IoFreeIrp( irp );
  2521. }
  2522. if ( usnRecord != NULL ) {
  2523. DEALLOCATE_NONPAGED_POOL( usnRecord );
  2524. }
  2525. return status;
  2526. } // SrvIssueQueryUsnInfoRequest
  2527. #endif // def INCLUDE_SMB_IFMODIFIED