ReactOS 0.4.15-dev-8138-g1e75ea8
iofunc.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/iofunc.c
5 * PURPOSE: Generic I/O Functions that build IRPs for various operations
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Gunnar Dalsnes
8 * Filip Navara (navaraf@reactos.org)
9 * Pierre Schweitzer (pierre@reactos.org)
10 */
11
12/* INCLUDES *****************************************************************/
13
14#include <ntoskrnl.h>
15#include <ioevent.h>
16#define NDEBUG
17#include <debug.h>
18#include "internal/io_i.h"
19
22
23/* PRIVATE FUNCTIONS *********************************************************/
24
25VOID
30 IN PKEVENT LocalEvent OPTIONAL)
31{
32 PAGED_CODE();
33 IOTRACE(IO_API_DEBUG, "IRP: %p. FO: %p\n", Irp, FileObject);
34
35 if (Irp)
36 {
37 /* Check if we had a buffer */
38 if (Irp->AssociatedIrp.SystemBuffer)
39 {
40 /* Free it */
41 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
42 }
43
44 /* Free the mdl */
45 if (Irp->MdlAddress) IoFreeMdl(Irp->MdlAddress);
46
47 /* Free the IRP */
49 }
50
51 /* Check if we had a file lock */
52 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
53 {
54 /* Release it */
56 }
57
58 /* Check if we had an event */
60
61 /* Check if we had a local event */
62 if (LocalEvent) ExFreePool(LocalEvent);
63
64 /* Derefenrce the FO */
66}
67
72 IN PIRP Irp,
74 IN PIO_STATUS_BLOCK KernelIosb,
76{
77 NTSTATUS FinalStatus = SynchStatus;
78 PAGED_CODE();
79 IOTRACE(IO_API_DEBUG, "IRP: %p. Status: %lx\n", Irp, SynchStatus);
80
81 /* Make sure the IRP was completed, but returned pending */
82 if (FinalStatus == STATUS_PENDING)
83 {
84 /* Wait for the IRP */
85 FinalStatus = KeWaitForSingleObject(Event,
88 FALSE,
89 NULL);
90 if (FinalStatus == STATUS_USER_APC)
91 {
92 /* Abort the request */
94 }
95
96 /* Set the final status */
97 FinalStatus = KernelIosb->Status;
98 }
99
100 /* Wrap potential user-mode write in SEH */
102 {
103 *IoStatusBlock = *KernelIosb;
104 }
106 {
107 /* Get the exception code */
108 FinalStatus = _SEH2_GetExceptionCode();
109 }
110 _SEH2_END;
111
112 /* Free the event and return status */
114 return FinalStatus;
115}
116
118NTAPI
120 IN PIRP Irp,
122 IN BOOLEAN Deferred,
124 IN BOOLEAN SynchIo,
125 IN IOP_TRANSFER_TYPE TransferType)
126{
128 PKNORMAL_ROUTINE NormalRoutine;
129 PVOID NormalContext = NULL;
131 PAGED_CODE();
132 IOTRACE(IO_API_DEBUG, "IRP: %p. DO: %p. FO: %p\n",
134
135 /* Queue the IRP */
137
138 /* Update operation counts */
139 IopUpdateOperationCount(TransferType);
140
141 /* Call the driver */
143
144 /* Check if we're optimizing this case */
145 if (Deferred)
146 {
147 /* We are! Check if the IRP wasn't completed */
148 if (Status != STATUS_PENDING)
149 {
150 /* Complete it ourselves */
151 NormalRoutine = NULL;
152 NormalContext = NULL;
153 ASSERT(!Irp->PendingReturned);
155 IopCompleteRequest(&Irp->Tail.Apc,
156 &NormalRoutine,
157 &NormalContext,
158 (PVOID*)&FileObject,
159 &NormalContext);
161 }
162 }
163
164 /* Check if this was synch I/O */
165 if (SynchIo)
166 {
167 /* Make sure the IRP was completed, but returned pending */
168 if (Status == STATUS_PENDING)
169 {
170 /* Wait for the IRP */
172 Executive,
174 (FileObject->Flags &
175 FO_ALERTABLE_IO) != 0,
176 NULL);
178 {
179 /* Abort the request */
181 }
182
183 /* Set the final status */
184 Status = FileObject->FinalStatus;
185 }
186
187 /* Release the file lock */
189 }
190
191 /* Return status */
192 return Status;
193}
194
196NTAPI
199 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
200 IN PVOID UserApcContext OPTIONAL,
207 IN BOOLEAN IsDevIoCtl)
208{
212 PIRP Irp;
213 PIO_STACK_LOCATION StackPtr;
214 PKEVENT EventObject = NULL;
215 BOOLEAN LockedForSynch = FALSE;
216 ULONG AccessType;
222
223 PAGED_CODE();
224
225 IOTRACE(IO_CTL_DEBUG, "Handle: %p. CTL: %lx. Type: %lx\n",
226 DeviceHandle, IoControlCode, IsDevIoCtl);
227
228 /* Get the access type */
230
231 /* Check if we came from user mode */
233 {
235 {
236 /* Probe the status block */
238
239 /* Check if this is buffered I/O */
240 if (AccessType == METHOD_BUFFERED)
241 {
242 /* Check if we have an output buffer */
243 if (OutputBuffer)
244 {
245 /* Probe the output buffer */
248 sizeof(CHAR));
249 }
250 else
251 {
252 /* Make sure the caller can't fake this as we depend on this */
254 }
255 }
256
257 /* Check if we we have an input buffer I/O */
258 if (AccessType != METHOD_NEITHER)
259 {
260 /* Check if we have an input buffer */
261 if (InputBuffer)
262 {
263 /* Probe the input buffer */
265 }
266 else
267 {
268 /* Make sure the caller can't fake this as we depend on this */
270 }
271 }
272 }
274 {
275 /* Return the exception code */
277 }
278 _SEH2_END;
279 }
280
281 /* Don't check for access rights right now, KernelMode can do anything */
283 0,
286 (PVOID*)&FileObject,
288 if (!NT_SUCCESS(Status)) return Status;
289
290 /* Can't use an I/O completion port and an APC at the same time */
291 if ((FileObject->CompletionContext) && (UserApcRoutine))
292 {
293 /* Fail */
296 }
297
298 /* Check if we from user mode */
300 {
301 /* Get the access mask */
302 DesiredAccess = (ACCESS_MASK)((IoControlCode >> 14) & 3);
303
304 /* Check if we can open it */
306 (HandleInformation.GrantedAccess & DesiredAccess) != DesiredAccess)
307 {
308 /* Dereference the file object and fail */
311 }
312 }
313
314 /* Check for an event */
315 if (Event)
316 {
317 /* Reference it */
322 (PVOID*)&EventObject,
323 NULL);
324 if (!NT_SUCCESS(Status))
325 {
326 /* Dereference the file object and fail */
328 return Status;
329 }
330
331 /* Clear it */
332 KeClearEvent(EventObject);
333 }
334
335 /* Check if this is a file that was opened for Synch I/O */
336 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
337 {
338 /* Lock it */
340 if (Status != STATUS_SUCCESS)
341 {
342 if (EventObject) ObDereferenceObject(EventObject);
344 return Status;
345 }
346
347 /* Remember to unlock later */
348 LockedForSynch = TRUE;
349 }
350
351 /* Check if this is a direct open or not */
353 {
354 /* It's a direct open, get the attached device */
356 }
357 else
358 {
359 /* Otherwise get the related device */
361 }
362
363 /* If this is a device I/O, try to do it with FastIO path */
364 if (IsDevIoCtl)
365 {
366 PFAST_IO_DISPATCH FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
367
368 /* Check whether FSD is FastIO aware and provide an appropriate routine */
370 {
371 IO_STATUS_BLOCK KernelIosb;
372
373 /* If we have an output buffer coming from usermode */
375 {
376 /* Probe it according to its usage */
378 {
379 if (AccessType == METHOD_IN_DIRECT)
380 {
382 }
383 else if (AccessType == METHOD_OUT_DIRECT)
384 {
386 }
387 }
389 {
390 /* Cleanup after exception and return */
392
393 /* Return the exception code */
395 }
396 _SEH2_END;
397 }
398
399 /* If we are dismounting a volume, increase the dismount count */
401 {
402 InterlockedIncrement((PLONG)&SharedUserData->DismountCount);
403 }
404
405 /* Call the FSD */
407 TRUE,
413 &KernelIosb,
415 {
416 IO_COMPLETION_CONTEXT CompletionInfo = { NULL, NULL };
417
418 /* Write the IOSB back */
420 {
421 *IoStatusBlock = KernelIosb;
422
423 }
425 {
426 KernelIosb.Status = _SEH2_GetExceptionCode();
427 }
428 _SEH2_END;
429
430 /* Backup our complete context in case it exists */
431 if (FileObject->CompletionContext)
432 {
433 CompletionInfo = *(FileObject->CompletionContext);
434 }
435
436 /* If we had an event, signal it */
437 if (Event)
438 {
439 KeSetEvent(EventObject, IO_NO_INCREMENT, FALSE);
440 ObDereferenceObject(EventObject);
441 }
442
443 /* If FO was locked, unlock it */
444 if (LockedForSynch)
445 {
447 }
448
449 /* Set completion if required */
450 if (CompletionInfo.Port != NULL && UserApcContext != NULL)
451 {
452 if (!NT_SUCCESS(IoSetIoCompletion(CompletionInfo.Port,
453 CompletionInfo.Key,
454 UserApcContext,
455 KernelIosb.Status,
456 KernelIosb.Information,
457 TRUE)))
458 {
460 }
461 }
462
463 /* We're done with FastIO! */
465 return KernelIosb.Status;
466 }
467 }
468 }
469
470 /* Clear the event */
471 KeClearEvent(&FileObject->Event);
472
473 /* Allocate IRP */
474 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
475 if (!Irp) return IopCleanupFailedIrp(FileObject, EventObject, NULL);
476
477 /* Setup the IRP */
478 Irp->UserIosb = IoStatusBlock;
479 Irp->UserEvent = EventObject;
480 Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
481 Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
482 Irp->Cancel = FALSE;
483 Irp->CancelRoutine = NULL;
484 Irp->PendingReturned = FALSE;
485 Irp->RequestorMode = PreviousMode;
486 Irp->MdlAddress = NULL;
487 Irp->AssociatedIrp.SystemBuffer = NULL;
488 Irp->Flags = 0;
489 Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
490 Irp->Tail.Overlay.OriginalFileObject = FileObject;
491 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
492
493 /* Set stack location settings */
494 StackPtr = IoGetNextIrpStackLocation(Irp);
495 StackPtr->FileObject = FileObject;
496 StackPtr->MajorFunction = IsDevIoCtl ?
499 StackPtr->MinorFunction = 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
500 StackPtr->Control = 0;
501 StackPtr->Flags = 0;
502 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
503
504 /* Set the IOCTL Data */
505 StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
506 StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
507 StackPtr->Parameters.DeviceIoControl.OutputBufferLength =
509
511
512 /* Handle the Methods */
513 switch (AccessType)
514 {
515 /* Buffered I/O */
516 case METHOD_BUFFERED:
517
518 /* Enter SEH for allocations */
520 {
521 /* Select the right Buffer Length */
524
525 /* Make sure there is one */
526 if (BufferLength)
527 {
528 /* Allocate the System Buffer */
529 Irp->AssociatedIrp.SystemBuffer =
533
534 /* Check if we got a buffer */
535 if (InputBuffer)
536 {
537 /* Copy into the System Buffer */
538 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
541 }
542
543 /* Write the flags */
545 if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION;
546
547 /* Save the Buffer */
548 Irp->UserBuffer = OutputBuffer;
549 }
550 else
551 {
552 /* Clear the Flags and Buffer */
553 Irp->UserBuffer = NULL;
554 }
555 }
557 {
558 /* Cleanup after exception and return */
561 }
562 _SEH2_END;
563 break;
564
565 /* Direct I/O */
566 case METHOD_IN_DIRECT:
568
569 /* Enter SEH */
571 {
572 /* Check if we got an input buffer */
574 {
575 /* Allocate the System Buffer */
576 Irp->AssociatedIrp.SystemBuffer =
580
581 /* Copy into the System Buffer */
582 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
585
586 /* Write the flags */
588 }
589
590 /* Check if we got an output buffer */
592 {
593 /* Allocate the System Buffer */
594 Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
596 FALSE,
597 FALSE,
598 Irp);
599 if (!Irp->MdlAddress)
600 {
601 /* Raise exception we'll catch */
603 }
604
605 /* Do the probe */
606 MmProbeAndLockPages(Irp->MdlAddress,
608 (AccessType == METHOD_IN_DIRECT) ?
610 }
611 }
613 {
614 /* Cleanup after exception and return */
617 }
618 _SEH2_END;
619 break;
620
621 case METHOD_NEITHER:
622
623 /* Just save the Buffer */
624 Irp->UserBuffer = OutputBuffer;
625 StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
626 }
627
628 /* Use deferred completion for FS I/O */
629 if (!IsDevIoCtl)
630 {
632 }
633
634 /* If we are dismounting a volume, increaase the dismount count */
636 {
637 InterlockedIncrement((PLONG)&SharedUserData->DismountCount);
638 }
639
640 /* Perform the call */
642 Irp,
644 !IsDevIoCtl,
646 LockedForSynch,
648}
649
651NTAPI
658{
660 PIRP Irp;
662 PIO_STACK_LOCATION StackPtr;
663 BOOLEAN LocalEvent = FALSE;
666 PAGED_CODE();
667 IOTRACE(IO_API_DEBUG, "Handle: %p. CTL: %lx. Type: %lx\n",
669
670 /* Reference the object */
672
673 /* Check if this is a file that was opened for Synch I/O */
674 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
675 {
676 /* Lock it */
678
679 /* Use File Object event */
680 KeClearEvent(&FileObject->Event);
681 }
682 else
683 {
684 /* Use local event */
686 LocalEvent = TRUE;
687 }
688
689 /* Get the Device Object */
691
692 /* Allocate the IRP */
693 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
695
696 /* Set the IRP */
697 Irp->Tail.Overlay.OriginalFileObject = FileObject;
698 Irp->RequestorMode = KernelMode;
699 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
700 Irp->UserIosb = &IoStatusBlock;
701 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
702 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
703 Irp->Flags |= IRP_BUFFERED_IO;
704 Irp->AssociatedIrp.SystemBuffer = Information;
705 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
706
707 /* Set the Stack Data */
708 StackPtr = IoGetNextIrpStackLocation(Irp);
711 StackPtr->FileObject = FileObject;
712
713 /* Check which type this is */
714 if (File)
715 {
716 /* Set Parameters */
717 StackPtr->Parameters.QueryFile.FileInformationClass = InformationClass;
718 StackPtr->Parameters.QueryFile.Length = Length;
719 }
720 else
721 {
722 /* Set Parameters */
723 StackPtr->Parameters.QueryVolume.FsInformationClass = InformationClass;
724 StackPtr->Parameters.QueryVolume.Length = Length;
725 }
726
727 /* Queue the IRP */
729
730 /* Call the Driver */
732
733 /* Check if this was synch I/O */
734 if (!LocalEvent)
735 {
736 /* Check if the request is pending */
737 if (Status == STATUS_PENDING)
738 {
739 /* Wait on the file object */
741 Executive,
743 (FileObject->Flags &
744 FO_ALERTABLE_IO) != 0,
745 NULL);
746 if (Status == STATUS_ALERTED)
747 {
748 /* Abort the operation */
750 }
751
752 /* Get the final status */
753 Status = FileObject->FinalStatus;
754 }
755
756 /* Release the file lock */
758 }
759 else if (Status == STATUS_PENDING)
760 {
761 /* Wait on the local event and get the final status */
763 Executive,
765 FALSE,
766 NULL);
768 }
769
770 /* Return the Length and Status. ReturnedLength is NOT optional */
772 return Status;
773}
774
776NTAPI
779 IN FILE_INFORMATION_CLASS FileInfoClass,
782{
783 PIRP Irp;
789
790 PAGED_CODE();
791
792 /* Allocate an IRP */
795 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
796 if (Irp == NULL)
797 {
800 }
801
802 /* Init event */
804
805 /* Setup the IRP */
806 Irp->UserIosb = &IoStatusBlock;
807 Irp->UserEvent = &Event;
808 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
809 Irp->RequestorMode = KernelMode;
810 Irp->AssociatedIrp.SystemBuffer = Buffer;
812 Irp->Tail.Overlay.OriginalFileObject = FileObject;
813 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
814
816 Stack->MajorFunction = IRP_MJ_QUERY_INFORMATION;
817 Stack->FileObject = FileObject;
818 Stack->Parameters.QueryFile.FileInformationClass = FileInfoClass;
819 Stack->Parameters.QueryFile.Length = Length;
820
821
822 /* Queue the IRP */
824
825 /* Call the driver */
827 if (Status == STATUS_PENDING)
828 {
831 }
832
834 return Status;
835}
836
838NTAPI
841{
845
846 PAGED_CODE();
847
848 /* Try to do it the fast way if possible */
850 if (DeviceObject->DriverObject->FastIoDispatch != NULL &&
851 DeviceObject->DriverObject->FastIoDispatch->FastIoQueryBasicInfo != NULL &&
852 DeviceObject->DriverObject->FastIoDispatch->FastIoQueryBasicInfo(FileObject,
853 ((FileObject->Flags & FO_SYNCHRONOUS_IO) != 0),
854 BasicInfo,
857 {
858 return IoStatusBlock.Status;
859 }
860
861 /* In case it failed, fall back to IRP-based method */
863}
864
866NTAPI
868 IN PIRP Irp,
869 IN PFILE_RENAME_INFORMATION RenameInfo,
871{
876 PFILE_OBJECT TargetFileObject;
878 FILE_BASIC_INFORMATION BasicInfo;
882
883 PAGED_CODE();
884
885 /* First, establish whether our target is a directory */
886 if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
887 {
889 if (!NT_SUCCESS(Status))
890 {
891 return Status;
892 }
893
896 }
897 }
898
899 /* Setup the string to the target */
900 FileName.Buffer = RenameInfo->FileName;
901 FileName.Length = RenameInfo->FileNameLength;
902 FileName.MaximumLength = RenameInfo->FileNameLength;
903
905 &FileName,
907 RenameInfo->RootDirectory,
908 NULL);
909
910 /* And open its parent directory
911 * Use hint if specified
912 */
914 {
915 PFILE_OBJECT_EXTENSION FileObjectExtension;
916
918
919 FileObjectExtension = FileObject->FileObjectExtension;
924 NULL,
925 0,
927 FILE_OPEN,
929 NULL,
930 0,
932 NULL,
934 FileObjectExtension->TopDeviceObjectHint);
935 }
936 else
937 {
942 NULL,
943 0,
945 FILE_OPEN,
947 NULL,
948 0,
950 NULL,
952 }
953
954 if (!NT_SUCCESS(Status))
955 {
956 return Status;
957 }
958
959 /* Once open, continue only if:
960 * Target exists and we're allowed to overwrite it
961 */
963 if (Stack->Parameters.SetFile.FileInformationClass == FileLinkInformation &&
964 !RenameInfo->ReplaceIfExists &&
966 {
969 }
970
971 /* Now, we'll get the associated device of the target, to check for same device location
972 * So, get the FO first
973 */
978 (PVOID *)&TargetFileObject,
980 if (!NT_SUCCESS(Status))
981 {
983 return Status;
984 }
985
986 /* We can dereference, we have the handle */
987 ObDereferenceObject(TargetFileObject);
988 /* If we're not on the same device, error out **/
990 {
993 }
994
995 /* Return parent directory file object and handle */
996 Stack->Parameters.SetFile.FileObject = TargetFileObject;
998
999 return STATUS_SUCCESS;
1000}
1001
1002static
1003ULONG
1005{
1006 ULONG Mode = 0;
1007
1008 if (FileObject->Flags & FO_WRITE_THROUGH)
1010
1011 if (FileObject->Flags & FO_SEQUENTIAL_ONLY)
1013
1016
1017 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1018 {
1019 if (FileObject->Flags & FO_ALERTABLE_IO)
1021 else
1023 }
1024
1025 if (FileObject->Flags & FO_DELETE_ON_CLOSE)
1027
1028 return Mode;
1029}
1030
1031static
1032BOOLEAN
1034{
1035 KIRQL OldIrql;
1036 PVPB Vpb;
1037 BOOLEAN Mounted;
1038
1039 /* Assume not mounted */
1040 Mounted = FALSE;
1041
1042 /* Check whether we have the mount flag */
1044
1045 Vpb = DeviceObject->Vpb;
1046 if (Vpb != NULL &&
1047 BooleanFlagOn(Vpb->Flags, VPB_MOUNTED))
1048 {
1049 Mounted = TRUE;
1050 }
1051
1053
1054 return Mounted;
1055}
1056
1057static
1058BOOLEAN
1061{
1062 PDEVICE_OBJECT StackDO;
1063
1064 /* Browse our whole device stack, trying to find the appropriate driver */
1066 while (StackDO != NULL)
1067 {
1068 /* We've found the driver, return success */
1069 if (StackDO->DriverObject == DriverObject)
1070 {
1071 return TRUE;
1072 }
1073
1074 /* Move to the next */
1075 StackDO = StackDO->AttachedDevice;
1076 }
1077
1078 /* We only reach there if driver was not found */
1079 return FALSE;
1080}
1081
1082static
1085 IN PFILE_FS_DRIVER_PATH_INFORMATION DriverPathInfo,
1086 IN ULONG Length)
1087{
1088 KIRQL OldIrql;
1090 UNICODE_STRING DriverName;
1092
1093 /* Make sure the structure is consistent (ie, driver name fits into the buffer) */
1094 if (Length - FIELD_OFFSET(FILE_FS_DRIVER_PATH_INFORMATION, DriverName) < DriverPathInfo->DriverNameLength)
1095 {
1097 }
1098
1099 /* Setup the whole driver name */
1100 DriverName.Length = DriverPathInfo->DriverNameLength;
1101 DriverName.MaximumLength = DriverPathInfo->DriverNameLength;
1102 DriverName.Buffer = &DriverPathInfo->DriverName[0];
1103
1104 /* Ask Ob for such driver */
1105 Status = ObReferenceObjectByName(&DriverName,
1107 NULL,
1108 0,
1110 KernelMode,
1111 NULL,
1112 (PVOID*)&DriverObject);
1113 /* No such driver, bail out */
1114 if (!NT_SUCCESS(Status))
1115 {
1116 return Status;
1117 }
1118
1119 /* Lock the devices database, we'll browse it */
1121 /* If we have a VPB, browse the stack from the volume */
1122 if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL)
1123 {
1124 DriverPathInfo->DriverInPath = IopVerifyDriverObjectOnStack(FileObject->Vpb->DeviceObject, DriverObject);
1125 }
1126 /* Otherwise, do it from the normal device */
1127 else
1128 {
1129 DriverPathInfo->DriverInPath = IopVerifyDriverObjectOnStack(FileObject->DeviceObject, DriverObject);
1130 }
1132
1133 /* No longer needed */
1135
1136 return STATUS_SUCCESS;
1137}
1138
1139/* PUBLIC FUNCTIONS **********************************************************/
1140
1141/*
1142 * @implemented
1143 */
1145NTAPI
1147 IN PMDL Mdl,
1150 IN PIO_STATUS_BLOCK StatusBlock)
1151{
1152 PIRP Irp;
1153 PIO_STACK_LOCATION StackPtr;
1155 IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p\n",
1157
1158 /* Is the write originating from Cc? */
1159 if (FileObject->SectionObjectPointer != NULL &&
1160 FileObject->SectionObjectPointer->SharedCacheMap != NULL)
1161 {
1162 ++CcDataFlushes;
1164 }
1165
1166 /* Get the Device Object */
1168
1169 /* Allocate IRP */
1170 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1172
1173 /* Get the Stack */
1174 StackPtr = IoGetNextIrpStackLocation(Irp);
1175
1176 /* Create the IRP Settings */
1177 Irp->MdlAddress = Mdl;
1178 Irp->UserBuffer = MmGetMdlVirtualAddress(Mdl);
1179 Irp->UserIosb = StatusBlock;
1180 Irp->UserEvent = Event;
1181 Irp->RequestorMode = KernelMode;
1183 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1184 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1185
1186 /* Set the Stack Settings */
1187 StackPtr->Parameters.Write.Length = MmGetMdlByteCount(Mdl);
1188 StackPtr->Parameters.Write.ByteOffset = *Offset;
1189 StackPtr->MajorFunction = IRP_MJ_WRITE;
1190 StackPtr->FileObject = FileObject;
1191
1192 /* Call the Driver */
1193 return IoCallDriver(DeviceObject, Irp);
1194}
1195
1196/*
1197 * @implemented
1198 */
1200NTAPI
1202 IN PMDL Mdl,
1205 IN PIO_STATUS_BLOCK StatusBlock)
1206{
1207 PIRP Irp;
1208 PIO_STACK_LOCATION StackPtr;
1210 IOTRACE(IO_API_DEBUG, "FileObject: %p. Mdl: %p. Offset: %p\n",
1212
1213 /* Get the Device Object */
1215
1216 /* Allocate IRP */
1217 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1218 /* If allocation failed, try to see whether we can use
1219 * the reserve IRP
1220 */
1221 if (Irp == NULL)
1222 {
1223 /* We will use it only for paging file */
1225 {
1228 }
1229 else
1230 {
1232 }
1233
1234 /* If allocation failed (not a paging file or too big stack size)
1235 * Fail for real
1236 */
1237 if (Irp == NULL)
1238 {
1240 }
1241 }
1242
1243 /* Get the Stack */
1244 StackPtr = IoGetNextIrpStackLocation(Irp);
1245
1246 /* Create the IRP Settings */
1247 Irp->MdlAddress = Mdl;
1248 Irp->UserBuffer = MmGetMdlVirtualAddress(Mdl);
1249 Irp->UserIosb = StatusBlock;
1250 Irp->UserEvent = Event;
1251 Irp->RequestorMode = KernelMode;
1252 Irp->Flags = IRP_PAGING_IO |
1253 IRP_NOCACHE |
1256 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1257 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1258
1259 /* Set the Stack Settings */
1260 StackPtr->Parameters.Read.Length = MmGetMdlByteCount(Mdl);
1261 StackPtr->Parameters.Read.ByteOffset = *Offset;
1262 StackPtr->MajorFunction = IRP_MJ_READ;
1263 StackPtr->FileObject = FileObject;
1264
1265 /* Call the Driver */
1266 return IoCallDriver(DeviceObject, Irp);
1267}
1268
1269/*
1270 * @implemented
1271 */
1273NTAPI
1276 IN ULONG Length,
1279{
1280 /* Call the shared routine */
1283 Length,
1286 TRUE);
1287}
1288
1289/*
1290 * @implemented
1291 */
1293NTAPI
1296 IN ULONG Length,
1297 OUT PVOID FsInformation,
1299{
1300 /* Call the shared routine */
1303 Length,
1304 FsInformation,
1306 FALSE);
1307}
1308
1309/*
1310 * @implemented
1311 */
1313NTAPI
1316 IN ULONG Length,
1318{
1320 PIRP Irp;
1322 PIO_STACK_LOCATION StackPtr;
1323 BOOLEAN LocalEvent = FALSE;
1324 KEVENT Event;
1326 PAGED_CODE();
1327 IOTRACE(IO_API_DEBUG, "FileObject: %p. Class: %lx. Length: %lx\n",
1329
1330 /* Reference the object */
1332
1333 /* Check if this is a file that was opened for Synch I/O */
1334 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1335 {
1336 /* Lock it */
1338
1339 /* Use File Object event */
1340 KeClearEvent(&FileObject->Event);
1341 }
1342 else
1343 {
1344 /* Use local event */
1346 LocalEvent = TRUE;
1347 }
1348
1349 /* Get the Device Object */
1351
1352 /* Allocate the IRP */
1353 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1354 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL);
1355
1356 /* Set the IRP */
1357 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1358 Irp->RequestorMode = KernelMode;
1359 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
1360 Irp->UserIosb = &IoStatusBlock;
1361 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1362 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1363 Irp->Flags |= IRP_BUFFERED_IO;
1364 Irp->AssociatedIrp.SystemBuffer = FileInformation;
1365 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1366
1367 /* Set the Stack Data */
1368 StackPtr = IoGetNextIrpStackLocation(Irp);
1370 StackPtr->FileObject = FileObject;
1371
1372 /* Set Parameters */
1373 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
1374 StackPtr->Parameters.SetFile.Length = Length;
1375
1376 /* Queue the IRP */
1378
1379 /* Call the Driver */
1381
1382 /* Check if this was synch I/O */
1383 if (!LocalEvent)
1384 {
1385 /* Check if the request is pending */
1386 if (Status == STATUS_PENDING)
1387 {
1388 /* Wait on the file object */
1390 Executive,
1391 KernelMode,
1392 (FileObject->Flags &
1393 FO_ALERTABLE_IO) != 0,
1394 NULL);
1395 if (Status == STATUS_ALERTED)
1396 {
1397 /* Abort the operation */
1399 }
1400
1401 /* Get the final status */
1402 Status = FileObject->FinalStatus;
1403 }
1404
1405 /* Release the file lock */
1407 }
1408 else if (Status == STATUS_PENDING)
1409 {
1410 /* Wait on the local event and get the final status */
1412 Executive,
1413 KernelMode,
1414 FALSE,
1415 NULL);
1417 }
1418
1419 /* Return the status */
1420 return Status;
1421}
1422
1423/* NATIVE SERVICES ***********************************************************/
1424
1425/*
1426 * @implemented
1427 */
1429NTAPI
1432 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1433 IN PVOID UserApcContext OPTIONAL,
1440{
1441 /* Call the Generic Function */
1443 Event,
1444 UserApcRoutine,
1445 UserApcContext,
1452 TRUE);
1453}
1454
1455/*
1456 * @implemented
1457 */
1459NTAPI
1462 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
1463 IN PVOID UserApcContext OPTIONAL,
1470{
1471 /* Call the Generic Function */
1473 Event,
1474 UserApcRoutine,
1475 UserApcContext,
1482 FALSE);
1483}
1484
1486NTAPI
1489{
1491 PIRP Irp;
1492 PIO_STACK_LOCATION StackPtr;
1495 PKEVENT Event = NULL;
1496 BOOLEAN LocalEvent = FALSE;
1497 OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
1499 IO_STATUS_BLOCK KernelIosb;
1500 PAGED_CODE();
1501 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
1502
1503 if (PreviousMode != KernelMode)
1504 {
1505 /* Protect probes */
1506 _SEH2_TRY
1507 {
1508 /* Probe the I/O Status block */
1510 }
1512 {
1513 /* Return the exception code */
1515 }
1516 _SEH2_END;
1517 }
1518
1519 /* Get the File Object */
1521 0,
1524 (PVOID*)&FileObject,
1525 &ObjectHandleInfo);
1526 if (!NT_SUCCESS(Status)) return Status;
1527
1528 /*
1529 * Check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was
1530 * granted. However, if this is a named pipe, make sure we don't ask for
1531 * FILE_APPEND_DATA as it interferes with the FILE_CREATE_PIPE_INSTANCE
1532 * access right!
1533 */
1534 if (!(ObjectHandleInfo.GrantedAccess &
1535 ((!(FileObject->Flags & FO_NAMED_PIPE) ? FILE_APPEND_DATA : 0) |
1537 {
1538 /* We failed */
1540 return STATUS_ACCESS_DENIED;
1541 }
1542
1543 /* Check if we should use Sync IO or not */
1544 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1545 {
1546 /* Lock it */
1548 if (Status != STATUS_SUCCESS)
1549 {
1551 return Status;
1552 }
1553 }
1554 else
1555 {
1556 /* Use local event */
1558 if (!Event)
1559 {
1560 /* We failed */
1563 }
1565 LocalEvent = TRUE;
1566 }
1567
1568 /* Get the Device Object */
1570
1571 /* Clear the event */
1572 KeClearEvent(&FileObject->Event);
1573
1574 /* Allocate the IRP */
1575 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
1577
1578 /* Set up the IRP */
1579 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1580 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
1581 Irp->UserEvent = (LocalEvent) ? Event : NULL;
1582 Irp->RequestorMode = PreviousMode;
1583 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1584 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1585 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
1586
1587 /* Set up Stack Data */
1588 StackPtr = IoGetNextIrpStackLocation(Irp);
1590 StackPtr->FileObject = FileObject;
1591
1592 /* Call the Driver */
1594 Irp,
1595 FileObject,
1596 FALSE,
1598 !LocalEvent,
1600
1601 /* Check if this was async I/O */
1602 if (LocalEvent)
1603 {
1604 /* It was, finalize this request */
1606 Event,
1607 Irp,
1609 &KernelIosb,
1611 }
1612
1613 /* Return the Status */
1614 return Status;
1615}
1616
1617/*
1618 * @implemented
1619 */
1621NTAPI
1631{
1632 PIRP Irp;
1633 PKEVENT Event = NULL;
1636 PIO_STACK_LOCATION IoStack;
1639 BOOLEAN LockedForSync = FALSE;
1640 PAGED_CODE();
1641 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
1642
1643 /* Check if we're called from user mode */
1644 if (PreviousMode != KernelMode)
1645 {
1646 /* Enter SEH for probing */
1647 _SEH2_TRY
1648 {
1649 /* Probe the I/O STatus block */
1651
1652 /* Probe the buffer */
1654 }
1656 {
1657 /* Return the exception code */
1659 }
1660 _SEH2_END;
1661
1662 /* Check if CompletionFilter is valid */
1664 {
1666 }
1667 }
1668
1669 /* Get File Object */
1674 (PVOID*)&FileObject,
1675 NULL);
1676 if (!NT_SUCCESS(Status)) return Status;
1677
1678 /* Can't use an I/O completion port and an APC at the same time */
1679 if ((FileObject->CompletionContext) && (ApcRoutine))
1680 {
1681 /* Fail */
1684 }
1685
1686 /* Check if we have an event handle */
1687 if (EventHandle)
1688 {
1689 /* Reference it */
1694 (PVOID *)&Event,
1695 NULL);
1696 if (Status != STATUS_SUCCESS)
1697 {
1699 return Status;
1700 }
1702 }
1703
1704 /* Check if we should use Sync IO or not */
1705 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1706 {
1707 /* Lock it */
1709 if (Status != STATUS_SUCCESS)
1710 {
1713 return Status;
1714 }
1715 LockedForSync = TRUE;
1716 }
1717
1718 /* Clear File Object event */
1719 KeClearEvent(&FileObject->Event);
1720
1721 /* Get the device object */
1723
1724 /* Allocate the IRP */
1725 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1727
1728 /* Set up the IRP */
1729 Irp->RequestorMode = PreviousMode;
1730 Irp->UserIosb = IoStatusBlock;
1731 Irp->UserEvent = Event;
1732 Irp->UserBuffer = Buffer;
1733 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1734 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1735 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
1736 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
1737
1738 /* Set up Stack Data */
1739 IoStack = IoGetNextIrpStackLocation(Irp);
1742 IoStack->FileObject = FileObject;
1743
1744 /* Set parameters */
1745 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
1746 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
1747 if (WatchTree) IoStack->Flags = SL_WATCH_TREE;
1748
1749 /* Perform the call */
1751 Irp,
1752 FileObject,
1753 FALSE,
1755 LockedForSync,
1757}
1758
1759/*
1760 * @implemented
1761 */
1763NTAPI
1771 IN ULONG Key,
1774{
1776 PLARGE_INTEGER LocalLength = NULL;
1777 PIRP Irp;
1778 PIO_STACK_LOCATION StackPtr;
1780 PKEVENT Event = NULL;
1781 BOOLEAN LockedForSync = FALSE;
1783 LARGE_INTEGER CapturedByteOffset, CapturedLength;
1787 PAGED_CODE();
1788 CapturedByteOffset.QuadPart = 0;
1789 CapturedLength.QuadPart = 0;
1790 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
1791
1792 /* Get File Object */
1794 0,
1797 (PVOID*)&FileObject,
1799 if (!NT_SUCCESS(Status)) return Status;
1800
1801 /* Check if we're called from user mode */
1802 if (PreviousMode != KernelMode)
1803 {
1804 /* Can't use an I/O completion port and an APC at the same time */
1805 if ((FileObject->CompletionContext) && (ApcRoutine))
1806 {
1807 /* Fail */
1810 }
1811
1812 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
1813 if (!(HandleInformation.GrantedAccess &
1815 {
1817 return STATUS_ACCESS_DENIED;
1818 }
1819
1820 /* Enter SEH for probing */
1821 _SEH2_TRY
1822 {
1823 /* Probe the I/O STatus block */
1825
1826 /* Probe and capture the large integers */
1827 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
1828 CapturedLength = ProbeForReadLargeInteger(Length);
1829 }
1831 {
1832 /* Dereference the object and return exception code */
1835 }
1836 _SEH2_END;
1837 }
1838 else
1839 {
1840 /* Otherwise, capture them directly */
1841 CapturedByteOffset = *ByteOffset;
1842 CapturedLength = *Length;
1843 }
1844
1845 /* Check if we have an event handle */
1846 if (EventHandle)
1847 {
1848 /* Reference it */
1853 (PVOID *)&Event,
1854 NULL);
1855 if (Status != STATUS_SUCCESS) return Status;
1857 }
1858
1859 /* Get the device object */
1861
1862 /* Try to do it the FastIO way if possible */
1863 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
1865 {
1866 IO_STATUS_BLOCK KernelIosb;
1867
1869 &CapturedByteOffset,
1870 &CapturedLength,
1872 Key,
1875 &KernelIosb,
1876 DeviceObject))
1877 {
1878 /* Write the IOSB back */
1879 _SEH2_TRY
1880 {
1881 *IoStatusBlock = KernelIosb;
1882 }
1884 {
1885 KernelIosb.Status = _SEH2_GetExceptionCode();
1886 }
1887 _SEH2_END;
1888
1889 /* If we had an event, signal it */
1890 if (EventHandle)
1891 {
1894 }
1895
1896 /* Set completion if required */
1897 if (FileObject->CompletionContext != NULL && ApcContext != NULL)
1898 {
1899 if (!NT_SUCCESS(IoSetIoCompletion(FileObject->CompletionContext->Port,
1900 FileObject->CompletionContext->Key,
1901 ApcContext,
1902 KernelIosb.Status,
1903 KernelIosb.Information,
1904 TRUE)))
1905 {
1907 }
1908 }
1909
1910 FileObject->LockOperation = TRUE;
1911
1912 /* We're done with FastIO! */
1914 return KernelIosb.Status;
1915 }
1916 }
1917
1918 /* Check if we should use Sync IO or not */
1919 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1920 {
1921 /* Lock it */
1923 if (Status != STATUS_SUCCESS)
1924 {
1927 return Status;
1928 }
1929 LockedForSync = TRUE;
1930 }
1931
1932 /* Clear File Object event */
1933 KeClearEvent(&FileObject->Event);
1934 FileObject->LockOperation = TRUE;
1935
1936 /* Allocate the IRP */
1937 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1939
1940 /* Set up the IRP */
1941 Irp->RequestorMode = PreviousMode;
1942 Irp->UserIosb = IoStatusBlock;
1943 Irp->UserEvent = Event;
1944 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1945 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1946 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
1947 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
1948
1949 /* Set up Stack Data */
1950 StackPtr = IoGetNextIrpStackLocation(Irp);
1952 StackPtr->MinorFunction = IRP_MN_LOCK;
1953 StackPtr->FileObject = FileObject;
1954
1955 /* Allocate local buffer */
1956 LocalLength = ExAllocatePoolWithTag(NonPagedPool,
1957 sizeof(LARGE_INTEGER),
1958 TAG_LOCK);
1959 if (!LocalLength)
1960 {
1961 /* Allocating failed, clean up and return failure */
1964 }
1965
1966 /* Set the length */
1967 *LocalLength = CapturedLength;
1968 Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength;
1969 StackPtr->Parameters.LockControl.Length = LocalLength;
1970
1971 /* Set Parameters */
1972 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
1973 StackPtr->Parameters.LockControl.Key = Key;
1974
1975 /* Set Flags */
1976 if (FailImmediately) StackPtr->Flags = SL_FAIL_IMMEDIATELY;
1977 if (ExclusiveLock) StackPtr->Flags |= SL_EXCLUSIVE_LOCK;
1978
1979 /* Perform the call */
1981 Irp,
1982 FileObject,
1983 FALSE,
1985 LockedForSync,
1987}
1988
1989/*
1990 * @implemented
1991 */
1993NTAPI
2000 IN ULONG Length,
2005{
2006 PIRP Irp;
2009 PIO_STACK_LOCATION StackPtr;
2012 BOOLEAN LockedForSynch = FALSE;
2013 PKEVENT Event = NULL;
2014 volatile PVOID AuxBuffer = NULL;
2015 PMDL Mdl;
2016 UNICODE_STRING CapturedFileName;
2017 PUNICODE_STRING SearchPattern;
2018 PAGED_CODE();
2019 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
2020
2021 /* Check if we came from user mode */
2022 if (PreviousMode != KernelMode)
2023 {
2024 /* Enter SEH for probing */
2025 _SEH2_TRY
2026 {
2027 /* Probe the I/O Status Block */
2029
2030 /* Probe the file information */
2032
2033 /* Check if we have a file name */
2034 if (FileName)
2035 {
2036 /* Capture it */
2037 CapturedFileName = ProbeForReadUnicodeString(FileName);
2038 if (CapturedFileName.Length)
2039 {
2040 /* Probe its buffer */
2041 ProbeForRead(CapturedFileName.Buffer,
2042 CapturedFileName.Length,
2043 1);
2044 }
2045
2046 /* Allocate the auxiliary buffer */
2048 CapturedFileName.Length +
2049 sizeof(UNICODE_STRING),
2050 TAG_SYSB);
2051 RtlCopyMemory((PVOID)((ULONG_PTR)AuxBuffer +
2052 sizeof(UNICODE_STRING)),
2053 CapturedFileName.Buffer,
2054 CapturedFileName.Length);
2055
2056 /* Setup the search pattern */
2057 SearchPattern = (PUNICODE_STRING)AuxBuffer;
2058 SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)AuxBuffer +
2059 sizeof(UNICODE_STRING));
2060 SearchPattern->Length = CapturedFileName.Length;
2061 SearchPattern->MaximumLength = CapturedFileName.Length;
2062 }
2063 }
2065 {
2066 /* Free buffer and return the exception code */
2067 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2069 }
2070 _SEH2_END;
2071 }
2072
2073 /* Check input parameters */
2074
2075 switch (FileInformationClass)
2076 {
2077#define CHECK_LENGTH(class, struct) \
2078 case class: \
2079 if (Length < sizeof(struct)) \
2080 return STATUS_INFO_LENGTH_MISMATCH; \
2081 break
2088 default:
2089 break;
2090#undef CHECK_LENGTH
2091 }
2092
2093 /* Get File Object */
2098 (PVOID *)&FileObject,
2099 NULL);
2100 if (!NT_SUCCESS(Status))
2101 {
2102 /* Fail */
2103 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2104 return Status;
2105 }
2106
2107 /* Are there two associated completion routines? */
2108 if (FileObject->CompletionContext != NULL && ApcRoutine != NULL)
2109 {
2111 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2113 }
2114
2115 /* Check if we have an even handle */
2116 if (EventHandle)
2117 {
2118 /* Get its pointer */
2123 (PVOID *)&Event,
2124 NULL);
2125 if (!NT_SUCCESS(Status))
2126 {
2127 /* Fail */
2128 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2130 return Status;
2131 }
2132
2133 /* Clear it */
2135 }
2136
2137 /* Check if this is a file that was opened for Synch I/O */
2138 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2139 {
2140 /* Lock it */
2142 if (Status != STATUS_SUCCESS)
2143 {
2146 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2147 return Status;
2148 }
2149
2150 /* Remember to unlock later */
2151 LockedForSynch = TRUE;
2152 }
2153
2154 /* Get the device object */
2156
2157 /* Clear the File Object's event */
2158 KeClearEvent(&FileObject->Event);
2159
2160 /* Allocate the IRP */
2161 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
2162 if (!Irp) return IopCleanupFailedIrp(FileObject, EventHandle, AuxBuffer);
2163
2164 /* Set up the IRP */
2165 Irp->RequestorMode = PreviousMode;
2166 Irp->UserIosb = IoStatusBlock;
2167 Irp->UserEvent = Event;
2168 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2169 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2170 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2171 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2172 Irp->MdlAddress = NULL;
2173 Irp->Tail.Overlay.AuxiliaryBuffer = AuxBuffer;
2174 Irp->AssociatedIrp.SystemBuffer = NULL;
2175
2176 /* Check if this is buffered I/O */
2177 if (DeviceObject->Flags & DO_BUFFERED_IO)
2178 {
2179 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
2180 _SEH2_TRY
2181 {
2182 /* Allocate a buffer */
2183 Irp->AssociatedIrp.SystemBuffer =
2185 }
2187 {
2188 /* Allocating failed, clean up and return the exception code */
2190 if (AuxBuffer) ExFreePoolWithTag(AuxBuffer, TAG_SYSB);
2191
2192 /* Return the exception code */
2193 return _SEH2_GetExceptionCode();
2194 }
2195 _SEH2_END;
2196
2197 /* Set the buffer and flags */
2198 Irp->UserBuffer = FileInformation;
2199 Irp->Flags = (IRP_BUFFERED_IO |
2202 }
2203 else if (DeviceObject->Flags & DO_DIRECT_IO)
2204 {
2205 _SEH2_TRY
2206 {
2207 /* Allocate an MDL */
2211 }
2213 {
2214 /* Allocating failed, clean up and return the exception code */
2217 }
2218 _SEH2_END;
2219 }
2220 else
2221 {
2222 /* No allocation flags, and use the buffer directly */
2223 Irp->UserBuffer = FileInformation;
2224 }
2225
2226 /* Set up Stack Data */
2227 StackPtr = IoGetNextIrpStackLocation(Irp);
2228 StackPtr->FileObject = FileObject;
2231
2232 /* Set Parameters */
2233 StackPtr->Parameters.QueryDirectory.FileInformationClass =
2235 StackPtr->Parameters.QueryDirectory.FileName = AuxBuffer;
2236 StackPtr->Parameters.QueryDirectory.FileIndex = 0;
2237 StackPtr->Parameters.QueryDirectory.Length = Length;
2238 StackPtr->Flags = 0;
2239 if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
2241
2242 /* Set deferred I/O */
2243 Irp->Flags |= IRP_DEFER_IO_COMPLETION;
2244
2245 /* Perform the call */
2247 Irp,
2248 FileObject,
2249 TRUE,
2251 LockedForSynch,
2253}
2254
2255/*
2256 * @unimplemented
2257 */
2259NTAPI
2263 IN ULONG Length,
2265 IN PVOID EaList OPTIONAL,
2269{
2272}
2273
2274/*
2275 * @implemented
2276 */
2278NTAPI
2282 IN ULONG Length,
2284{
2288 PIRP Irp;
2290 PIO_STACK_LOCATION StackPtr;
2292 PKEVENT Event = NULL;
2293 BOOLEAN LocalEvent = FALSE;
2294 PKNORMAL_ROUTINE NormalRoutine;
2295 PVOID NormalContext;
2296 KIRQL OldIrql;
2297 IO_STATUS_BLOCK KernelIosb;
2298 BOOLEAN CallDriver = TRUE;
2299 PFILE_ACCESS_INFORMATION AccessBuffer;
2300 PFILE_MODE_INFORMATION ModeBuffer;
2301 PFILE_ALIGNMENT_INFORMATION AlignmentBuffer;
2302 PFILE_ALL_INFORMATION AllBuffer;
2304 PAGED_CODE();
2305 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
2306
2307 /* Check if we're called from user mode */
2308 if (PreviousMode != KernelMode)
2309 {
2310 /* Validate the information class */
2311 if ((FileInformationClass < 0) ||
2314 {
2315 /* Invalid class */
2317 }
2318
2319 /* Validate the length */
2321 {
2322 /* Invalid length */
2324 }
2325
2326 /* Enter SEH for probing */
2327 _SEH2_TRY
2328 {
2329 /* Probe the I/O Status block */
2331
2332 /* Probe the information */
2334 }
2336 {
2337 /* Return the exception code */
2339 }
2340 _SEH2_END;
2341 }
2342#if DBG
2343 else
2344 {
2345 /* Validate the information class */
2346 if ((FileInformationClass < 0) ||
2349 {
2350 /* Invalid class */
2352 }
2353
2354 /* Validate the length */
2356 {
2357 /* Invalid length */
2359 }
2360 }
2361#endif
2362
2363 /* Reference the Handle */
2369 (PVOID *)&FileObject,
2371 if (!NT_SUCCESS(Status)) return Status;
2372
2373 /* Check if this is a direct open or not */
2374 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2375 {
2376 /* Get the device object */
2378 }
2379 else
2380 {
2381 /* Get the device object */
2383 }
2384
2385 /* Check if this is a file that was opened for Synch I/O */
2386 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2387 {
2388 /* Lock it */
2390 if (Status != STATUS_SUCCESS)
2391 {
2393 return Status;
2394 }
2395
2396 /* Check if the caller just wants the position */
2398 {
2399 /* Protect write in SEH */
2400 _SEH2_TRY
2401 {
2402 /* Write the offset */
2404 CurrentByteOffset = FileObject->CurrentByteOffset;
2405
2406 /* Fill out the I/O Status Block */
2409 }
2411 {
2412 /* Get the exception code */
2414 }
2415 _SEH2_END;
2416
2417 /* Release the file lock, dereference the file and return */
2420 return Status;
2421 }
2422 }
2423 else
2424 {
2425 /* Use local event */
2427 if (!Event)
2428 {
2431 }
2433 LocalEvent = TRUE;
2434 }
2435
2436 /* Check if FastIO is possible for the two available information classes */
2437 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
2438 if (FastIoDispatch != NULL &&
2441 {
2443
2445 {
2448 &KernelIosb,
2449 DeviceObject);
2450 }
2451 else
2452 {
2455 &KernelIosb,
2456 DeviceObject);
2457 }
2458
2459 /* If call succeed */
2460 if (Success)
2461 {
2462 /* Write the IOSB back */
2463 _SEH2_TRY
2464 {
2465 *IoStatusBlock = KernelIosb;
2466 }
2468 {
2469 KernelIosb.Status = _SEH2_GetExceptionCode();
2470 }
2471 _SEH2_END;
2472
2473 /* Free the event if we had one */
2474 if (LocalEvent)
2475 {
2477 }
2478
2479 /* If FO was locked, unlock it */
2480 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2481 {
2483 }
2484
2485 /* We're done with FastIO! */
2487 return KernelIosb.Status;
2488 }
2489 }
2490
2491 /* Clear the File Object event */
2492 KeClearEvent(&FileObject->Event);
2493
2494 /* Allocate the IRP */
2495 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
2497
2498 /* Set the IRP */
2499 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2500 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2501 Irp->RequestorMode = PreviousMode;
2502 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
2503 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
2504 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
2505 Irp->UserEvent = (LocalEvent) ? Event : NULL;
2506 Irp->AssociatedIrp.SystemBuffer = NULL;
2507 Irp->MdlAddress = NULL;
2508 Irp->UserBuffer = FileInformation;
2509
2510 /* Set the Stack Data */
2511 StackPtr = IoGetNextIrpStackLocation(Irp);
2513 StackPtr->FileObject = FileObject;
2514
2515 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
2516 _SEH2_TRY
2517 {
2518 /* Allocate a buffer */
2519 Irp->AssociatedIrp.SystemBuffer =
2521 }
2523 {
2524 /* Allocating failed, clean up and return the exception code */
2527 }
2528 _SEH2_END;
2529
2530 /* Set the flags */
2531 Irp->Flags |= (IRP_BUFFERED_IO |
2535
2536 /* Set the Parameters */
2537 StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
2538 StackPtr->Parameters.QueryFile.Length = Length;
2539
2540 /* Queue the IRP */
2542
2543 /* Update operation counts */
2545
2546 /* Fill in file information before calling the driver.
2547 See 'File System Internals' page 485.*/
2549 {
2550 AccessBuffer = Irp->AssociatedIrp.SystemBuffer;
2551 AccessBuffer->AccessFlags = HandleInformation.GrantedAccess;
2552 Irp->IoStatus.Information = sizeof(FILE_ACCESS_INFORMATION);
2553 CallDriver = FALSE;
2554 }
2556 {
2557 ModeBuffer = Irp->AssociatedIrp.SystemBuffer;
2558 ModeBuffer->Mode = IopGetFileMode(FileObject);
2559 Irp->IoStatus.Information = sizeof(FILE_MODE_INFORMATION);
2560 CallDriver = FALSE;
2561 }
2563 {
2564 AlignmentBuffer = Irp->AssociatedIrp.SystemBuffer;
2565 AlignmentBuffer->AlignmentRequirement = DeviceObject->AlignmentRequirement;
2566 Irp->IoStatus.Information = sizeof(FILE_ALIGNMENT_INFORMATION);
2567 CallDriver = FALSE;
2568 }
2570 {
2571 AllBuffer = Irp->AssociatedIrp.SystemBuffer;
2572 AllBuffer->AccessInformation.AccessFlags = HandleInformation.GrantedAccess;
2574 AllBuffer->AlignmentInformation.AlignmentRequirement = DeviceObject->AlignmentRequirement;
2575 Irp->IoStatus.Information = sizeof(FILE_ACCESS_INFORMATION) +
2576 sizeof(FILE_MODE_INFORMATION) +
2578 }
2579
2580 /* Call the Driver */
2581 if (CallDriver)
2582 {
2584 }
2585 else
2586 {
2588 Irp->IoStatus.Status = STATUS_SUCCESS;
2589 }
2590
2591 if (Status == STATUS_PENDING)
2592 {
2593 /* Check if this was async I/O */
2594 if (LocalEvent)
2595 {
2596 /* Then to a non-alertable wait */
2598 Executive,
2600 FALSE,
2601 NULL);
2602 if (Status == STATUS_USER_APC)
2603 {
2604 /* Abort the request */
2606 }
2607
2608 /* Set the final status */
2609 Status = KernelIosb.Status;
2610
2611 /* Enter SEH to write the IOSB back */
2612 _SEH2_TRY
2613 {
2614 /* Write it back to the caller */
2615 *IoStatusBlock = KernelIosb;
2616 }
2618 {
2619 /* Get the exception code */
2621 }
2622 _SEH2_END;
2623
2624 /* Free the event */
2626 }
2627 else
2628 {
2629 /* Wait for the IRP */
2631 Executive,
2633 (FileObject->Flags &
2634 FO_ALERTABLE_IO) != 0,
2635 NULL);
2637 {
2638 /* Abort the request */
2640 }
2641
2642 /* Set the final status */
2643 Status = FileObject->FinalStatus;
2644
2645 /* Release the file lock */
2647 }
2648 }
2649 else
2650 {
2651 /* Free the event if we had one */
2652 if (LocalEvent)
2653 {
2654 /* Clear it in the IRP for completion */
2655 Irp->UserEvent = NULL;
2657 }
2658
2659 /* Set the caller IOSB */
2660 Irp->UserIosb = IoStatusBlock;
2661
2662 /* The IRP wasn't completed, complete it ourselves */
2663 NormalRoutine = NULL;
2664 NormalContext = NULL;
2666 IopCompleteRequest(&Irp->Tail.Apc,
2667 &NormalRoutine,
2668 &NormalContext,
2669 (PVOID*)&FileObject,
2670 &NormalContext);
2672
2673 /* Release the file object if we had locked it*/
2674 if (!LocalEvent) IopUnlockFileObject(FileObject);
2675 }
2676
2677 /* Return the Status */
2678 return Status;
2679}
2680
2681/*
2682 * @unimplemented
2683 */
2685NTAPI
2689 IN ULONG Length,
2691 IN PVOID SidList OPTIONAL,
2695{
2698}
2699
2700/*
2701 * @implemented
2702 */
2704NTAPI
2711 IN ULONG Length,
2714{
2717 PIRP Irp;
2719 PIO_STACK_LOCATION StackPtr;
2721 PKEVENT EventObject = NULL;
2722 LARGE_INTEGER CapturedByteOffset;
2723 ULONG CapturedKey = 0;
2724 BOOLEAN Synchronous = FALSE;
2725 PMDL Mdl;
2727 IO_STATUS_BLOCK KernelIosb;
2729
2730 PAGED_CODE();
2731 CapturedByteOffset.QuadPart = 0;
2732 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
2733
2734 /* Get File Object */
2739 (PVOID*)&FileObject,
2740 NULL);
2741 if (!NT_SUCCESS(Status)) return Status;
2742
2743 /* Get the device object */
2745
2746 /* Validate User-Mode Buffers */
2747 if (PreviousMode != KernelMode)
2748 {
2749 _SEH2_TRY
2750 {
2751 /* Probe the status block */
2753
2754 /* Probe the read buffer */
2756
2757 /* Check if we got a byte offset */
2758 if (ByteOffset)
2759 {
2760 /* Capture and probe it */
2761 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
2762 }
2763
2764 /* Can't use an I/O completion port and an APC at the same time */
2765 if ((FileObject->CompletionContext) && (ApcRoutine))
2766 {
2767 /* Fail */
2770 }
2771
2772 /* Perform additional checks for non-cached file access */
2774 {
2775 /* Fail if Length is not sector size aligned
2776 * Perform a quick check for 2^ sector sizes
2777 * If it fails, try a more standard way
2778 */
2779 if ((DeviceObject->SectorSize != 0) &&
2780 ((DeviceObject->SectorSize - 1) & Length) != 0)
2781 {
2782 if (Length % DeviceObject->SectorSize != 0)
2783 {
2784 /* Release the file object and and fail */
2787 }
2788 }
2789
2790 /* Fail if buffer doesn't match alignment requirements */
2791 if (((ULONG_PTR)Buffer & DeviceObject->AlignmentRequirement) != 0)
2792 {
2793 /* Release the file object and and fail */
2796 }
2797
2798 if (ByteOffset)
2799 {
2800 /* Fail if ByteOffset is not sector size aligned */
2801 if ((DeviceObject->SectorSize != 0) &&
2802 (CapturedByteOffset.QuadPart % DeviceObject->SectorSize != 0))
2803 {
2804 /* Release the file object and and fail */
2807 }
2808 }
2809 }
2810
2811 /* Capture and probe the key */
2812 if (Key) CapturedKey = ProbeForReadUlong(Key);
2813 }
2815 {
2816 /* Release the file object and return the exception code */
2819 }
2820 _SEH2_END;
2821 }
2822 else
2823 {
2824 /* Kernel mode: capture directly */
2825 if (ByteOffset) CapturedByteOffset = *ByteOffset;
2826 if (Key) CapturedKey = *Key;
2827 }
2828
2829 /* Check for invalid offset */
2830 if ((CapturedByteOffset.QuadPart < 0) && (CapturedByteOffset.QuadPart != -2))
2831 {
2832 /* -2 is FILE_USE_FILE_POINTER_POSITION */
2835 }
2836
2837 /* Check for event */
2838 if (Event)
2839 {
2840 /* Reference it */
2845 (PVOID*)&EventObject,
2846 NULL);
2847 if (!NT_SUCCESS(Status))
2848 {
2849 /* Fail */
2851 return Status;
2852 }
2853
2854 /* Otherwise reset the event */
2855 KeClearEvent(EventObject);
2856 }
2857
2858 /* Check if we should use Sync IO or not */
2859 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
2860 {
2861 /* Lock the file object */
2863 if (Status != STATUS_SUCCESS)
2864 {
2865 if (EventObject) ObDereferenceObject(EventObject);
2867 return Status;
2868 }
2869
2870 /* Check if we don't have a byte offset available */
2871 if (!(ByteOffset) ||
2872 ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
2873 (CapturedByteOffset.u.HighPart == -1)))
2874 {
2875 /* Use the Current Byte Offset instead */
2876 CapturedByteOffset = FileObject->CurrentByteOffset;
2877 }
2878
2879 /* If the file is cached, try fast I/O */
2880 if (FileObject->PrivateCacheMap)
2881 {
2882 /* Perform fast read */
2883 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
2885
2887 &CapturedByteOffset,
2888 Length,
2889 TRUE,
2890 CapturedKey,
2891 Buffer,
2892 &KernelIosb,
2893 DeviceObject);
2894
2895 /* Only accept the result if we got a straightforward status */
2896 if (Success &&
2897 (KernelIosb.Status == STATUS_SUCCESS ||
2898 KernelIosb.Status == STATUS_BUFFER_OVERFLOW ||
2899 KernelIosb.Status == STATUS_END_OF_FILE))
2900 {
2901 /* Fast path -- update transfer & operation counts */
2904 (ULONG)KernelIosb.Information);
2905
2906 /* Enter SEH to write the IOSB back */
2907 _SEH2_TRY
2908 {
2909 /* Write it back to the caller */
2910 *IoStatusBlock = KernelIosb;
2911 }
2913 {
2914 /* The caller's IOSB was invalid, so fail */
2915 if (EventObject) ObDereferenceObject(EventObject);
2919 }
2920 _SEH2_END;
2921
2922 /* Signal the completion event */
2923 if (EventObject)
2924 {
2925 KeSetEvent(EventObject, 0, FALSE);
2926 ObDereferenceObject(EventObject);
2927 }
2928
2929 /* Clean up */
2932 return KernelIosb.Status;
2933 }
2934 }
2935
2936 /* Remember we are sync */
2937 Synchronous = TRUE;
2938 }
2939 else if (!(ByteOffset) &&
2940 !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT)))
2941 {
2942 /* Otherwise, this was async I/O without a byte offset, so fail */
2943 if (EventObject) ObDereferenceObject(EventObject);
2946 }
2947
2948 /* Clear the File Object's event */
2949 KeClearEvent(&FileObject->Event);
2950
2951 /* Allocate the IRP */
2952 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
2953 if (!Irp) return IopCleanupFailedIrp(FileObject, EventObject, NULL);
2954
2955 /* Set the IRP */
2956 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2957 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2958 Irp->RequestorMode = PreviousMode;
2959 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
2960 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
2961 Irp->UserIosb = IoStatusBlock;
2962 Irp->UserEvent = EventObject;
2963 Irp->PendingReturned = FALSE;
2964 Irp->Cancel = FALSE;
2965 Irp->CancelRoutine = NULL;
2966 Irp->AssociatedIrp.SystemBuffer = NULL;
2967 Irp->MdlAddress = NULL;
2968
2969 /* Set the Stack Data */
2970 StackPtr = IoGetNextIrpStackLocation(Irp);
2971 StackPtr->MajorFunction = IRP_MJ_READ;
2972 StackPtr->FileObject = FileObject;
2973 StackPtr->Parameters.Read.Key = CapturedKey;
2974 StackPtr->Parameters.Read.Length = Length;
2975 StackPtr->Parameters.Read.ByteOffset = CapturedByteOffset;
2976
2977 /* Check if this is buffered I/O */
2978 if (DeviceObject->Flags & DO_BUFFERED_IO)
2979 {
2980 /* Check if we have a buffer length */
2981 if (Length)
2982 {
2983 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
2984 _SEH2_TRY
2985 {
2986 /* Allocate a buffer */
2987 Irp->AssociatedIrp.SystemBuffer =
2989 }
2991 {
2992 /* Allocating failed, clean up and return the exception code */
2995 }
2996 _SEH2_END;
2997
2998 /* Set the buffer and flags */
2999 Irp->UserBuffer = Buffer;
3000 Irp->Flags = (IRP_BUFFERED_IO |
3003 }
3004 else
3005 {
3006 /* Not reading anything */
3008 }
3009 }
3010 else if (DeviceObject->Flags & DO_DIRECT_IO)
3011 {
3012 /* Check if we have a buffer length */
3013 if (Length)
3014 {
3015 _SEH2_TRY
3016 {
3017 /* Allocate an MDL */
3019 if (!Mdl)
3022 }
3024 {
3025 /* Allocating failed, clean up and return the exception code */
3028 }
3029 _SEH2_END;
3030
3031 }
3032
3033 /* No allocation flags */
3034 Irp->Flags = 0;
3035 }
3036 else
3037 {
3038 /* No allocation flags, and use the buffer directly */
3039 Irp->Flags = 0;
3040 Irp->UserBuffer = Buffer;
3041 }
3042
3043 /* Now set the deferred read flags */
3045
3047
3048 /* Perform the call */
3050 Irp,
3051 FileObject,
3052 TRUE,
3054 Synchronous,
3056}
3057
3058/*
3059 * @unimplemented
3060 */
3062NTAPI
3065 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
3066 IN PVOID UserApcContext OPTIONAL,
3067 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
3068 IN FILE_SEGMENT_ELEMENT BufferDescription [],
3072{
3075}
3076
3077/*
3078 * @unimplemented
3079 */
3081NTAPI
3085 IN ULONG EaBufferSize)
3086{
3089}
3090
3091/*
3092 * @implemented
3093 */
3095NTAPI
3099 IN ULONG Length,
3101{
3104 PIRP Irp;
3106 PIO_STACK_LOCATION StackPtr;
3108 PKEVENT Event = NULL;
3109 BOOLEAN LocalEvent = FALSE;
3110 PKNORMAL_ROUTINE NormalRoutine;
3111 PVOID NormalContext;
3112 KIRQL OldIrql;
3113 IO_STATUS_BLOCK KernelIosb;
3114 PVOID Queue;
3117 PFILE_RENAME_INFORMATION RenameInfo;
3119 PAGED_CODE();
3120 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
3121
3122 /* Check if we're called from user mode */
3123 if (PreviousMode != KernelMode)
3124 {
3125 /* Validate the information class */
3126 if ((FileInformationClass < 0) ||
3129 {
3130 /* Invalid class */
3132 }
3133
3134 /* Validate the length */
3136 {
3137 /* Invalid length */
3139 }
3140
3141 /* Enter SEH for probing */
3142 _SEH2_TRY
3143 {
3144 /* Probe the I/O Status block */
3146
3147 /* Probe the information */
3149 Length,
3150 (Length == sizeof(BOOLEAN)) ?
3151 sizeof(BOOLEAN) : sizeof(ULONG));
3152 }
3154 {
3155 /* Return the exception code */
3157 }
3158 _SEH2_END;
3159 }
3160 else
3161 {
3162 /* Validate the information class */
3163 if ((FileInformationClass < 0) ||
3166 {
3167 /* Invalid class */
3169 }
3170
3171 /* Validate the length */
3173 {
3174 /* Invalid length */
3176 }
3177 }
3178
3179 /* Reference the Handle */
3185 (PVOID *)&FileObject,
3186 NULL);
3187 if (!NT_SUCCESS(Status)) return Status;
3188
3189 /* Check if this is a direct open or not */
3190 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3191 {
3192 /* Get the device object */
3194 }
3195 else
3196 {
3197 /* Get the device object */
3199 }
3200
3201 DPRINT("Will call: %p\n", DeviceObject);
3202 DPRINT("Associated driver: %p (%wZ)\n", DeviceObject->DriverObject, &DeviceObject->DriverObject->DriverName);
3203
3204 /* Check if this is a file that was opened for Synch I/O */
3205 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3206 {
3207 /* Lock it */
3209 if (Status != STATUS_SUCCESS)
3210 {
3212 return Status;
3213 }
3214
3215 /* Check if the caller just wants the position */
3217 {
3218 /* Protect write in SEH */
3219 _SEH2_TRY
3220 {
3221 /* Write the offset */
3222 FileObject->CurrentByteOffset =
3224 CurrentByteOffset;
3225
3226 /* Fill out the I/O Status Block */
3229 }
3231 {
3232 /* Get the exception code */
3234 }
3235 _SEH2_END;
3236
3237 /* Update transfer count */
3239
3240 /* Release the file lock, dereference the file and return */
3243 return Status;
3244 }
3245 }
3246 else
3247 {
3248 /* Use local event */
3250 if (!Event)
3251 {
3254 }
3255
3257 LocalEvent = TRUE;
3258 }
3259
3260 /* Clear the File Object event */
3261 KeClearEvent(&FileObject->Event);
3262
3263 /* Allocate the IRP */
3264 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
3266
3267 /* Set the IRP */
3268 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3269 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3270 Irp->RequestorMode = PreviousMode;
3271 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
3272 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3273 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
3274 Irp->UserEvent = (LocalEvent) ? Event : NULL;
3275 Irp->AssociatedIrp.SystemBuffer = NULL;
3276 Irp->MdlAddress = NULL;
3277 Irp->UserBuffer = FileInformation;
3278
3279 /* Set the Stack Data */
3280 StackPtr = IoGetNextIrpStackLocation(Irp);
3282 StackPtr->FileObject = FileObject;
3283
3284 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
3285 _SEH2_TRY
3286 {
3287 /* Allocate a buffer */
3288 Irp->AssociatedIrp.SystemBuffer =
3290
3291 /* Copy the data into it */
3292 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
3294 Length);
3295 }
3297 {
3298 /* Allocating failed, clean up and return the exception code */
3301 }
3302 _SEH2_END;
3303
3304 /* Set the flags */
3305 Irp->Flags |= (IRP_BUFFERED_IO |
3308
3309 /* Set the Parameters */
3310 StackPtr->Parameters.SetFile.FileInformationClass = FileInformationClass;
3311 StackPtr->Parameters.SetFile.Length = Length;
3312
3313 /* Queue the IRP */
3315
3316 /* Update operation counts */
3318
3319 /* FIXME: Later, we can implement a lot of stuff here and avoid a driver call */
3320 /* Handle IO Completion Port quickly */
3322 {
3323 /* Check if the file object already has a completion port */
3324 if ((FileObject->Flags & FO_SYNCHRONOUS_IO) ||
3325 (FileObject->CompletionContext))
3326 {
3327 /* Fail */
3329 }
3330 else
3331 {
3332 /* Reference the Port */
3333 CompletionInfo = Irp->AssociatedIrp.SystemBuffer;
3334 Status = ObReferenceObjectByHandle(CompletionInfo->Port,
3338 (PVOID*)&Queue,
3339 NULL);
3340 if (NT_SUCCESS(Status))
3341 {
3342 /* Allocate the Context */
3344 sizeof(IO_COMPLETION_CONTEXT),
3345 IOC_TAG);
3346 if (Context)
3347 {
3348 /* Set the Data */
3349 Context->Key = CompletionInfo->Key;
3350 Context->Port = Queue;
3353 Context,
3354 NULL))
3355 {
3356 /*
3357 * Someone else set the completion port in the
3358 * meanwhile, so dereference the port and fail.
3359 */
3363 }
3364 }
3365 else
3366 {
3367 /* Dereference the Port now */
3370 }
3371 }
3372 }
3373
3374 /* Set the IRP Status */
3375 Irp->IoStatus.Status = Status;
3376 Irp->IoStatus.Information = 0;
3377 }
3381 {
3382 /* Get associated information */
3383 RenameInfo = Irp->AssociatedIrp.SystemBuffer;
3384
3385 /* Only rename if:
3386 * -> We have a name
3387 * -> In unicode
3388 * -> sizes are valid
3389 */
3390 if (RenameInfo->FileNameLength != 0 &&
3391 !(RenameInfo->FileNameLength & 1) &&
3393 {
3394 /* Properly set information received */
3396 {
3397 StackPtr->Parameters.SetFile.ClusterCount = ((PFILE_MOVE_CLUSTER_INFORMATION)RenameInfo)->ClusterCount;
3398 }
3399 else
3400 {
3401 StackPtr->Parameters.SetFile.ReplaceIfExists = RenameInfo->ReplaceIfExists;
3402 }
3403
3404 /* If we got fully path OR relative target, attempt a parent directory open */
3405 if (RenameInfo->FileName[0] == OBJ_NAME_PATH_SEPARATOR || RenameInfo->RootDirectory)
3406 {
3408 if (!NT_SUCCESS(Status))
3409 {
3410 Irp->IoStatus.Status = Status;
3411 }
3412 else
3413 {
3414 /* Call the Driver */
3416 }
3417 }
3418 else
3419 {
3420 /* Call the Driver */
3422 }
3423 }
3424 else
3425 {
3427 Irp->IoStatus.Status = Status;
3428 }
3429 }
3430 else
3431 {
3432 /* Call the Driver */
3434 }
3435
3436 /* Check if we're waiting for the IRP to complete */
3437 if (Status == STATUS_PENDING)
3438 {
3439 /* Check if this was async I/O */
3440 if (LocalEvent)
3441 {
3442 /* Then to a non-alertable wait */
3444 Executive,
3446 FALSE,
3447 NULL);
3448 if (Status == STATUS_USER_APC)
3449 {
3450 /* Abort the request */
3452 }
3453
3454 /* Set the final status */
3455 Status = KernelIosb.Status;
3456
3457 /* Enter SEH to write the IOSB back */
3458 _SEH2_TRY
3459 {
3460 /* Write it back to the caller */
3461 *IoStatusBlock = KernelIosb;
3462 }
3464 {
3465 /* Get the exception code */
3467 }
3468 _SEH2_END;
3469
3470 /* Free the event */
3472 }
3473 else
3474 {
3475 /* Wait for the IRP */
3477 Executive,
3479 (FileObject->Flags &
3480 FO_ALERTABLE_IO) != 0,
3481 NULL);
3483 {
3484 /* Abort the request */
3486 }
3487
3488 /* Set the final status */
3489 Status = FileObject->FinalStatus;
3490
3491 /* Release the file lock */
3493 }
3494 }
3495 else
3496 {
3497 /* Free the event if we had one */
3498 if (LocalEvent)
3499 {
3500 /* Clear it in the IRP for completion */
3501 Irp->UserEvent = NULL;
3503 }
3504
3505 /* Set the caller IOSB */
3506 Irp->UserIosb = IoStatusBlock;
3507
3508 /* The IRP wasn't completed, complete it ourselves */
3509 NormalRoutine = NULL;
3510 NormalContext = NULL;
3512 IopCompleteRequest(&Irp->Tail.Apc,
3513 &NormalRoutine,
3514 &NormalContext,
3515 (PVOID*)&FileObject,
3516 &NormalContext);
3518
3519 /* Release the file object if we had locked it*/
3520 if (!LocalEvent) IopUnlockFileObject(FileObject);
3521 }
3522
3523 if (TargetHandle != NULL)
3524 {
3526 }
3527
3528 /* Return the Status */
3529 return Status;
3530}
3531
3532/*
3533 * @unimplemented
3534 */
3536NTAPI
3539 IN PVOID Buffer,
3541{
3544}
3545
3546/*
3547 * @implemented
3548 */
3550NTAPI
3556{
3558 PLARGE_INTEGER LocalLength = NULL;
3559 PIRP Irp;
3560 PIO_STACK_LOCATION StackPtr;
3562 PKEVENT Event = NULL;
3563 BOOLEAN LocalEvent = FALSE;
3565 LARGE_INTEGER CapturedByteOffset, CapturedLength;
3568 IO_STATUS_BLOCK KernelIosb;
3570 PAGED_CODE();
3571 CapturedByteOffset.QuadPart = 0;
3572 CapturedLength.QuadPart = 0;
3573 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
3574
3575 /* Get File Object */
3577 0,
3580 (PVOID*)&FileObject,
3582 if (!NT_SUCCESS(Status)) return Status;
3583
3584 /* Check if we're called from user mode */
3585 if (PreviousMode != KernelMode)
3586 {
3587 /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */
3588 if (!(HandleInformation.GrantedAccess &
3590 {
3592 return STATUS_ACCESS_DENIED;
3593 }
3594
3595 /* Enter SEH for probing */
3596 _SEH2_TRY
3597 {
3598 /* Probe the I/O Status block */
3600
3601 /* Probe and capture the large integers */
3602 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
3603 CapturedLength = ProbeForReadLargeInteger(Length);
3604 }
3606 {
3607 /* Dereference the object and return exception code */
3610 }
3611 _SEH2_END;
3612 }
3613 else
3614 {
3615 /* Otherwise, capture them directly */
3616 CapturedByteOffset = *ByteOffset;
3617 CapturedLength = *Length;
3618 }
3619
3620 /* Check if this is a direct open or not */
3621 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
3622 {
3624 }
3625 else
3626 {
3628 }
3629
3630 /* Try to do it the FastIO way if possible */
3631 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
3633 {
3635 &CapturedByteOffset,
3636 &CapturedLength,
3638 Key,
3639 &KernelIosb,
3640 DeviceObject))
3641 {
3642 /* Write the IOSB back */
3643 _SEH2_TRY
3644 {
3645 *IoStatusBlock = KernelIosb;
3646 }
3648 {
3649 KernelIosb.Status = _SEH2_GetExceptionCode();
3650 }
3651 _SEH2_END;
3652
3653 /* We're done with FastIO! */
3655 return KernelIosb.Status;
3656 }
3657 }
3658
3659 /* Check if we should use Sync IO or not */
3660 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3661 {
3662 /* Lock it */
3664 if (Status != STATUS_SUCCESS)
3665 {
3667 return Status;
3668 }
3669 }
3670 else
3671 {
3672 /* Use local event */
3674 if (!Event)
3675 {
3678 }
3680 LocalEvent = TRUE;
3681 }
3682
3683 /* Clear File Object event */
3684 KeClearEvent(&FileObject->Event);
3685
3686 /* Allocate the IRP */
3687 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
3689
3690 /* Set up the IRP */
3691 Irp->RequestorMode = PreviousMode;
3692 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
3693 Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
3694 Irp->UserEvent = (LocalEvent) ? Event : NULL;
3695 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3696 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3697 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
3698
3699 /* Set up Stack Data */
3700 StackPtr = IoGetNextIrpStackLocation(Irp);
3703 StackPtr->FileObject = FileObject;
3704
3705 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
3706 _SEH2_TRY
3707 {
3708 /* Allocate a buffer */
3710 sizeof(LARGE_INTEGER),
3711 TAG_LOCK);
3712
3713 /* Set the length */
3714 *LocalLength = CapturedLength;
3715 Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength;
3716 StackPtr->Parameters.LockControl.Length = LocalLength;
3717 }
3719 {
3720 /* Allocating failed, clean up and return the exception code */
3722 if (LocalLength) ExFreePoolWithTag(LocalLength, TAG_LOCK);
3723
3724 /* Return the exception code */
3726 }
3727 _SEH2_END;
3728
3729 /* Set Parameters */
3730 StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset;
3731 StackPtr->Parameters.LockControl.Key = Key;
3732
3733 /* Call the Driver */
3735 Irp,
3736 FileObject,
3737 FALSE,
3739 !LocalEvent,
3741
3742 /* Check if this was async I/O */
3743 if (LocalEvent)
3744 {
3745 /* It was, finalize this request */
3747 Event,
3748 Irp,
3750 &KernelIosb,
3752 }
3753
3754 /* Return status */
3755 return Status;
3756}
3757
3758/*
3759 * @implemented
3760 */
3762NTAPI
3768 IN PVOID Buffer,
3769 IN ULONG Length,
3772{
3775 PIRP Irp;
3777 PIO_STACK_LOCATION StackPtr;
3779 PKEVENT EventObject = NULL;
3780 LARGE_INTEGER CapturedByteOffset;
3781 ULONG CapturedKey = 0;
3782 BOOLEAN Synchronous = FALSE;
3783 PMDL Mdl;
3784 OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
3786 IO_STATUS_BLOCK KernelIosb;
3788
3789 PAGED_CODE();
3790 CapturedByteOffset.QuadPart = 0;
3791 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
3792
3793 /* Get File Object for write */
3796 &FileObject,
3797 &ObjectHandleInfo);
3798 if (!NT_SUCCESS(Status)) return Status;
3799
3800 /* Get the device object */
3802
3803 /* Validate User-Mode Buffers */
3804 if (PreviousMode != KernelMode)
3805 {
3806 _SEH2_TRY
3807 {
3808 /* Probe the status block */
3810
3811 /* Probe the read buffer */
3813
3814 /* Check if we got a byte offset */
3815 if (ByteOffset)
3816 {
3817 /* Capture and probe it */
3818 CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset);
3819 }
3820
3821 /* Can't use an I/O completion port and an APC at the same time */
3822 if ((FileObject->CompletionContext) && (ApcRoutine))
3823 {
3824 /* Fail */
3827 }
3828
3829 /* Perform additional checks for non-cached file access */
3831 {
3832 /* Fail if Length is not sector size aligned
3833 * Perform a quick check for 2^ sector sizes
3834 * If it fails, try a more standard way
3835 */
3836 if ((DeviceObject->SectorSize != 0) &&
3837 ((DeviceObject->SectorSize - 1) & Length) != 0)
3838 {
3839 if (Length % DeviceObject->SectorSize != 0)
3840 {
3841 /* Release the file object and and fail */
3844 }
3845 }
3846
3847 /* Fail if buffer doesn't match alignment requirements */
3848 if (((ULONG_PTR)Buffer & DeviceObject->AlignmentRequirement) != 0)
3849 {
3850 /* Release the file object and and fail */
3853 }
3854
3855 if (ByteOffset)
3856 {
3857 /* Fail if ByteOffset is not sector size aligned */
3858 if ((DeviceObject->SectorSize != 0) &&
3859 (CapturedByteOffset.QuadPart % DeviceObject->SectorSize != 0))
3860 {
3861 /* Only if that's not specific values for synchronous IO */
3862 if ((CapturedByteOffset.QuadPart != FILE_WRITE_TO_END_OF_FILE) &&
3863 (CapturedByteOffset.QuadPart != FILE_USE_FILE_POINTER_POSITION ||
3865 {
3866 /* Release the file object and and fail */
3869 }
3870 }
3871 }
3872 }
3873
3874 /* Capture and probe the key */
3875 if (Key) CapturedKey = ProbeForReadUlong(Key);
3876 }
3878 {
3879 /* Release the file object and return the exception code */
3882 }
3883 _SEH2_END;
3884 }
3885 else
3886 {
3887 /* Kernel mode: capture directly */
3888 if (ByteOffset) CapturedByteOffset = *ByteOffset;
3889 if (Key) CapturedKey = *Key;
3890 }
3891
3892 /* Check for invalid offset */
3893 if (CapturedByteOffset.QuadPart < -2)
3894 {
3895 /* -1 is FILE_WRITE_TO_END_OF_FILE */
3896 /* -2 is FILE_USE_FILE_POINTER_POSITION */
3899 }
3900
3901 /* Check if this is an append operation */
3902 if ((ObjectHandleInfo.GrantedAccess &
3904 {
3905 /* Give the drivers something to understand */
3906 CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE;
3907 CapturedByteOffset.u.HighPart = -1;
3908 }
3909
3910 /* Check for event */
3911 if (Event)
3912 {
3913 /* Reference it */
3918 (PVOID*)&EventObject,
3919 NULL);
3920 if (!NT_SUCCESS(Status))
3921 {
3922 /* Fail */
3924 return Status;
3925 }
3926
3927 /* Otherwise reset the event */
3928 KeClearEvent(EventObject);
3929 }
3930
3931 /* Check if we should use Sync IO or not */
3932 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
3933 {
3934 /* Lock the file object */
3936 if (Status != STATUS_SUCCESS)
3937 {
3938 if (EventObject) ObDereferenceObject(EventObject);
3940 return Status;
3941 }
3942
3943 /* Check if we don't have a byte offset available */
3944 if (!(ByteOffset) ||
3945 ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) &&
3946 (CapturedByteOffset.u.HighPart == -1)))
3947 {
3948 /* Use the Current Byte Offset instead */
3949 CapturedByteOffset = FileObject->CurrentByteOffset;
3950 }
3951
3952 /* If the file is cached, try fast I/O */
3953 if (FileObject->PrivateCacheMap)
3954 {
3955 /* Perform fast write */
3956 FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch;
3958
3960 &CapturedByteOffset,
3961 Length,
3962 TRUE,
3963 CapturedKey,
3964 Buffer,
3965 &KernelIosb,
3966 DeviceObject);
3967
3968 /* Only accept the result if it was successful */
3969 if (Success &&
3970 KernelIosb.Status == STATUS_SUCCESS)
3971 {
3972 /* Fast path -- update transfer & operation counts */
3975 (ULONG)KernelIosb.Information);
3976
3977 /* Enter SEH to write the IOSB back */
3978 _SEH2_TRY
3979 {
3980 /* Write it back to the caller */
3981 *IoStatusBlock = KernelIosb;
3982 }
3984 {
3985 /* The caller's IOSB was invalid, so fail */
3986 if (EventObject) ObDereferenceObject(EventObject);
3990 }
3991 _SEH2_END;
3992
3993 /* Signal the completion event */
3994 if (EventObject)
3995 {
3996 KeSetEvent(EventObject, 0, FALSE);
3997 ObDereferenceObject(EventObject);
3998 }
3999
4000 /* Clean up */
4003 return KernelIosb.Status;
4004 }
4005 }
4006
4007 /* Remember we are sync */
4008 Synchronous = TRUE;
4009 }
4010 else if (!(ByteOffset) &&
4011 !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT)))
4012 {
4013 /* Otherwise, this was async I/O without a byte offset, so fail */
4014 if (EventObject) ObDereferenceObject(EventObject);
4017 }
4018
4019 /* Clear the File Object's event */
4020 KeClearEvent(&FileObject->Event);
4021
4022 /* Allocate the IRP */
4023 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
4024 if (!Irp) return IopCleanupFailedIrp(FileObject, EventObject, NULL);
4025
4026 /* Set the IRP */
4027 Irp->Tail.Overlay.OriginalFileObject = FileObject;
4028 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
4029 Irp->RequestorMode = PreviousMode;
4030 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
4031 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
4032 Irp->UserIosb = IoStatusBlock;
4033 Irp->UserEvent = EventObject;
4034 Irp->PendingReturned = FALSE;
4035 Irp->Cancel = FALSE;
4036 Irp->CancelRoutine = NULL;
4037 Irp->AssociatedIrp.SystemBuffer = NULL;
4038 Irp->MdlAddress = NULL;
4039
4040 /* Set the Stack Data */
4041 StackPtr = IoGetNextIrpStackLocation(Irp);
4042 StackPtr->MajorFunction = IRP_MJ_WRITE;
4043 StackPtr->FileObject = FileObject;
4044 StackPtr->Flags = FileObject->Flags & FO_WRITE_THROUGH ?
4045 SL_WRITE_THROUGH : 0;
4046 StackPtr->Parameters.Write.Key = CapturedKey;
4047 StackPtr->Parameters.Write.Length = Length;
4048 StackPtr->Parameters.Write.ByteOffset = CapturedByteOffset;
4049
4050 /* Check if this is buffered I/O */
4051 if (DeviceObject->Flags & DO_BUFFERED_IO)
4052 {
4053 /* Check if we have a buffer length */
4054 if (Length)
4055 {
4056 /* Enter SEH (ExAllocatePoolWithQuotaTag raises on failure!) */
4057 _SEH2_TRY
4058 {
4059 /* Allocate a buffer */
4060 Irp->AssociatedIrp.SystemBuffer =
4062
4063 /* Copy the data into it */
4064 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length);
4065 }
4067 {
4068 /* Allocating failed, clean up and return the exception code */
4071 }
4072 _SEH2_END;
4073
4074 /* Set the flags */
4076 }
4077 else
4078 {
4079 /* Not writing anything */
4080 Irp->Flags = IRP_BUFFERED_IO;
4081 }
4082 }
4083 else if (DeviceObject->Flags & DO_DIRECT_IO)
4084 {
4085 /* Check if we have a buffer length */
4086 if (Length)
4087 {
4088 _SEH2_TRY
4089 {
4090 /* Allocate an MDL */
4092 if (!Mdl)
4095 }
4097 {
4098 /* Allocating failed, clean up and return the exception code */
4101 }
4102 _SEH2_END;
4103 }
4104
4105 /* No allocation flags */
4106 Irp->Flags = 0;
4107 }
4108 else
4109 {
4110 /* No allocation flags, and use the buffer directly */
4111 Irp->Flags = 0;
4112 Irp->UserBuffer = Buffer;
4113 }
4114
4115 /* Now set the deferred read flags */
4117
4119
4120 /* Perform the call */
4122 Irp,
4123 FileObject,
4124 TRUE,
4126 Synchronous,
4128}
4129
4131NTAPI
4134 IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
4135 IN PVOID UserApcContext OPTIONAL,
4136 OUT PIO_STATUS_BLOCK UserIoStatusBlock,
4137 IN FILE_SEGMENT_ELEMENT BufferDescription [],
4141{
4144}
4145
4146/*
4147 * @implemented
4148 */
4150NTAPI
4153 OUT PVOID FsInformation,
4154 IN ULONG Length,
4156{
4158 PIRP Irp;
4159 PIO_STACK_LOCATION StackPtr;
4161 PKEVENT Event = NULL;
4162 BOOLEAN LocalEvent = FALSE;
4165 IO_STATUS_BLOCK KernelIosb;
4166 PAGED_CODE();
4167 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
4168
4169 /* Check if we're called from user mode */
4170 if (PreviousMode != KernelMode)
4171 {
4172 /* Validate the information class */
4173 if ((FsInformationClass < 0) ||
4176 {
4177 /* Invalid class */
4179 }
4180
4181 /* Validate the length */
4183 {
4184 /* Invalid length */
4186 }
4187
4188 /* Enter SEH for probing */
4189 _SEH2_TRY
4190 {
4191 /* Probe the I/O Status block */
4193
4194 /* Probe the information */
4195 ProbeForWrite(FsInformation, Length, sizeof(ULONG));
4196 }
4198 {
4199 /* Return the exception code */
4201 }
4202 _SEH2_END;
4203 }
4204
4205 /* Get File Object */
4211 (PVOID*)&FileObject,
4212 NULL);
4213 if (!NT_SUCCESS(Status)) return Status;
4214
4215 /* Only allow direct device open for FileFsDeviceInformation */
4218 {
4221 }
4222
4223 /* Check if we should use Sync IO or not */
4224 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
4225 {
4226 /* Lock it */
4228 if (Status != STATUS_SUCCESS)
4229 {
4231 return Status;
4232 }
4233 }
4234
4235 /*
4236 * Quick path for FileFsDeviceInformation - the kernel has enough
4237 * info to reply instead of the driver, excepted for network file systems
4238 */
4241 {
4242 PFILE_FS_DEVICE_INFORMATION FsDeviceInfo = FsInformation;
4243 DeviceObject = FileObject->DeviceObject;
4244
4245 _SEH2_TRY
4246 {
4247 FsDeviceInfo->DeviceType = DeviceObject->DeviceType;
4248
4249 /* Complete characteristcs with mount status if relevant */
4250 FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
4252 {
4254 }
4255
4258 }
4260 {
4261 /* Check if we had a file lock */
4263 {
4264 /* Release it */