Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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