ReactOS 0.4.15-dev-7924-g5949c20
file.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/file.c
5 * PURPOSE: Functions that deal with managing the FILE_OBJECT itself.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Gunnar Dalsnes
8 * Eric Kohl
9 * Filip Navara (navaraf@reactos.org)
10 * Pierre Schweitzer
11 */
12
13/* INCLUDES *****************************************************************/
14
15#include <ntoskrnl.h>
16#define NDEBUG
17#include <debug.h>
18
20
21/* PRIVATE FUNCTIONS *********************************************************/
22
23VOID
29{
32 BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE;
33 PAGED_CODE();
34
35 /* Don't do anything if privileges were checked already */
36 if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return;
37
38 /* Check if the file was actually opened for backup purposes */
40 {
41 /* Set the check flag since were doing it now */
43
44 /* Set the access masks required */
55 DELETE;
56 DesiredAccess = AccessState->RemainingDesiredAccess;
57
58 /* Check if desired access was the maximum */
60 {
61 /* Then add all the access masks required */
63 }
64
65 /* Check if the file already exists */
67 {
68 /* Check if desired access has the read mask */
70 {
71 /* Setup the privilege check lookup */
72 Privileges.PrivilegeCount = 1;
74 Privileges.Privilege[0].Luid = SeBackupPrivilege;
75 Privileges.Privilege[0].Attributes = 0;
80 if (AccessGranted)
81 {
82 /* Remember that backup was allowed */
83 HaveBackupPriv = TRUE;
84
85 /* Append the privileges and update the access state */
87 AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess);
88 AccessState->RemainingDesiredAccess &= ~ReadAccess;
89 DesiredAccess &= ~ReadAccess;
90
91 /* Set backup privilege for the token */
93 }
94 }
95 }
96 else
97 {
98 /* Caller is creating the file, check restore privileges later */
99 CheckRestore = TRUE;
100 }
101
102 /* Check if caller wants write access or if it's creating a file */
103 if ((WriteAccess & DesiredAccess) || (CheckRestore))
104 {
105 /* Setup the privilege lookup and do it */
106 Privileges.PrivilegeCount = 1;
108 Privileges.Privilege[0].Luid = SeRestorePrivilege;
109 Privileges.Privilege[0].Attributes = 0;
111 &AccessState->SubjectSecurityContext,
113 if (AccessGranted)
114 {
115 /* Remember that privilege was given */
116 HaveBackupPriv = TRUE;
117
118 /* Append the privileges and update the access state */
120 AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess);
121 AccessState->RemainingDesiredAccess &= ~WriteAccess;
122
123 /* Set restore privilege for the token */
125 }
126 }
127
128 /* If we don't have the privilege, remove the option */
129 if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
130 }
131}
132
134NTAPI
137{
138 /* Make sure the object is valid */
139 if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags &
145 {
146 /* It's unloading or initializing, so fail */
147 DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
148 " sucks. Please fix it's AddDevice Routine\n",
149 &DeviceObject->DriverObject->DriverName);
151 }
152 else if ((DeviceObject->Flags & DO_EXCLUSIVE) &&
153 (DeviceObject->ReferenceCount) &&
154 !(OpenPacket->RelatedFileObject) &&
155 !(OpenPacket->Options & IO_ATTACH_DEVICE))
156 {
158 }
159
160 else
161 {
162 /* Increase reference count */
163 InterlockedIncrement(&DeviceObject->ReferenceCount);
164 return STATUS_SUCCESS;
165 }
166}
167
168VOID
169NTAPI
172 IN PREPARSE_DATA_BUFFER DataBuffer)
173{
177 PWSTR NewBuffer;
178
179 PAGED_CODE();
180
181 ASSERT(Irp->IoStatus.Status == STATUS_REPARSE);
182 ASSERT(Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT);
183 ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
184 ASSERT(DataBuffer != NULL);
185 ASSERT(DataBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
186 ASSERT(DataBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
187 ASSERT(DataBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
188
189 /* First of all, validate data */
190 if (DataBuffer->ReparseDataLength < REPARSE_DATA_BUFFER_HEADER_SIZE ||
191 (DataBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
192 DataBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength +
194 {
195 Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
196 }
197
198 /* Everything went right */
199 if (NT_SUCCESS(Irp->IoStatus.Status))
200 {
201 /* Compute buffer & length */
202 Buffer = (PWSTR)((ULONG_PTR)DataBuffer->MountPointReparseBuffer.PathBuffer +
203 DataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
204 Length = DataBuffer->MountPointReparseBuffer.SubstituteNameLength;
205
206 /* Check we don't overflow */
207 if (((ULONG)MAXUSHORT - DataBuffer->Reserved) <= (Length + sizeof(UNICODE_NULL)))
208 {
209 Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
210 }
211 else
212 {
213 /* Compute how much memory we'll need */
214 RequiredLength = DataBuffer->Reserved + Length + sizeof(UNICODE_NULL);
215
216 /* Check if FileObject can already hold what we need */
217 if (FileObject->FileName.MaximumLength >= RequiredLength)
218 {
219 NewBuffer = FileObject->FileName.Buffer;
220 }
221 else
222 {
223 /* Allocate otherwise */
225 if (NewBuffer == NULL)
226 {
227 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
228 }
229 }
230 }
231 }
232
233 /* Everything went right */
234 if (NT_SUCCESS(Irp->IoStatus.Status))
235 {
236 /* Copy the reserved data */
237 if (DataBuffer->Reserved)
238 {
239 RtlMoveMemory((PWSTR)((ULONG_PTR)NewBuffer + Length),
240 (PWSTR)((ULONG_PTR)FileObject->FileName.Buffer + FileObject->FileName.Length - DataBuffer->Reserved),
241 DataBuffer->Reserved);
242 }
243
244 /* Then the buffer */
245 if (Length)
246 {
247 RtlCopyMemory(NewBuffer, Buffer, Length);
248 }
249
250 /* And finally replace buffer if new one was allocated */
251 FileObject->FileName.Length = RequiredLength - sizeof(UNICODE_NULL);
252 if (NewBuffer != FileObject->FileName.Buffer)
253 {
254 if (FileObject->FileName.Buffer)
255 {
256 /*
257 * Don't use TAG_IO_NAME since the FileObject's FileName
258 * may have been re-allocated using a different tag
259 * by a filesystem.
260 */
261 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
262 }
263
264 FileObject->FileName.Buffer = NewBuffer;
265 FileObject->FileName.MaximumLength = RequiredLength;
266 FileObject->FileName.Buffer[RequiredLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
267 }
268 }
269
270 /* We don't need them anymore - it was allocated by the driver */
271 ExFreePool(DataBuffer);
272}
273
276 IN POPEN_PACKET OpenPacket,
277 BOOLEAN DirectOpen)
278{
281
283
284 /* Direct open is not allowed */
285 if (DirectOpen)
286 {
288 }
289
290 /* Validate we have a file system device */
291 DeviceType = LocalDevice->DeviceType;
297 {
299 }
300
301 /* Verify the hint and if it's OK, return it */
302 if (IopVerifyDeviceObjectOnStack(LocalDevice, OpenPacket->TopDeviceObjectHint))
303 {
304 *DeviceObject = OpenPacket->TopDeviceObjectHint;
305 return STATUS_SUCCESS;
306 }
307
308 /* Failure case here */
309 /* If we thought was had come through a mount point,
310 * actually update we didn't and return the error
311 */
312 if (OpenPacket->TraversedMountPoint)
313 {
314 OpenPacket->TraversedMountPoint = FALSE;
316 }
317
318 /* Otherwise, just return the fact the hint is invalid */
320}
321
323NTAPI
329 IN OUT PUNICODE_STRING CompleteName,
334{
335 POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;
336 PDEVICE_OBJECT OriginalDeviceObject = (PDEVICE_OBJECT)ParseObject;
337 PDEVICE_OBJECT DeviceObject, OwnerDevice;
340 PVPB Vpb = NULL;
341 PIRP Irp;
342 PIO_STACK_LOCATION StackLoc;
343 IO_SECURITY_CONTEXT SecurityContext;
345 BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile;
348 PDUMMY_FILE_OBJECT LocalFileObject;
349 PFILE_BASIC_INFORMATION FileBasicInfo;
351 KPROCESSOR_MODE CheckMode;
352 BOOLEAN VolumeOpen = FALSE;
354 BOOLEAN AccessGranted, LockHeld = FALSE;
356 UNICODE_STRING FileString;
357 USHORT Attempt;
358 IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n",
359 ParseObject, RemainingName);
360
361 for (Attempt = 0; Attempt < IOP_MAX_REPARSE_TRAVERSAL; ++Attempt)
362 {
363 /* Assume failure */
364 *Object = NULL;
365
366 /* Validate the open packet */
367 if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
368
369 /* Valide reparse point in case we traversed a mountpoint */
370 if (OpenPacket->TraversedMountPoint)
371 {
372 /* This is a reparse point we understand */
374
375 /* Make sure we're dealing with correct DO */
376 if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK &&
377 OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM &&
378 OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK &&
379 OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE)
380 {
383 }
384 }
385
386 /* Check if we have a related file object */
387 if (OpenPacket->RelatedFileObject)
388 {
389 /* Use the related file object's device object */
390 OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject;
391 }
392
393 /* Validate device status */
394 Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject);
395 if (!NT_SUCCESS(Status))
396 {
397 /* We failed, return status */
398 OpenPacket->FinalStatus = Status;
399 return Status;
400 }
401
402 /* Map the generic mask and set the new mapping in the access state */
403 RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
405 RtlMapGenericMask(&AccessState->OriginalDesiredAccess,
409 DesiredAccess = AccessState->RemainingDesiredAccess;
410
411 /* Check what kind of access checks to do */
412 if ((AccessMode != KernelMode) ||
413 (OpenPacket->Options & IO_FORCE_ACCESS_CHECK))
414 {
415 /* Call is from user-mode or kernel is forcing checks */
416 CheckMode = UserMode;
417 }
418 else
419 {
420 /* Call is from the kernel */
421 CheckMode = KernelMode;
422 }
423
424 /* Check privilege for backup or restore operation */
426 &OpenPacket->CreateOptions,
427 CheckMode,
428 OpenPacket->Disposition);
429
430 /* Check if we are re-parsing */
431 if (((OpenPacket->Override) && !(RemainingName->Length)) ||
433 {
434 /* Get granted access from the last call */
435 DesiredAccess |= AccessState->PreviouslyGrantedAccess;
436 }
437
438 /* Check if this is a volume open */
439 if ((OpenPacket->RelatedFileObject) &&
440 (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
441 !(RemainingName->Length))
442 {
443 /* It is */
444 VolumeOpen = TRUE;
445 }
446
447 /* Now check if we need access checks */
448 if (((AccessMode != KernelMode) ||
449 (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) &&
450 (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) &&
451 !(OpenPacket->Override))
452 {
455
456 /* Check if a device object is being parsed */
457 if (!RemainingName->Length)
458 {
459 /* Lock the subject context */
460 SeLockSubjectContext(&AccessState->SubjectSecurityContext);
461 LockHeld = TRUE;
462
463 /* Do access check */
464 AccessGranted = SeAccessCheck(OriginalDeviceObject->
466 &AccessState->SubjectSecurityContext,
467 LockHeld,
469 0,
470 &Privileges,
472 TypeInfo.GenericMapping,
473 UserMode,
475 &Status);
476 if (Privileges)
477 {
478 /* Append and free the privileges */
481 }
482
483 /* Check if we got access */
484 if (AccessGranted)
485 {
486 /* Update access state */
487 AccessState->PreviouslyGrantedAccess |= GrantedAccess;
488 AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
490 OpenPacket->Override= TRUE;
491 }
492
493 FileString.Length = 8;
494 FileString.MaximumLength = 8;
495 FileString.Buffer = L"File";
496
497 /* Do Audit/Alarm for open operation */
498 SeOpenObjectAuditAlarm(&FileString,
499 OriginalDeviceObject,
500 CompleteName,
501 OriginalDeviceObject->SecurityDescriptor,
503 FALSE,
505 UserMode,
506 &AccessState->GenerateOnClose);
507 }
508 else
509 {
510 /* Check if we need to do traverse validation */
512 ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
513 (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)))
514 {
515 /* Check if this is a restricted token */
516 if (!(AccessState->Flags & TOKEN_IS_RESTRICTED))
517 {
518 /* Do the FAST traverse check */
519 AccessGranted = SeFastTraverseCheck(OriginalDeviceObject->SecurityDescriptor,
522 UserMode);
523 }
524 else
525 {
526 /* Fail */
528 }
529
530 /* Check if we failed to get access */
531 if (!AccessGranted)
532 {
533 /* Lock the subject context */
534 SeLockSubjectContext(&AccessState->SubjectSecurityContext);
535 LockHeld = TRUE;
536
537 /* Do access check */
538 AccessGranted = SeAccessCheck(OriginalDeviceObject->
540 &AccessState->SubjectSecurityContext,
541 LockHeld,
543 0,
544 &Privileges,
546 TypeInfo.GenericMapping,
547 UserMode,
549 &Status);
550 if (Privileges)
551 {
552 /* Append and free the privileges */
555 }
556 }
557
558 /* FIXME: Do Audit/Alarm for traverse check */
559 }
560 else
561 {
562 /* Access automatically granted */
564 }
565 }
566
569
570 /* Check if we hold the lock */
571 if (LockHeld)
572 {
573 /* Release it */
574 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
575 }
576
577 /* Check if access failed */
578 if (!AccessGranted)
579 {
580 /* Dereference the device and fail */
581 DPRINT1("Traverse access failed!\n");
582 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
584 }
585 }
586
587 /* Check if we can simply use a dummy file */
588 UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
589
590 /* Check if this is a direct open */
591 if (!(RemainingName->Length) &&
592 !(OpenPacket->RelatedFileObject) &&
598 WRITE_DAC)) == 0) &&
599 !(UseDummyFile))
600 {
601 /* Remember this for later */
602 DirectOpen = TRUE;
603 }
604
605 /* Check if we have a related FO that wasn't a direct open */
606 if ((OpenPacket->RelatedFileObject) &&
607 !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
608 {
609 /* The device object is the one we were given */
610 DeviceObject = ParseObject;
611
612 /* Check if the related FO had a VPB */
613 if (OpenPacket->RelatedFileObject->Vpb)
614 {
615 /* Yes, remember it */
616 Vpb = OpenPacket->RelatedFileObject->Vpb;
617
618 /* Reference it */
619 InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
620
621 /* Check if we were given a specific top level device to use */
623 {
624 DeviceObject = Vpb->DeviceObject;
625 }
626 }
627 }
628 else
629 {
630 /* Check if it has a VPB */
631 if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
632 {
633 /* Check if the VPB is mounted, and mount it */
634 Vpb = IopCheckVpbMounted(OpenPacket,
635 OriginalDeviceObject,
637 &Status);
638 if (!Vpb) return Status;
639
640 /* Get the VPB's device object */
641 DeviceObject = Vpb->DeviceObject;
642 }
643 else
644 {
645 /* The device object is the one we were given */
646 DeviceObject = OriginalDeviceObject;
647 }
648
649 /* If we weren't given a specific top level device, look for an attached device */
650 if (!(OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) &&
651 DeviceObject->AttachedDevice)
652 {
653 /* Get the attached device */
655 }
656 }
657
658 /* If we have a top level device hint, verify it */
660 {
661 Status = IopCheckTopDeviceHint(&DeviceObject, OpenPacket, DirectOpen);
662 if (!NT_SUCCESS(Status))
663 {
664 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
666 return Status;
667 }
668 }
669
670 /* If we traversed a mount point, reset the information */
671 if (OpenPacket->TraversedMountPoint)
672 {
673 OpenPacket->TraversedMountPoint = FALSE;
674 }
675
676 /* Check if this is a secure FSD */
677 if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
678 ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
679 (!VolumeOpen))
680 {
682 GrantedAccess = 0;
683
686
687 /* Lock the subject context */
688 SeLockSubjectContext(&AccessState->SubjectSecurityContext);
689
690 /* Do access check */
691 AccessGranted = SeAccessCheck(OriginalDeviceObject->SecurityDescriptor,
692 &AccessState->SubjectSecurityContext,
693 TRUE,
695 0,
696 &Privileges,
698 UserMode,
700 &Status);
701 if (Privileges != NULL)
702 {
703 /* Append and free the privileges */
706 }
707
708 /* Check if we got access */
709 if (GrantedAccess)
710 {
711 AccessState->PreviouslyGrantedAccess |= GrantedAccess;
712 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
713 }
714
715 FileString.Length = 8;
716 FileString.MaximumLength = 8;
717 FileString.Buffer = L"File";
718
719 /* Do Audit/Alarm for open operation
720 * NOTA: we audit target device object
721 */
722 SeOpenObjectAuditAlarm(&FileString,
724 CompleteName,
725 OriginalDeviceObject->SecurityDescriptor,
727 FALSE,
729 UserMode,
730 &AccessState->GenerateOnClose);
731
732 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
733
736
737 /* Check if access failed */
738 if (!AccessGranted)
739 {
740 /* Dereference the device and fail */
741 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
744 }
745 }
746
747 /* Allocate the IRP */
748 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
749 if (!Irp)
750 {
751 /* Dereference the device and VPB, then fail */
752 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
755 }
756
757 /* Now set the IRP data */
758 Irp->RequestorMode = AccessMode;
760 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
761 Irp->UserIosb = &IoStatusBlock;
762 Irp->MdlAddress = NULL;
763 Irp->PendingReturned = FALSE;
764 Irp->UserEvent = NULL;
765 Irp->Cancel = FALSE;
766 Irp->CancelRoutine = NULL;
767 Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
768
769 /* Setup the security context */
770 SecurityContext.SecurityQos = SecurityQos;
771 SecurityContext.AccessState = AccessState;
772 SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
773 SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
774
775 /* Get the I/O Stack location */
776 StackLoc = IoGetNextIrpStackLocation(Irp);
777 StackLoc->Control = 0;
778
779 /* Check what kind of file this is */
780 switch (OpenPacket->CreateFileType)
781 {
782 /* Normal file */
784
785 /* Set the major function and EA Length */
786 StackLoc->MajorFunction = IRP_MJ_CREATE;
787 StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;
788
789 /* Set the flags */
790 StackLoc->Flags = (UCHAR)OpenPacket->Options;
792 break;
793
794 /* Named pipe */
796
797 /* Set the named pipe MJ and set the parameters */
799 StackLoc->Parameters.CreatePipe.Parameters = OpenPacket->ExtraCreateParameters;
800 break;
801
802 /* Mailslot */
804
805 /* Set the mailslot MJ and set the parameters */
807 StackLoc->Parameters.CreateMailslot.Parameters = OpenPacket->ExtraCreateParameters;
808 break;
809 }
810
811 /* Set the common data */
812 Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
813 Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
814 StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
815 (OpenPacket->CreateOptions &
816 0xFFFFFF);
817 StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
818 StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
819 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
820
821 /* Check if we really need to create an object */
822 if (!UseDummyFile)
823 {
824 ULONG ObjectSize = sizeof(FILE_OBJECT);
825
826 /* Tag on space for a file object extension */
828 ObjectSize += sizeof(FILE_OBJECT_EXTENSION);
829
830 /* Create the actual file object */
832 NULL,
834 NULL,
835 NULL);
840 NULL,
841 ObjectSize,
842 0,
843 0,
844 (PVOID*)&FileObject);
845 if (!NT_SUCCESS(Status))
846 {
847 /* Create failed, free the IRP */
848 IoFreeIrp(Irp);
849
850 /* Dereference the device and VPB */
851 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
853
854 /* We failed, return status */
855 OpenPacket->FinalStatus = Status;
856 return Status;
857 }
858
859 /* Clear the file object */
860 RtlZeroMemory(FileObject, ObjectSize);
861
862 /* Check if this is Synch I/O */
863 if (OpenPacket->CreateOptions &
865 {
866 /* Set the synch flag */
868
869 /* Check if it's also alertable */
871 {
872 /* It is, set the alertable flag */
873 FileObject->Flags |= FO_ALERTABLE_IO;
874 }
875 }
876
877 /* Check if this is synch I/O */
878 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
879 {
880 /* Initialize the event */
882 }
883
884 /* Check if the caller requested no intermediate buffering */
886 {
887 /* Set the correct flag for the FSD to read */
889 }
890
891 /* Check if the caller requested write through support */
892 if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
893 {
894 /* Set the correct flag for the FSD to read */
896 }
897
898 /* Check if the caller says the file will be only read sequentially */
899 if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
900 {
901 /* Set the correct flag for the FSD to read */
903 }
904
905 /* Check if the caller believes the file will be only read randomly */
906 if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
907 {
908 /* Set the correct flag for the FSD to read */
910 }
911
912 /* Check if we were asked to setup a file object extension */
914 {
915 PFILE_OBJECT_EXTENSION FileObjectExtension;
916
917 /* Make sure the file object knows it has an extension */
919
920 /* Initialize file object extension */
921 FileObjectExtension = (PFILE_OBJECT_EXTENSION)(FileObject + 1);
922 FileObject->FileObjectExtension = FileObjectExtension;
923
924 /* Add the top level device which we'll send the request to */
926 {
927 FileObjectExtension->TopDeviceObjectHint = DeviceObject;
928 }
929 }
930 }
931 else
932 {
933 /* Use the dummy object instead */
934 LocalFileObject = OpenPacket->LocalFileObject;
935 RtlZeroMemory(LocalFileObject, sizeof(DUMMY_FILE_OBJECT));
936
937 /* Set it up */
938 FileObject = (PFILE_OBJECT)&LocalFileObject->ObjectHeader.Body;
939 LocalFileObject->ObjectHeader.Type = IoFileObjectType;
940 LocalFileObject->ObjectHeader.PointerCount = 1;
941 }
942
943 /* Setup the file header */
944 FileObject->Type = IO_TYPE_FILE;
945 FileObject->Size = sizeof(FILE_OBJECT);
946 FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
947 FileObject->DeviceObject = OriginalDeviceObject;
948
949 /* Check if this is a direct device open */
950 if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
951
952 /* Check if the caller wants case sensitivity */
954 {
955 /* Tell the driver about it */
957 }
958
959 /* Now set the file object */
960 Irp->Tail.Overlay.OriginalFileObject = FileObject;
961 StackLoc->FileObject = FileObject;
962
963 /* Check if the file object has a name */
964 if (RemainingName->Length)
965 {
966 /* Setup the unicode string */
967 FileObject->FileName.MaximumLength = RemainingName->Length + sizeof(WCHAR);
968 FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
969 FileObject->FileName.MaximumLength,
971 if (!FileObject->FileName.Buffer)
972 {
973 /* Failed to allocate the name, free the IRP */
974 IoFreeIrp(Irp);
975
976 /* Dereference the device object and VPB */
977 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
979
980 /* Clear the FO and dereference it */
981 FileObject->DeviceObject = NULL;
982 if (!UseDummyFile) ObDereferenceObject(FileObject);
983
984 /* Fail */
986 }
987 }
988
989 /* Copy the name */
991
992 /* Initialize the File Object event and set the FO */
994 OpenPacket->FileObject = FileObject;
995
996 /* Queue the IRP and call the driver */
999 if (Status == STATUS_PENDING)
1000 {
1001 /* Wait for the driver to complete the create */
1003 Executive,
1004 KernelMode,
1005 FALSE,
1006 NULL);
1007
1008 /* Get the new status */
1010 }
1011 else
1012 {
1013 /* We'll have to complete it ourselves */
1014 ASSERT(!Irp->PendingReturned);
1015 ASSERT(!Irp->MdlAddress);
1016
1017 /* Handle name change if required */
1018 if (Status == STATUS_REPARSE)
1019 {
1020 /* Check this is a mount point */
1021 if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)
1022 {
1023 PREPARSE_DATA_BUFFER ReparseData;
1024
1025 /* Reparse point attributes were passed by the driver in the auxiliary buffer */
1026 ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
1027 ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
1028
1032
1033 IopDoNameTransmogrify(Irp, FileObject, ReparseData);
1034 }
1035 }
1036
1037 /* Completion happens at APC_LEVEL */
1039
1040 /* Get the new I/O Status block ourselves */
1041 IoStatusBlock = Irp->IoStatus;
1043
1044 /* Manually signal the even, we can't have any waiters */
1045 FileObject->Event.Header.SignalState = 1;
1046
1047 /* Now that we've signaled the events, de-associate the IRP */
1049
1050 /* Check if the IRP had an input buffer */
1051 if ((Irp->Flags & IRP_BUFFERED_IO) &&
1052 (Irp->Flags & IRP_DEALLOCATE_BUFFER))
1053 {
1054 /* Free it. A driver might've tacked one on */
1055 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
1056 }
1057
1058 /* Free the IRP and bring the IRQL back down */
1059 IoFreeIrp(Irp);
1061 }
1062
1063 /* Copy the I/O Status */
1065
1066 /* The driver failed to create the file */
1067 if (!NT_SUCCESS(Status))
1068 {
1069 /* Check if we have a name and if so, free it */
1070 if (FileObject->FileName.Length)
1071 {
1072 /*
1073 * Don't use TAG_IO_NAME since the FileObject's FileName
1074 * may have been re-allocated using a different tag
1075 * by a filesystem.
1076 */
1077 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1078 FileObject->FileName.Buffer = NULL;
1079 FileObject->FileName.Length = 0;
1080 }
1081
1082 /* Clear its device object */
1083 FileObject->DeviceObject = NULL;
1084
1085 /* Save this now because the FO might go away */
1086 OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ?
1087 TRUE : FALSE;
1088
1089 /* Clear the file object in the open packet */
1090 OpenPacket->FileObject = NULL;
1091
1092 /* Dereference the file object */
1093 if (!UseDummyFile) ObDereferenceObject(FileObject);
1094
1095 /* Dereference the device object */
1096 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
1097
1098 /* Unless the driver cancelled the open, dereference the VPB */
1099 if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
1100
1101 /* Set the status and return */
1102 OpenPacket->FinalStatus = Status;
1103 return Status;
1104 }
1105 else if (Status == STATUS_REPARSE)
1106 {
1107 if (OpenPacket->Information == IO_REPARSE ||
1109 {
1110 /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
1111 if (CompleteName->MaximumLength < FileObject->FileName.Length)
1112 {
1113 PWSTR NewCompleteName;
1114
1115 /* Allocate a new buffer for the string */
1116 NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME);
1117 if (NewCompleteName == NULL)
1118 {
1121 }
1122
1123 /* Release the old one */
1124 if (CompleteName->Buffer != NULL)
1125 {
1126 /*
1127 * Don't use TAG_IO_NAME since the FileObject's FileName
1128 * may have been re-allocated using a different tag
1129 * by a filesystem.
1130 */
1131 ExFreePoolWithTag(CompleteName->Buffer, 0);
1132 }
1133
1134 /* And setup the new one */
1135 CompleteName->Buffer = NewCompleteName;
1136 CompleteName->MaximumLength = FileObject->FileName.Length;
1137 }
1138
1139 /* Copy our new complete name */
1140 RtlCopyUnicodeString(CompleteName, &FileObject->FileName);
1141
1142 if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
1143 {
1144 OpenPacket->RelatedFileObject = NULL;
1145 }
1146 }
1147
1148 /* Check if we have a name and if so, free it */
1149 if (FileObject->FileName.Length)
1150 {
1151 /*
1152 * Don't use TAG_IO_NAME since the FileObject's FileName
1153 * may have been re-allocated using a different tag
1154 * by a filesystem.
1155 */
1156 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1157 FileObject->FileName.Buffer = NULL;
1158 FileObject->FileName.Length = 0;
1159 }
1160
1161 /* Clear its device object */
1162 FileObject->DeviceObject = NULL;
1163
1164 /* Clear the file object in the open packet */
1165 OpenPacket->FileObject = NULL;
1166
1167 /* Dereference the file object */
1168 if (!UseDummyFile) ObDereferenceObject(FileObject);
1169
1170 /* Dereference the device object */
1171 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
1172
1173 /* Unless the driver cancelled the open, dereference the VPB */
1175
1176 if (OpenPacket->Information != IO_REMOUNT)
1177 {
1178 OpenPacket->RelatedFileObject = NULL;
1179
1180 /* Inform we traversed a mount point for later attempt */
1181 if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
1182 {
1183 OpenPacket->TraversedMountPoint = 1;
1184 }
1185
1186 /* In case we override checks, but got this on volume open, fail hard */
1187 if (OpenPacket->Override)
1188 {
1189 KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
1190 (ULONG_PTR)OriginalDeviceObject,
1192 (ULONG_PTR)CompleteName,
1193 OpenPacket->Information);
1194 }
1195
1196 /* Return to IO/OB so that information can be upgraded */
1197 return STATUS_REPARSE;
1198 }
1199
1200 /* Loop again and reattempt an opening */
1201 continue;
1202 }
1203
1204 break;
1205 }
1206
1207 if (Attempt == IOP_MAX_REPARSE_TRAVERSAL)
1208 return STATUS_UNSUCCESSFUL;
1209
1210 /* Get the owner of the File Object */
1211 OwnerDevice = IoGetRelatedDeviceObject(FileObject);
1212
1213 /*
1214 * It's possible that the device to whom we sent the IRP to
1215 * isn't actually the device that ended opening the file object
1216 * internally.
1217 */
1218 if (OwnerDevice != DeviceObject)
1219 {
1220 /* We have to de-reference the VPB we had associated */
1222
1223 /* And re-associate with the actual one */
1224 Vpb = FileObject->Vpb;
1225 if (Vpb) InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
1226 }
1227
1228 /* Make sure we are not using a dummy */
1229 if (!UseDummyFile)
1230 {
1231 /* Check if this was a volume open */
1232 if ((!(FileObject->RelatedFileObject) ||
1233 (FileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN)) &&
1234 !(FileObject->FileName.Length))
1235 {
1236 /* All signs point to it, but make sure it was actually an FSD */
1237 if ((OwnerDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
1238 (OwnerDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||
1239 (OwnerDevice->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) ||
1240 (OwnerDevice->DeviceType == FILE_DEVICE_FILE_SYSTEM))
1241 {
1242 /* The owner device is an FSD, so this is a volume open for real */
1243 FileObject->Flags |= FO_VOLUME_OPEN;
1244 }
1245 }
1246
1247 /* Reference the object and set the parse check */
1249 *Object = FileObject;
1250 OpenPacket->FinalStatus = IoStatusBlock.Status;
1251 OpenPacket->ParseCheck = TRUE;
1252 return OpenPacket->FinalStatus;
1253 }
1254 else
1255 {
1256 /* Check if this was a query */
1257 if (OpenPacket->QueryOnly)
1258 {
1259 /* Check if the caller wants basic info only */
1260 if (!OpenPacket->FullAttributes)
1261 {
1262 /* Allocate the buffer */
1263 FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool,
1264 sizeof(*FileBasicInfo),
1265 TAG_IO);
1266 if (FileBasicInfo)
1267 {
1268 /* Do the query */
1271 sizeof(*FileBasicInfo),
1272 FileBasicInfo,
1273 &ReturnLength);
1274 if (NT_SUCCESS(Status))
1275 {
1276 /* Copy the data */
1277 RtlCopyMemory(OpenPacket->BasicInformation,
1278 FileBasicInfo,
1279 ReturnLength);
1280 }
1281
1282 /* Free our buffer */
1283 ExFreePoolWithTag(FileBasicInfo, TAG_IO);
1284 }
1285 else
1286 {
1287 /* Fail */
1289 }
1290 }
1291 else
1292 {
1293 /* This is a full query */
1295 FileObject,
1298 OpenPacket->NetworkInformation,
1299 &ReturnLength);
1301 }
1302 }
1303
1304 /* Delete the file object */
1306
1307 /* Clear out the file */
1308 OpenPacket->FileObject = NULL;
1309
1310 /* Set and return status */
1311 OpenPacket->FinalStatus = Status;
1312 OpenPacket->ParseCheck = TRUE;
1313 return Status;
1314 }
1315}
1316
1318NTAPI
1324 IN OUT PUNICODE_STRING CompleteName,
1328 OUT PVOID *Object)
1329{
1331 POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;
1332
1333 /* Validate the open packet */
1334 if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
1335
1336 /* Get the device object */
1338 OpenPacket->RelatedFileObject = ParseObject;
1339
1340 /* Call the main routine */
1342 ObjectType,
1344 AccessMode,
1345 Attributes,
1346 CompleteName,
1348 OpenPacket,
1349 SecurityQos,
1350 Object);
1351}
1352
1353VOID
1354NTAPI
1356{
1357 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
1358 PIRP Irp;
1359 PIO_STACK_LOCATION StackPtr;
1361 KEVENT Event;
1363 BOOLEAN DereferenceDone = FALSE;
1364 PVPB Vpb;
1365 KIRQL OldIrql;
1366 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1367
1368 /* Check if the file has a device object */
1369 if (FileObject->DeviceObject)
1370 {
1371 /* Check if this is a direct open or not */
1372 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1373 {
1374 /* Get the attached device */
1376 }
1377 else
1378 {
1379 /* Use the file object's device object */
1381 }
1382
1383 /* Sanity check */
1384 ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) ||
1386
1387 /* Check if the handle wasn't created yet */
1388 if (!(FileObject->Flags & FO_HANDLE_CREATED))
1389 {
1390 /* Send the cleanup IRP */
1391 IopCloseFile(NULL, ObjectBody, 0, 1, 1);
1392 }
1393
1394 /* Clear and set up Events */
1395 KeClearEvent(&FileObject->Event);
1397
1398 /* Allocate an IRP */
1400
1401 /* Set it up */
1402 Irp->UserEvent = &Event;
1403 Irp->UserIosb = &Irp->IoStatus;
1404 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1405 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1407
1408 /* Set up Stack Pointer Data */
1409 StackPtr = IoGetNextIrpStackLocation(Irp);
1410 StackPtr->MajorFunction = IRP_MJ_CLOSE;
1411 StackPtr->FileObject = FileObject;
1412
1413 /* Queue the IRP */
1415
1416 /* Get the VPB and check if this isn't a direct open */
1417 Vpb = FileObject->Vpb;
1418 if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
1419 {
1420 /* Dereference the VPB before the close */
1421 InterlockedDecrement((PLONG)&Vpb->ReferenceCount);
1422 }
1423
1424 /* Check if the FS will never disappear by itself */
1425 if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE)
1426 {
1427 /* Dereference it */
1428 InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount);
1429 DereferenceDone = TRUE;
1430 }
1431
1432 /* Call the FS Driver */
1434 if (Status == STATUS_PENDING)
1435 {
1436 /* Wait for completion */
1438 }
1439
1440 /* De-queue the IRP */
1444
1445 /* Free the IRP */
1446 IoFreeIrp(Irp);
1447
1448 /* Clear the file name */
1449 if (FileObject->FileName.Buffer)
1450 {
1451 /*
1452 * Don't use TAG_IO_NAME since the FileObject's FileName
1453 * may have been re-allocated using a different tag
1454 * by a filesystem.
1455 */
1456 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1457 FileObject->FileName.Buffer = NULL;
1458 }
1459
1460 /* Check if the FO had a completion port */
1461 if (FileObject->CompletionContext)
1462 {
1463 /* Free it */
1464 ObDereferenceObject(FileObject->CompletionContext->Port);
1465 ExFreePool(FileObject->CompletionContext);
1466 }
1467
1468 /* Check if the FO had extension */
1470 {
1471 /* Release filter context structure if any */
1473 }
1474
1475 /* Check if dereference has been done yet */
1476 if (!DereferenceDone)
1477 {
1478 /* Dereference device object */
1480 }
1481 }
1482}
1483
1485NTAPI
1487{
1489
1490 /* Go down the stack to attempt to get the PDO */
1491 for (; ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo != NULL;
1492 PDO = ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo);
1493
1494 return PDO;
1495}
1496
1498NTAPI
1500{
1501 KIRQL OldIrql;
1502 PDEVICE_OBJECT PDO;
1503
1505
1507 /* Get the base DO */
1509 /* Check whether that's really a PDO and if so, keep it */
1511 {
1512 PDO = NULL;
1513 }
1514 else
1515 {
1516 ObReferenceObject(PDO);
1517 }
1519
1520 return PDO;
1521}
1522
1524NTAPI
1530{
1532 PSECURITY_DESCRIPTOR OldSecurityDescriptor, CachedSecurityDescriptor, NewSecurityDescriptor;
1533
1534 PAGED_CODE();
1535
1536 /* Keep attempting till we find our old SD or fail */
1537 while (TRUE)
1538 {
1541
1542 /* Get our old SD and reference it */
1543 OldSecurityDescriptor = DeviceObject->SecurityDescriptor;
1544 if (OldSecurityDescriptor != NULL)
1545 {
1546 ObReferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1547 }
1548
1551
1552 /* Set the SD information */
1553 NewSecurityDescriptor = OldSecurityDescriptor;
1555 SecurityDescriptor, &NewSecurityDescriptor,
1557
1558 if (!NT_SUCCESS(Status))
1559 {
1560 if (OldSecurityDescriptor != NULL)
1561 {
1562 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1563 }
1564
1565 break;
1566 }
1567
1568 /* Add the new DS to the internal cache */
1569 Status = ObLogSecurityDescriptor(NewSecurityDescriptor,
1570 &CachedSecurityDescriptor, 1);
1571 ExFreePool(NewSecurityDescriptor);
1572 if (!NT_SUCCESS(Status))
1573 {
1574 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1575 break;
1576 }
1577
1580 /* Check if someone changed it in our back */
1581 if (DeviceObject->SecurityDescriptor == OldSecurityDescriptor)
1582 {
1583 /* We're clear, do the swap */
1584 DeviceObject->SecurityDescriptor = CachedSecurityDescriptor;
1587
1588 /* And dereference old SD (twice - us + not in use) */
1589 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 2);
1590
1591 break;
1592 }
1595
1596 /* If so, try again */
1597 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1598 ObDereferenceSecurityDescriptor(CachedSecurityDescriptor, 1);
1599 }
1600
1601 return Status;
1602}
1603
1605NTAPI
1612{
1613 PDEVICE_OBJECT CurrentDO = PhysicalDeviceObject, NextDevice;
1614 NTSTATUS Status = STATUS_SUCCESS, TmpStatus;
1615
1616 PAGED_CODE();
1617
1619
1620 /* We always reference the DO we're working on */
1621 ObReferenceObject(CurrentDO);
1622
1623 /* Go up from PDO to latest DO */
1624 do
1625 {
1626 /* Attempt to set the new SD on it */
1630 /* Was our last one? Remember that status then */
1631 if (CurrentDO == UpperDeviceObject)
1632 {
1633 Status = TmpStatus;
1634 }
1635
1636 /* Try to move to the next DO (and thus, reference it) */
1637 NextDevice = CurrentDO->AttachedDevice;
1638 if (NextDevice)
1639 {
1640 ObReferenceObject(NextDevice);
1641 }
1642
1643 /* Dereference current DO and move to the next one */
1644 ObDereferenceObject(CurrentDO);
1645 CurrentDO = NextDevice;
1646 }
1647 while (CurrentDO != NULL);
1648
1649 return Status;
1650}
1651
1653NTAPI
1655 IN SECURITY_OPERATION_CODE OperationCode,
1659 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
1662{
1664 PIO_STACK_LOCATION StackPtr;
1667 PIRP Irp;
1668 BOOLEAN LocalEvent = FALSE;
1669 KEVENT Event;
1671 PAGED_CODE();
1672 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1673
1674 /* Check if this is a device or file */
1675 if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE)
1676 {
1677 /* It's a device */
1678 DeviceObject = (PDEVICE_OBJECT)ObjectBody;
1679 FileObject = NULL;
1680 }
1681 else
1682 {
1683 /* It's a file */
1684 FileObject = (PFILE_OBJECT)ObjectBody;
1685
1686 /* Check if this is a direct open */
1687 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1688 {
1689 /* Get the Device Object */
1691 }
1692 else
1693 {
1694 /* Otherwise, use the direct device*/
1695 DeviceObject = FileObject->DeviceObject;
1696 }
1697 }
1698
1699 /* Check if the request was for a device object */
1700 if (!(FileObject) ||
1701 (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) ||
1703 {
1704 /* Check what kind of request this was */
1705 if (OperationCode == QuerySecurityDescriptor)
1706 {
1710 &DeviceObject->SecurityDescriptor);
1711 }
1712 else if (OperationCode == DeleteSecurityDescriptor)
1713 {
1714 /* Simply return success */
1715 return STATUS_SUCCESS;
1716 }
1717 else if (OperationCode == AssignSecurityDescriptor)
1718 {
1720
1721 /* Make absolutely sure this is a device object */
1722 if (!(FileObject) || !(FileObject->Flags & FO_STREAM_FILE))
1723 {
1724 PSECURITY_DESCRIPTOR CachedSecurityDescriptor;
1725
1726 /* Add the security descriptor in cache */
1727 Status = ObLogSecurityDescriptor(SecurityDescriptor, &CachedSecurityDescriptor, 1);
1728 if (NT_SUCCESS(Status))
1729 {
1732
1733 /* Assign the Security Descriptor */
1734 DeviceObject->SecurityDescriptor = CachedSecurityDescriptor;
1735
1738 }
1739 }
1740
1741 /* Return status */
1742 return Status;
1743 }
1744 else if (OperationCode == SetSecurityDescriptor)
1745 {
1746 /* Get the Physical Device Object if any */
1748
1749 if (PDO != NULL)
1750 {
1751 /* Apply the new SD to any DO in the path from PDO to current DO */
1757 }
1758 else
1759 {
1760 /* Otherwise, just set for ourselves */
1765 }
1766
1767 return STATUS_SUCCESS;
1768 }
1769
1770 /* Shouldn't happen */
1771 return STATUS_SUCCESS;
1772 }
1773 else if (OperationCode == DeleteSecurityDescriptor)
1774 {
1775 /* Same as for devices, do nothing */
1776 return STATUS_SUCCESS;
1777 }
1778
1779 /* At this point, we know we're a file. Reference it */
1781
1782 /* Check if we should use Sync IO or not */
1783 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1784 {
1785 /* Lock the file object */
1787 if (Status != STATUS_SUCCESS)
1788 {
1790 return Status;
1791 }
1792 }
1793 else
1794 {
1795 /* Use local event */
1797 LocalEvent = TRUE;
1798 }
1799
1800 /* Clear the File Object event */
1801 KeClearEvent(&FileObject->Event);
1802
1803 /* Get the device object */
1805
1806 /* Allocate the IRP */
1807 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1808 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL);
1809
1810 /* Set the IRP */
1811 Irp->Tail.Overlay.OriginalFileObject = FileObject;
1812 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1813 Irp->RequestorMode = ExGetPreviousMode();
1814 Irp->UserIosb = &IoStatusBlock;
1815 Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1816 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1817 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
1818
1819 /* Set Stack Parameters */
1820 StackPtr = IoGetNextIrpStackLocation(Irp);
1821 StackPtr->FileObject = FileObject;
1822
1823 /* Check if this is a query or set */
1824 if (OperationCode == QuerySecurityDescriptor)
1825 {
1826 /* Set the major function and parameters */
1828 StackPtr->Parameters.QuerySecurity.SecurityInformation =
1830 StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
1831 Irp->UserBuffer = SecurityDescriptor;
1832 }
1833 else
1834 {
1835 /* Set the major function and parameters for a set */
1837 StackPtr->Parameters.SetSecurity.SecurityInformation =
1839 StackPtr->Parameters.SetSecurity.SecurityDescriptor =
1841 }
1842
1843 /* Queue the IRP */
1845
1846 /* Update operation counts */
1848
1849 /* Call the Driver */
1851
1852 /* Check if this was async I/O */
1853 if (LocalEvent)
1854 {
1855 /* Check if the IRP is pending completion */
1856 if (Status == STATUS_PENDING)
1857 {
1858 /* Wait on the local event */
1860 Executive,
1861 KernelMode,
1862 FALSE,
1863 NULL);
1865 }
1866 }
1867 else
1868 {
1869 /* Check if the IRP is pending completion */
1870 if (Status == STATUS_PENDING)
1871 {
1872 /* Wait on the file object */
1874 Executive,
1875 KernelMode,
1876 FALSE,
1877 NULL);
1878 Status = FileObject->FinalStatus;
1879 }
1880
1881 /* Release the lock */
1883 }
1884
1885 /* This Driver doesn't implement Security, so try to give it a default */
1887 {
1888 /* Was this a query? */
1889 if (OperationCode == QuerySecurityDescriptor)
1890 {
1891 /* Set a World Security Descriptor */
1894 BufferLength);
1895 }
1896 else
1897 {
1898 /* It wasn't a query, so just fake success */
1900 }
1901 }
1902 else if (OperationCode == QuerySecurityDescriptor)
1903 {
1904 /* Callers usually expect the normalized form */
1906
1907 _SEH2_TRY
1908 {
1909 /* Return length */
1911 }
1913 {
1914 /* Get the exception code */
1916 }
1917 _SEH2_END;
1918 }
1919
1920 /* Return Status */
1921 return Status;
1922}
1923
1925NTAPI
1927 IN BOOLEAN HasName,
1928 OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
1929 IN ULONG Length,
1932{
1933 return IopQueryNameInternal(ObjectBody,
1934 HasName,
1935 FALSE,
1936 ObjectNameInfo,
1937 Length,
1939 PreviousMode);
1940}
1941
1943NTAPI
1945 IN BOOLEAN HasName,
1946 IN BOOLEAN QueryDosName,
1947 OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
1948 IN ULONG Length,
1951{
1952 POBJECT_NAME_INFORMATION LocalInfo;
1953 PFILE_NAME_INFORMATION LocalFileInfo;
1954 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
1955 ULONG LocalReturnLength, FileLength;
1956 BOOLEAN LengthMismatch = FALSE;
1958 PWCHAR p;
1960 BOOLEAN NoObCall;
1961
1962 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1963
1964 /* Validate length */
1965 if (Length < sizeof(OBJECT_NAME_INFORMATION))
1966 {
1967 /* Wrong length, fail */
1970 }
1971
1972 /* Allocate Buffer */
1974 if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES;
1975
1976 /* Query DOS name if the caller asked to */
1977 NoObCall = FALSE;
1978 if (QueryDosName)
1979 {
1980 DeviceObject = FileObject->DeviceObject;
1981
1982 /* In case of a network file system, don't call mountmgr */
1984 {
1985 /* We'll store separator and terminator */
1986 LocalReturnLength = sizeof(OBJECT_NAME_INFORMATION) + 2 * sizeof(WCHAR);
1987 if (Length < LocalReturnLength)
1988 {
1990 }
1991 else
1992 {
1993 LocalInfo->Name.Length = sizeof(WCHAR);
1994 LocalInfo->Name.MaximumLength = sizeof(WCHAR);
1995 LocalInfo->Name.Buffer = (PVOID)((ULONG_PTR)LocalInfo + sizeof(OBJECT_NAME_INFORMATION));
1996 LocalInfo->Name.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
1998 }
1999 }
2000 /* Otherwise, call mountmgr to get DOS name */
2001 else
2002 {
2004 LocalReturnLength = LocalInfo->Name.Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR);
2005 }
2006 }
2007
2008 /* Fall back if querying DOS name failed or if caller never wanted it ;-) */
2009 if (!QueryDosName || !NT_SUCCESS(Status))
2010 {
2011 /* Query the name */
2012 Status = ObQueryNameString(FileObject->DeviceObject,
2013 LocalInfo,
2014 Length,
2015 &LocalReturnLength);
2016 }
2017 else
2018 {
2019 NoObCall = TRUE;
2020 }
2021
2023 {
2024 /* Free the buffer and fail */
2025 ExFreePoolWithTag(LocalInfo, TAG_IO);
2026 return Status;
2027 }
2028
2029 /* Get buffer pointer */
2030 p = (PWCHAR)(ObjectNameInfo + 1);
2031
2032 _SEH2_TRY
2033 {
2034 /* Copy the information */
2035 if (QueryDosName && NoObCall)
2036 {
2038
2039 /* Copy structure first */
2040 RtlCopyMemory(ObjectNameInfo,
2041 LocalInfo,
2042 (Length >= LocalReturnLength ? sizeof(OBJECT_NAME_INFORMATION) : Length));
2043 /* Name then */
2044 RtlCopyMemory(p, LocalInfo->Name.Buffer,
2045 (Length >= LocalReturnLength ? LocalInfo->Name.Length : Length - sizeof(OBJECT_NAME_INFORMATION)));
2046
2047 if (FileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM)
2048 {
2049 ExFreePool(LocalInfo->Name.Buffer);
2050 }
2051 }
2052 else
2053 {
2054 RtlCopyMemory(ObjectNameInfo,
2055 LocalInfo,
2056 (LocalReturnLength > Length) ?
2057 Length : LocalReturnLength);
2058 }
2059
2060 /* Set buffer pointer */
2061 ObjectNameInfo->Name.Buffer = p;
2062
2063 /* Advance in buffer */
2064 p += (LocalInfo->Name.Length / sizeof(WCHAR));
2065
2066 /* Check if this already filled our buffer */
2067 if (LocalReturnLength > Length)
2068 {
2069 /* Set the length mismatch to true, so that we can return
2070 * the proper buffer size to the caller later
2071 */
2072 LengthMismatch = TRUE;
2073
2074 /* Save the initial buffer length value */
2075 *ReturnLength = LocalReturnLength;
2076 }
2077
2078 /* Now get the file name buffer and check the length needed */
2079 LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo;
2080 FileLength = Length -
2081 LocalReturnLength +
2083
2084 /* Query the File name */
2085 if (PreviousMode == KernelMode &&
2087 {
2089 LengthMismatch ? Length : FileLength,
2091 LocalFileInfo,
2092 &LocalReturnLength);
2093 }
2094 else
2095 {
2098 LengthMismatch ? Length : FileLength,
2099 LocalFileInfo,
2100 &LocalReturnLength);
2101 }
2102 if (NT_ERROR(Status))
2103 {
2104 /* Allow status that would mean it's not implemented in the storage stack */
2107 {
2109 }
2110
2111 /* In such case, zero output */
2112 LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2113 LocalFileInfo->FileNameLength = 0;
2114 LocalFileInfo->FileName[0] = OBJ_NAME_PATH_SEPARATOR;
2115 }
2116 else
2117 {
2118 /* We'll at least return the name length */
2119 if (LocalReturnLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName))
2120 {
2121 LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2122 }
2123 }
2124
2125 /* If the provided buffer is too small, return the required size */
2126 if (LengthMismatch)
2127 {
2128 /* Add the required length */
2129 *ReturnLength += LocalFileInfo->FileNameLength;
2130
2131 /* Free the allocated buffer and return failure */
2134 }
2135
2136 /* Now calculate the new lengths left */
2137 FileLength = LocalReturnLength -
2139 LocalReturnLength = (ULONG)((ULONG_PTR)p -
2140 (ULONG_PTR)ObjectNameInfo +
2141 LocalFileInfo->FileNameLength);
2142
2143 /* Don't copy the name if it's not valid */
2144 if (LocalFileInfo->FileName[0] != OBJ_NAME_PATH_SEPARATOR)
2145 {
2146 /* Free the allocated buffer and return failure */
2149 }
2150
2151 /* Write the Name and null-terminate it */
2152 RtlCopyMemory(p, LocalFileInfo->FileName, FileLength);
2153 p += (FileLength / sizeof(WCHAR));
2154 *p = UNICODE_NULL;
2155 LocalReturnLength += sizeof(UNICODE_NULL);
2156
2157 /* Return the length needed */
2158 *ReturnLength = LocalReturnLength;
2159
2160 /* Setup the length and maximum length */
2161 FileLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo);
2162 ObjectNameInfo->Name.Length = (USHORT)FileLength -
2164 ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length +
2165 sizeof(UNICODE_NULL);
2166 }
2168 {
2169 /* Free buffer and return */
2170 ExFreePoolWithTag(LocalInfo, TAG_IO);
2171 } _SEH2_END;
2172
2173 return Status;
2174}
2175
2176VOID
2177NTAPI
2179 IN PVOID ObjectBody,
2181 IN ULONG HandleCount,
2182 IN ULONG SystemHandleCount)
2183{
2184 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
2185 KEVENT Event;
2186 PIRP Irp;
2187 PIO_STACK_LOCATION StackPtr;
2190 KIRQL OldIrql;
2192 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
2193
2194 /* If this isn't the last handle for the current process, quit */
2195 if (HandleCount != 1) return;
2196
2197 /* Check if the file is locked and has more then one handle opened */
2198 if ((FileObject->LockOperation) && (SystemHandleCount != 1))
2199 {
2200 /* Check if this is a direct open or not */
2202 {
2203 /* Get the attached device */
2205 }
2206 else
2207 {
2208 /* Get the FO's device */
2210 }
2211
2212 /* Check if this is a sync FO and lock it */
2214 {
2216 }
2217
2218 /* Go the FastIO path if possible, otherwise fall back to IRP */
2219 if (DeviceObject->DriverObject->FastIoDispatch == NULL ||
2220 DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL ||
2221 !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject))
2222 {
2223 /* Clear and set up Events */
2224 KeClearEvent(&FileObject->Event);
2226
2227 /* Allocate an IRP */
2229
2230 /* Set it up */
2231 Irp->UserEvent = &Event;
2232 Irp->UserIosb = &Irp->IoStatus;
2233 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2234 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2235 Irp->RequestorMode = KernelMode;
2236 Irp->Flags = IRP_SYNCHRONOUS_API;
2237 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
2239
2240 /* Set up Stack Pointer Data */
2241 StackPtr = IoGetNextIrpStackLocation(Irp);
2243 StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL;
2244 StackPtr->FileObject = FileObject;
2245
2246 /* Queue the IRP */
2248
2249 /* Call the FS Driver */
2251 if (Status == STATUS_PENDING)
2252 {
2253 /* Wait for completion */
2255 }
2256
2257 /* IO will unqueue & free for us */
2258 }
2259
2260 /* Release the lock if we were holding it */
2262 {
2264 }
2265 }
2266
2267 /* Make sure this is the last handle */
2268 if (SystemHandleCount != 1) return;
2269
2270 /* Check if this is a direct open or not */
2271 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2272 {
2273 /* Get the attached device */
2275 }
2276 else
2277 {
2278 /* Get the FO's device */
2280 }
2281
2282 /* Set the handle created flag */
2283 FileObject->Flags |= FO_HANDLE_CREATED;
2284
2285 /* Check if this is a sync FO and lock it */
2286 if (Process != NULL &&
2288 {
2290 }
2291
2292 /* Clear and set up Events */
2293 KeClearEvent(&FileObject->Event);
2295
2296 /* Allocate an IRP */
2298
2299 /* Set it up */
2300 Irp->UserEvent = &Event;
2301 Irp->UserIosb = &Irp->IoStatus;
2302 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2303 Irp->Tail.Overlay.OriginalFileObject = FileObject;
2304 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
2306
2307 /* Set up Stack Pointer Data */
2308 StackPtr = IoGetNextIrpStackLocation(Irp);
2309 StackPtr->MajorFunction = IRP_MJ_CLEANUP;
2310 StackPtr->FileObject = FileObject;
2311
2312 /* Queue the IRP */
2314
2315 /* Update operation counts */
2317
2318 /* Call the FS Driver */
2320 if (Status == STATUS_PENDING)
2321 {
2322 /* Wait for completion */
2324 }
2325
2326 /* Unqueue the IRP */
2330
2331 /* Free the IRP */
2332 IoFreeIrp(Irp);
2333
2334 /* Release the lock if we were holding it */
2335 if (Process != NULL &&
2337 {
2339 }
2340}
2341
2343NTAPI
2346 IN ULONG FileInformationSize,
2348{
2351 DUMMY_FILE_OBJECT LocalFileObject;
2352 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo;
2353 HANDLE Handle;
2354 OPEN_PACKET OpenPacket;
2355 BOOLEAN IsBasic;
2356 PAGED_CODE();
2357 IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass);
2358
2359 /* Check if the caller was user mode */
2360 if (AccessMode != KernelMode)
2361 {
2362 /* Protect probe in SEH */
2363 _SEH2_TRY
2364 {
2365 /* Probe the buffer */
2366 ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG));
2367 }
2369 {
2370 /* Return the exception code */
2372 }
2373 _SEH2_END;
2374 }
2375
2376 /* Check if this is a basic or full request */
2377 IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION));
2378
2379 /* Setup the Open Packet */
2380 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
2381 OpenPacket.Type = IO_TYPE_OPEN_PACKET;
2382 OpenPacket.Size = sizeof(OPEN_PACKET);
2385 OpenPacket.Disposition = FILE_OPEN;
2386 OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL;
2387 OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo :
2388 (AccessMode != KernelMode) ?
2389 &NetworkOpenInfo : FileInformation;
2390 OpenPacket.QueryOnly = TRUE;
2391 OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE;
2392 OpenPacket.LocalFileObject = &LocalFileObject;
2393
2394 /* Update the operation count */
2396
2397 /*
2398 * Attempt opening the file. This will call the I/O Parse Routine for
2399 * the File Object (IopParseDevice) which will use the dummy file obejct
2400 * send the IRP to its device object. Note that we have two statuses
2401 * to worry about: the Object Manager's status (in Status) and the I/O
2402 * status, which is in the Open Packet's Final Status, and determined
2403 * by the Parse Check member.
2404 */
2406 NULL,
2407 AccessMode,
2408 NULL,
2410 &OpenPacket,
2411 &Handle);
2412 if (OpenPacket.ParseCheck == FALSE)
2413 {
2414 /* Parse failed */
2415 DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
2416 ObjectAttributes->ObjectName, Status);
2417 return Status;
2418 }
2419 else
2420 {
2421 /* Use the Io status */
2422 Status = OpenPacket.FinalStatus;
2423 }
2424
2425 /* Check if we were succesful and this was user mode and a full query */
2426 if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic))
2427 {
2428 /* Enter SEH for copy */
2429 _SEH2_TRY
2430 {
2431 /* Copy the buffer back */
2433 &NetworkOpenInfo,
2434 FileInformationSize);
2435 }
2437 {
2438 /* Get exception code */
2440 }
2441 _SEH2_END;
2442 }
2443
2444 /* Return status */
2445 return Status;
2446}
2447
2449NTAPI
2452 _In_ KPROCESSOR_MODE WaitMode,
2454 _Out_ PBOOLEAN LockFailed)
2455{
2457
2458 PAGED_CODE();
2459
2461
2463 do
2464 {
2466 {
2467 break;
2468 }
2470 Executive,
2471 WaitMode,
2472 Alertable,
2473 NULL);
2474 } while (Status == STATUS_SUCCESS);
2475
2477 if (Status == STATUS_SUCCESS)
2478 {
2480 *LockFailed = FALSE;
2481 }
2482 else
2483 {
2484 if (!FileObject->Busy && FileObject->Waiters)
2485 {
2487 }
2488 *LockFailed = TRUE;
2489 }
2490
2491 return Status;
2492}
2493
2494PVOID
2495NTAPI
2497{
2499 {
2500 PFILE_OBJECT_EXTENSION FileObjectExtension;
2501
2502 FileObjectExtension = FileObject->FileObjectExtension;
2503 return FileObjectExtension->FilterContext;
2504 }
2505
2506 return NULL;
2507}
2508
2510NTAPI
2513 IN BOOLEAN Define)
2514{
2516 PFILE_OBJECT_EXTENSION FileObjectExtension;
2517
2519 {
2521 }
2522
2523 FileObjectExtension = FileObject->FileObjectExtension;
2524 if (Define)
2525 {
2526 /* If define, just set the new value if not value is set
2527 * Success will only contain old value. It is valid if it is NULL
2528 */
2530 }
2531 else
2532 {
2533 /* If not define, we want to reset filter context.
2534 * We will remove value (provided by the caller) and set NULL instead.
2535 * This will only success if caller provides correct previous value.
2536 * To catch whether it worked, we substract previous value to expect value:
2537 * If it matches (and thus, we reset), Success will contain 0
2538 * Otherwise, it will contain a non-zero value.
2539 */
2541 }
2542
2543 /* If success isn't 0, it means we failed somewhere (set or unset) */
2544 if (Success != 0)
2545 {
2547 }
2548
2549 return STATUS_SUCCESS;
2550}
2551
2553NTAPI
2566 IN PVOID ExtraCreateParameters OPTIONAL,
2568 IN ULONG Flags,
2570{
2572 HANDLE LocalHandle = 0;
2573 LARGE_INTEGER SafeAllocationSize;
2575 PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters;
2576 POPEN_PACKET OpenPacket;
2577 ULONG EaErrorOffset;
2578 PAGED_CODE();
2579
2580 IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
2581
2582
2583 /* Check if we have no parameter checking to do */
2585 {
2586 /* Then force kernel-mode access to avoid checks */
2588 }
2589 else
2590 {
2591 /* Otherwise, use the actual mode */
2593 }
2594
2595 /* Check if we need to do parameter checking */
2597 {
2598 /* Validate parameters */
2600 {
2601 DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
2603 }
2604
2606 {
2607 DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
2609 }
2610
2612 {
2613 DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
2615 }
2616
2618 {
2619 DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
2621 }
2622
2625 {
2626 DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
2628 }
2629
2631 {
2632 DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
2634 }
2635
2638 {
2639 DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
2641 }
2642
2655 {
2656 DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
2658 }
2659
2662 {
2663 DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
2665 }
2666
2668 {
2669 DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
2671 }
2672
2674 {
2675 DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
2677 }
2678
2679 /* Now check if this is a named pipe */
2681 {
2682 /* Make sure we have extra parameters */
2683 if (!ExtraCreateParameters)
2684 {
2685 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2687 }
2688
2689 /* Get the parameters and validate them */
2690 NamedPipeCreateParameters = ExtraCreateParameters;
2691 if ((NamedPipeCreateParameters->NamedPipeType > FILE_PIPE_MESSAGE_TYPE) ||
2692 (NamedPipeCreateParameters->ReadMode > FILE_PIPE_MESSAGE_MODE) ||
2693 (NamedPipeCreateParameters->CompletionMode > FILE_PIPE_COMPLETE_OPERATION) ||
2697 {
2698 /* Invalid named pipe create */
2699 DPRINT1("Invalid named pipe create\n");
2701 }
2702 }
2704 {
2705 /* Make sure we have extra parameters */
2706 if (!ExtraCreateParameters)
2707 {
2708 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2710 }
2711
2712 /* Get the parameters and validate them */
2715 (Disposition != FILE_CREATE) ||
2717 {
2718 /* Invalid mailslot create */
2719 DPRINT1("Invalid mailslot create\n");
2721 }
2722 }
2723 }
2724
2725 /* Allocate the open packet */
2726 OpenPacket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*OpenPacket), 'pOoI');
2727 if (!OpenPacket) return STATUS_INSUFFICIENT_RESOURCES;
2728 RtlZeroMemory(OpenPacket, sizeof(*OpenPacket));
2729
2730 /* Check if the call came from user mode */
2731 if (AccessMode != KernelMode)
2732 {
2733 _SEH2_TRY
2734 {
2735 /* Probe the output parameters */
2738
2739 /* Probe the allocation size if one was passed in */
2740 if (AllocationSize)
2741 {
2742 SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
2743 }
2744 else
2745 {
2746 SafeAllocationSize.QuadPart = 0;
2747 }
2748
2749 /* Make sure it's valid */
2750 if (SafeAllocationSize.QuadPart < 0)
2751 {
2753 }
2754
2755 /* Check if EA was passed in */
2756 if ((EaBuffer) && (EaLength))
2757 {
2758 /* Probe it */
2760
2761 /* And marshall it */
2763 EaLength,
2764 TAG_EA);
2765 OpenPacket->EaLength = EaLength;
2766 RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength);
2767
2768 /* Validate the buffer */
2770 EaLength,
2771 &EaErrorOffset);
2772 if (!NT_SUCCESS(Status))
2773 {
2774 /* Undo everything if it's invalid */
2775 DPRINT1("Invalid EA buffer\n");
2777 IoStatusBlock->Information = EaErrorOffset;
2779 }
2780 }
2781 }
2783 {
2784 /* Return the exception code */
2785 if (OpenPacket->EaBuffer != NULL) ExFreePool(OpenPacket->EaBuffer);
2786 ExFreePool(OpenPacket);
2788 }
2789 _SEH2_END;
2790 }
2791 else
2792 {
2793 /* Check if this is a device attach */
2795 {
2796 /* Set the flag properly */
2798 CreateOptions &= ~IO_ATTACH_DEVICE_API;
2799 }
2800
2801 /* Check if we have allocation size */
2802 if (AllocationSize)
2803 {
2804 /* Capture it */
2805 SafeAllocationSize = *AllocationSize;
2806 }
2807 else
2808 {
2809 /* Otherwise, no size */
2810 SafeAllocationSize.QuadPart = 0;
2811 }
2812
2813 /* Check if we have an EA packet */
2814 if ((EaBuffer) && (EaLength))
2815 {
2816 /* Allocate the kernel copy */
2818 EaLength,
2819 TAG_EA);
2820 if (!OpenPacket->EaBuffer)
2821 {
2822 ExFreePool(OpenPacket);
2823 DPRINT1("Failed to allocate open packet EA buffer\n");
2825 }
2826
2827 /* Copy the data */
2828 OpenPacket->EaLength = EaLength;
2829 RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength);
2830
2831 /* Validate the buffer */
2833 EaLength,
2834 &EaErrorOffset);
2835 if (!NT_SUCCESS(Status))
2836 {
2837 /* Undo everything if it's invalid */
2838 DPRINT1("Invalid EA buffer\n");
2839 ExFreePool(OpenPacket->EaBuffer);
2841 IoStatusBlock->Information = EaErrorOffset;
2842 ExFreePool(OpenPacket);
2843 return Status;
2844 }
2845 }
2846 }
2847
2848 /* Setup the Open Packet */
2849 OpenPacket->Type = IO_TYPE_OPEN_PACKET;
2850 OpenPacket->Size = sizeof(*OpenPacket);
2851 OpenPacket->AllocationSize = SafeAllocationSize;
2852 OpenPacket->CreateOptions = CreateOptions;
2853 OpenPacket->FileAttributes = (USHORT)FileAttributes;
2854 OpenPacket->ShareAccess = (USHORT)ShareAccess;
2855 OpenPacket->Options = Options;
2856 OpenPacket->Disposition = Disposition;
2857 OpenPacket->CreateFileType = CreateFileType;
2858 OpenPacket->ExtraCreateParameters = ExtraCreateParameters;
2859 OpenPacket->InternalFlags = Flags;
2860 OpenPacket->TopDeviceObjectHint = DeviceObject;
2861
2862 /* Update the operation count */
2864
2865 /*
2866 * Attempt opening the file. This will call the I/O Parse Routine for
2867 * the File Object (IopParseDevice) which will create the object and
2868 * send the IRP to its device object. Note that we have two statuses
2869 * to worry about: the Object Manager's status (in Status) and the I/O
2870 * status, which is in the Open Packet's Final Status, and determined
2871 * by the Parse Check member.
2872 */
2874 NULL,
2875 AccessMode,
2876 NULL,
2878 OpenPacket,
2879 &LocalHandle);
2880
2881 /* Free the EA Buffer */
2882 if (OpenPacket->EaBuffer) ExFreePool(OpenPacket->EaBuffer);
2883
2884 /* Now check for Ob or Io failure */
2885 if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck == FALSE))
2886 {
2887 /* Check if Ob thinks well went well */
2888 if (NT_SUCCESS(Status))
2889 {
2890 /*
2891 * Tell it otherwise. Because we didn't use an ObjectType,
2892 * it incorrectly returned us a handle to God knows what.
2893 */
2896 }
2897
2898 /* Now check the Io status */
2899 if (!NT_SUCCESS(OpenPacket->FinalStatus))
2900 {
2901 /* Use this status instead of Ob's */
2902 Status = OpenPacket->FinalStatus;
2903
2904 /* Check if it was only a warning */
2905 if (NT_WARNING(Status))
2906 {
2907 /* Protect write with SEH */
2908 _SEH2_TRY
2909 {
2910 /* In this case, we copy the I/O Status back */
2911 IoStatusBlock->Information = OpenPacket->Information;
2912 IoStatusBlock->Status = OpenPacket->FinalStatus;
2913 }
2915 {
2916 /* Get exception code */
2918 }
2919 _SEH2_END;
2920 }
2921 }
2922 else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck == FALSE))
2923 {
2924 /*
2925 * This can happen in the very bizarre case where the parse routine
2926 * actually executed more then once (due to a reparse) and ended
2927 * up failing after already having created the File Object.
2928 */
2929 if (OpenPacket->FileObject->FileName.Length)
2930 {
2931 /* It had a name, free it */
2932 ExFreePoolWithTag(OpenPacket->FileObject->FileName.Buffer, TAG_IO_NAME);
2933 }
2934
2935 /* Clear the device object to invalidate the FO, and dereference */
2936 OpenPacket->FileObject->DeviceObject = NULL;
2937 ObDereferenceObject(OpenPacket->FileObject);
2938 }
2939 }
2940 else
2941 {
2942 /* We reached success and have a valid file handle */
2943 OpenPacket->FileObject->Flags |= FO_HANDLE_CREATED;
2944 ASSERT(OpenPacket->FileObject->Type == IO_TYPE_FILE);
2945
2946 /* Enter SEH for write back */
2947 _SEH2_TRY
2948 {
2949 /* Write back the handle and I/O Status */
2951 IoStatusBlock->Information = OpenPacket->Information;
2952 IoStatusBlock->Status = OpenPacket->FinalStatus;
2953
2954 /* Get the Io status */
2955 Status = OpenPacket->FinalStatus;
2956 }
2958 {
2959 /* Get the exception status */
2961 }
2962 _SEH2_END;
2963 }
2964
2965 /* Check if we were 100% successful */
2966 if ((OpenPacket->ParseCheck != FALSE) && (OpenPacket->FileObject))
2967 {
2968 /* Dereference the File Object */
2969 ObDereferenceObject(OpenPacket->FileObject);
2970 }
2971
2972 /* Return status */
2973 ExFreePool(OpenPacket);
2974 return Status;
2975}
2976
2977/* FUNCTIONS *****************************************************************/
2978
2979/*
2980 * @unimplemented
2981 */
2983NTAPI
2985 IN ULONG Length,
2986 IN BOOLEAN SetOperation)
2987{
2990}
2991
2992/*
2993 * @unimplemented
2994 */
2996NTAPI
2998 IN ULONG QuotaLength,
2999 OUT PULONG ErrorOffset)
3000{
3003}
3004
3005/*
3006 * @implemented
3007 */
3009NTAPI
3022 IN PVOID ExtraCreateParameters OPTIONAL,
3024{
3025 PAGED_CODE();
3026
3036 EaBuffer,
3037 EaLength,
3039 ExtraCreateParameters,
3040 Options,
3041 0,
3042 NULL);
3043}
3044
3045/*
3046 * @unimplemented
3047 */
3049NTAPI
3062 IN PVOID ExtraCreateParameters OPTIONAL,
3065{
3066 ULONG Flags = 0;
3067
3068 PAGED_CODE();
3069
3070 /* Check if we were passed a device to send the create request to*/
3071 if (DeviceObject)
3072 {
3073 /* We'll tag this request into a file object extension */
3075 }
3076
3086 EaBuffer,
3087 EaLength,
3089 ExtraCreateParameters,
3091 Flags,
3092 DeviceObject);
3093}
3094
3095/*
3096 * @implemented
3097 */
3099NTAPI
3103{
3104 PFILE_OBJECT CreatedFileObject;
3108 PAGED_CODE();
3109 IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject);
3110
3111 /* Choose Device Object */
3112 if (FileObject) DeviceObject = FileObject->DeviceObject;
3113
3114 /* Reference the device object and initialize attributes */
3115 InterlockedIncrement(&DeviceObject->ReferenceCount);
3117
3118 /* Create the File Object */
3122 KernelMode,
3123 NULL,
3124 sizeof(FILE_OBJECT),
3125 sizeof(FILE_OBJECT),
3126 0,
3127 (PVOID*)&CreatedFileObject);
3128 if (!NT_SUCCESS(Status))
3129 {
3130 /* Fail */
3133 }
3134
3135 /* Set File Object Data */
3136 RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT));
3137 CreatedFileObject->DeviceObject = DeviceObject;
3138 CreatedFileObject->Type = IO_TYPE_FILE;
3139 CreatedFileObject->Size = sizeof(FILE_OBJECT);
3140 CreatedFileObject->Flags = FO_STREAM_FILE;
3141
3142 /* Initialize the wait event */
3143 KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE);
3144
3145 /* Insert it to create a handle for it */
3146 Status = ObInsertObject(CreatedFileObject,
3147 NULL,
3149 1,
3150 (PVOID*)&CreatedFileObject,
3151 &FileHandle);
3153
3154 /* Set the handle created flag */
3155 CreatedFileObject->Flags |= FO_HANDLE_CREATED;
3156 ASSERT(CreatedFileObject->Type == IO_TYPE_FILE);
3157
3158 /* Check if we have a VPB */
3159 if (DeviceObject->Vpb)
3160 {
3161 /* Reference it */
3162 InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount);
3163 }
3164
3165 /* Check if the caller wants the handle */
3166 if (FileObjectHandle)
3167 {
3168 /* Return it */
3170 ObDereferenceObject(CreatedFileObject);
3171 }
3172 else
3173 {
3174 /* Otherwise, close it */
3176 }
3177
3178 /* Return the file object */
3179 return CreatedFileObject;
3180}
3181
3182/*
3183 * @implemented
3184 */
3186NTAPI
3189{
3190 /* Call the newer function */
3192}
3193
3194/*
3195 * @implemented
3196 */
3198NTAPI
3201{
3202 PFILE_OBJECT CreatedFileObject;
3205 PAGED_CODE();
3206 IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject);
3207
3208 /* Choose Device Object */
3209 if (FileObject) DeviceObject = FileObject->DeviceObject;
3210
3211 /* Reference the device object and initialize attributes */
3212 InterlockedIncrement(&DeviceObject->ReferenceCount);
3214
3215 /* Create the File Object */
3219 KernelMode,
3220 NULL,
3221 sizeof(FILE_OBJECT),
3222 sizeof(FILE_OBJECT),
3223 0,
3224 (PVOID*)&CreatedFileObject);
3225 if (!NT_SUCCESS(Status))
3226 {
3227 /* Fail */
3230 }
3231
3232 /* Set File Object Data */
3233 RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT));
3234 CreatedFileObject->DeviceObject = DeviceObject;
3235 CreatedFileObject->Type = IO_TYPE_FILE;
3236 CreatedFileObject->Size = sizeof(FILE_OBJECT);
3237 CreatedFileObject->Flags = FO_STREAM_FILE;
3238
3239 /* Initialize the wait event */
3240 KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE);
3241
3242 /* Destroy create information */
3244 ObjectCreateInfo);
3245 OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL;
3246
3247 /* Set the handle created flag */
3248 CreatedFileObject->Flags |= FO_HANDLE_CREATED;
3249 ASSERT(CreatedFileObject->Type == IO_TYPE_FILE);
3250
3251 /* Check if we have a VPB */
3252 if (DeviceObject->Vpb)
3253 {
3254 /* Reference it */
3255 InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount);
3256 }
3257
3258 /* Return the file object */
3259 return CreatedFileObject;
3260}
3261
3262/*
3263 * @implemented
3264 */
3266NTAPI
3268{
3269 /* Return the mapping */
3270 return &IopFileMapping;
3271}
3272
3273/*
3274 * @implemented
3275 */
3276BOOLEAN
3277NTAPI
3279{
3280 /* Return the flag status */
3281 return FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE;
3282}
3283
3284/*
3285 * @implemented
3286 */
3287BOOLEAN
3288NTAPI
3294{
3296 DUMMY_FILE_OBJECT LocalFileObject;
3297 HANDLE Handle;
3298 OPEN_PACKET OpenPacket;
3299 PAGED_CODE();
3300 IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
3301
3302 /* Setup the Open Packet */
3303 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
3304 OpenPacket.Type = IO_TYPE_OPEN_PACKET;
3305 OpenPacket.Size = sizeof(OPEN_PACKET);
3308 OpenPacket.Options = IO_FORCE_ACCESS_CHECK;
3309 OpenPacket.Disposition = FILE_OPEN;
3310 OpenPacket.NetworkInformation = Buffer;
3311 OpenPacket.QueryOnly = TRUE;
3312 OpenPacket.FullAttributes = TRUE;
3313 OpenPacket.LocalFileObject = &LocalFileObject;
3314
3315 /*
3316 * Attempt opening the file. This will call the I/O Parse Routine for
3317 * the File Object (IopParseDevice) which will use the dummy file obejct
3318 * send the IRP to its device object. Note that we have two statuses
3319 * to worry about: the Object Manager's status (in Status) and the I/O
3320 * status, which is in the Open Packet's Final Status, and determined
3321 * by the Parse Check member.
3322 */
3324 NULL,
3325 KernelMode,
3326 NULL,
3328 &OpenPacket,
3329 &Handle);
3330 if (OpenPacket.ParseCheck == FALSE)
3331 {
3332 /* Parse failed */
3333 IoStatus->Status = Status;
3334 }
3335 else
3336 {
3337 /* Use the Io status */
3338 IoStatus->Status = OpenPacket.FinalStatus;
3339 IoStatus->Information = OpenPacket.Information;
3340 }
3341
3342 /* Return success */
3343 return TRUE;
3344}
3345
3346/*
3347 * @implemented
3348 */
3349VOID
3350NTAPI
3353{
3354 PAGED_CODE();
3355
3356 /* Check if the file has an extension */
3358 {
3359 /* Check if caller specified to ignore access checks */
3360 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3361 {
3362 /* Don't update share access */
3363 return;
3364 }
3365 }
3366
3367 /* Otherwise, check if there's any access present */
3368 if ((FileObject->ReadAccess) ||
3369 (FileObject->WriteAccess) ||
3370 (FileObject->DeleteAccess))
3371 {
3372 /* Increase the open count */
3373 ShareAccess->OpenCount++;
3374
3375 /* Add new share access */
3376 ShareAccess->Readers += FileObject->ReadAccess;
3377 ShareAccess->Writers += FileObject->WriteAccess;
3378 ShareAccess->Deleters += FileObject->DeleteAccess;
3379 ShareAccess->SharedRead += FileObject->SharedRead;
3380 ShareAccess->SharedWrite += FileObject->SharedWrite;
3381 ShareAccess->SharedDelete += FileObject->SharedDelete;
3382 }
3383}
3384
3385/*
3386 * @implemented
3387 */
3389NTAPI
3395{
3398 BOOLEAN DeleteAccess;
3399 BOOLEAN SharedRead;
3400 BOOLEAN SharedWrite;
3401 BOOLEAN SharedDelete;
3402 PAGED_CODE();
3403
3404 /* Get access masks */
3407 DeleteAccess = (DesiredAccess & DELETE) != 0;
3408
3409 /* Set them in the file object */
3410 FileObject->ReadAccess = ReadAccess;
3411 FileObject->WriteAccess = WriteAccess;
3412 FileObject->DeleteAccess = DeleteAccess;
3413
3414 /* Check if the file has an extension */
3416 {
3417 /* Check if caller specified to ignore access checks */
3418 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3419 {
3420 /* Don't check share access */
3421 return STATUS_SUCCESS;
3422 }
3423 }
3424
3425 /* Check if we have any access */
3426 if ((ReadAccess) || (WriteAccess) || (DeleteAccess))
3427 {
3428 /* Get shared access masks */
3429 SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
3430 SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
3431 SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
3432
3433 /* Check if the shared access is violated */
3434 if ((ReadAccess &&
3435 (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
3436 (WriteAccess &&
3437 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
3438 (DeleteAccess &&
3439 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
3440 ((ShareAccess->Readers != 0) && !SharedRead) ||
3441 ((ShareAccess->Writers != 0) && !SharedWrite) ||
3442 ((ShareAccess->Deleters != 0) && !SharedDelete))
3443 {
3444 /* Sharing violation, fail */
3446 }
3447
3448 /* Set them */
3449 FileObject->SharedRead = SharedRead;
3450 FileObject->SharedWrite = SharedWrite;
3451 FileObject->SharedDelete = SharedDelete;
3452
3453 /* It's not, check if caller wants us to update it */
3454 if (Update)
3455 {
3456 /* Increase open count */
3457 ShareAccess->OpenCount++;
3458
3459 /* Update shared access */
3460 ShareAccess->Readers += ReadAccess;
3461 ShareAccess->Writers += WriteAccess;
3462 ShareAccess->Deleters += DeleteAccess;
3463 ShareAccess->SharedRead += SharedRead;
3464 ShareAccess->SharedWrite += SharedWrite;
3465 ShareAccess->SharedDelete += SharedDelete;
3466 }
3467 }
3468
3469 /* Validation successful */
3470 return STATUS_SUCCESS;
3471}
3472
3473/*
3474 * @implemented
3475 */
3476VOID
3477NTAPI
3480{
3481 PAGED_CODE();
3482
3483 /* Check if the file has an extension */
3485 {
3486 /* Check if caller specified to ignore access checks */
3487 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3488 {
3489 /* Don't update share access */
3490 return;
3491 }
3492 }
3493
3494 /* Otherwise, check if there's any access present */
3495 if ((FileObject->ReadAccess) ||
3496 (FileObject->WriteAccess) ||
3497 (FileObject->DeleteAccess))
3498 {
3499 /* Decrement the open count */
3500 ShareAccess->OpenCount--;
3501
3502 /* Remove share access */
3503 ShareAccess->Readers -= FileObject->ReadAccess;
3504 ShareAccess->Writers -= FileObject->WriteAccess;
3505 ShareAccess->Deleters -= FileObject->DeleteAccess;
3506 ShareAccess->SharedRead -= FileObject->SharedRead;
3507 ShareAccess->SharedWrite -= FileObject->SharedWrite;
3508 ShareAccess->SharedDelete -= FileObject->SharedDelete;
3509 }
3510}
3511
3512/*
3513 * @implemented
3514 */
3515VOID
3516NTAPI
3521{
3524 BOOLEAN DeleteAccess;
3525 BOOLEAN SharedRead;
3526 BOOLEAN SharedWrite;
3527 BOOLEAN SharedDelete;
3529 PAGED_CODE();
3530
3533 DeleteAccess = (DesiredAccess & DELETE) != 0;
3534
3535 /* Check if the file has an extension */
3537 {
3538 /* Check if caller specified to ignore access checks */
3539 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3540 {
3541 /* Don't update share access */
3542 Update = FALSE;
3543 }
3544 }
3545
3546 /* Update basic access */
3547 FileObject->ReadAccess = ReadAccess;
3548 FileObject->WriteAccess = WriteAccess;
3549 FileObject->DeleteAccess = DeleteAccess;
3550
3551 /* Check if we have no access as all */
3552 if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess))
3553 {
3554 /* Check if we need to update the structure */
3555 if (!Update) return;
3556
3557 /* Otherwise, clear data */
3558 ShareAccess->OpenCount = 0;
3559 ShareAccess->Readers = 0;
3560 ShareAccess->Writers = 0;
3561 ShareAccess->Deleters = 0;
3562 ShareAccess->SharedRead = 0;
3563 ShareAccess->SharedWrite = 0;
3564 ShareAccess->SharedDelete = 0;
3565 }
3566 else
3567 {
3568 /* Calculate shared access */
3569 SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
3570 SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
3571 SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
3572
3573 /* Set it in the FO */
3574 FileObject->SharedRead = SharedRead;
3575 FileObject->SharedWrite = SharedWrite;
3576 FileObject->SharedDelete = SharedDelete;
3577
3578 /* Check if we need to update the structure */
3579 if (!Update) return;
3580
3581 /* Otherwise, set data */
3582 ShareAccess->OpenCount = 1;
3583 ShareAccess->Readers = ReadAccess;
3584 ShareAccess->Writers = WriteAccess;
3585 ShareAccess->Deleters = DeleteAccess;
3586 ShareAccess->SharedRead = SharedRead;
3587 ShareAccess->SharedWrite = SharedWrite;
3588 ShareAccess->SharedDelete = SharedDelete;
3589 }
3590}
3591
3592/*
3593 * @implemented
3594 */
3595VOID
3596NTAPI
3599{
3600 PIRP Irp;
3601 KEVENT Event;
3602 KIRQL OldIrql;
3605
3606 /* Check if handles were already created for the
3607 * open file. If so, that's over.
3608 */
3609 if (FileObject->Flags & FO_HANDLE_CREATED)
3610 KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN,
3612 (ULONG_PTR)DeviceObject, 0, 0);
3613
3614 /* Reset the events */
3616 KeClearEvent(&FileObject->Event);
3617
3618 /* Allocate the IRP we'll use */
3620 /* Properly set it */
3621 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3622 Irp->UserEvent = &Event;
3623 Irp->UserIosb = &Irp->IoStatus;
3624 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
3625 Irp->Tail.Overlay.OriginalFileObject = FileObject;
3626 Irp->RequestorMode = KernelMode;
3628
3630 Stack->MajorFunction = IRP_MJ_CLEANUP;
3631 Stack->FileObject = FileObject;
3632
3633 /* Put on top of IRPs list of the thread */
3635
3636 /* Call the driver */
3638 if (Status == STATUS_PENDING)
3639 {
3642 }
3643
3644 /* Remove from IRPs list */
3648
3649 /* Free the IRP */
3650 IoFreeIrp(Irp);
3651
3652 /* Clear the event */
3653 KeClearEvent(&FileObject->Event);
3654 /* And finally, mark the open operation as canceled */
3656}
3657
3658/*
3659 * @implemented
3660 */
3662NTAPI
3665{
3668 POBJECT_NAME_INFORMATION LocalInfo;
3669
3670 /* Start with a buffer length of 200 */
3671 ReturnLength = 200;
3672 /*
3673 * We'll loop until query works.
3674 * We will use returned length for next loop
3675 * iteration, trying to have a big enough buffer.
3676 */
3677 for (Length = 200; ; Length = ReturnLength)
3678 {
3679 /* Allocate our work buffer */
3680 LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, 'nDoI');
3681 if (LocalInfo == NULL)
3682 {
3684 }
3685
3686 /* Query the DOS name */
3688 TRUE,
3689 TRUE,
3690 LocalInfo,
3691 Length,
3692 &ReturnLength,
3693 KernelMode);
3694 /* If it succeed, nothing more to do */
3695 if (Status == STATUS_SUCCESS)
3696 {
3697 break;
3698 }
3699
3700 /* Otherwise, prepare for re-allocation */
3701 ExFreePoolWithTag(LocalInfo, 'nDoI');
3702
3703 /*
3704 * If we failed because of something else
3705 * than memory, simply stop and fail here
3706 */
3708 {
3709 return Status;
3710 }
3711 }
3712
3713 /* Success case here: return our buffer */
3714 *ObjectNameInformation = LocalInfo;
3715 return STATUS_SUCCESS;
3716}
3717
3718/*
3719 * @implemented
3720 */
3722NTAPI
3724 IN BOOLEAN Remote)
3725{
3727 BOOLEAN FlagSet;
3728
3729 /* Get the flag status */
3730 FlagSet = FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE;
3731
3732 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
3733 if (Remote && !FlagSet)
3734 {
3735 /* Set the flag */
3736 FileObject->Flags |= FO_REMOTE_ORIGIN;
3737 }
3738 else if (!Remote && FlagSet)
3739 {
3740 /* Remove the flag */
3741 FileObject->Flags &= ~FO_REMOTE_ORIGIN;
3742 }
3743 else
3744 {
3745 /* Fail */
3747 }
3748
3749 /* Return status */
3750 return Status;
3751}
3752
3753/*
3754 * @implemented
3755 */
3757NTAPI
3762 PLARGE_INTEGER AllocateSize,
3769{
3770 /* Call the I/O Function */
3771 return IoCreateFile(FileHandle,
3775 AllocateSize,
3780 EaBuffer,
3781 EaLength,
3783 NULL,
3784 0);
3785}
3786
3788NTAPI
3794 IN ULONG MailslotQuota,
3795 IN ULONG MaxMessageSize,
3796 IN PLARGE_INTEGER TimeOut)
3797{
3799 PAGED_CODE();
3800
3801 /* Check for Timeout */
3802 if (TimeOut)
3803 {
3804 /* check if the call came from user mode */
3806 {
3807 /* Enter SEH for Probe */
3808 _SEH2_TRY
3809 {
3810 /* Probe the timeout */
3811 Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
3812 }
3814 {
3815 /* Return the exception code */
3817 }
3818 _SEH2_END;
3819 }
3820 else
3821 {
3822 /* Otherwise, capture directly */
3823 Buffer.ReadTimeout = *TimeOut;
3824 }
3825
3826 /* Set the correct setting */
3827 Buffer.TimeoutSpecified = TRUE;
3828 }
3829 else
3830 {
3831 /* Tell the FSD we don't have a timeout */
3832 Buffer.TimeoutSpecified = FALSE;
3833 }
3834
3835 /* Set Settings */
3836 Buffer.MailslotQuota = MailslotQuota;
3837 Buffer.MaximumMessageSize = MaxMessageSize;
3838
3839 /* Call I/O */
3840 return IoCreateFile(FileHandle,
3844 NULL,
3845 0,
3849 NULL,
3850 0,
3852 (PVOID)&Buffer,
3853 0);
3854}
3855
3857NTAPI
3865 IN ULONG NamedPipeType,
3866 IN ULONG ReadMode,
3867 IN ULONG CompletionMode,
3868 IN ULONG MaximumInstances,
3869 IN ULONG InboundQuota,
3870 IN ULONG OutboundQuota,
3871 IN PLARGE_INTEGER DefaultTimeout)
3872{
3874 PAGED_CODE();
3875
3876 /* Check for Timeout */
3877 if (DefaultTimeout)
3878 {
3879 /* check if the call came from user mode */
3881 {
3882 /* Enter SEH for Probe */
3883 _SEH2_TRY
3884 {
3885 /* Probe the timeout */
3886 Buffer.DefaultTimeout =
3887 ProbeForReadLargeInteger(DefaultTimeout);
3888 }
3890 {
3891 /* Return the exception code */
3893 }
3894 _SEH2_END;
3895 }
3896 else
3897 {
3898 /* Otherwise, capture directly */
3899 Buffer.DefaultTimeout = *DefaultTimeout;
3900 }
3901
3902 /* Set the correct setting */
3903 Buffer.TimeoutSpecified = TRUE;
3904 }
3905 else
3906 {
3907 /* Tell the FSD we don't have a timeout */
3908 Buffer.TimeoutSpecified = FALSE;
3909 }
3910
3911 /* Set Settings */
3912 Buffer.NamedPipeType = NamedPipeType;
3913 Buffer.ReadMode = ReadMode;
3914 Buffer.CompletionMode = CompletionMode;
3915 Buffer.MaximumInstances = MaximumInstances;
3916 Buffer.InboundQuota = InboundQuota;
3917 Buffer.OutboundQuota = OutboundQuota;
3918
3919 /* Call I/O */
3920 return IoCreateFile(FileHandle,
3924 NULL,
3925 0,
3929 NULL,
3930 0,
3932 (PVOID)&Buffer,
3933 0);
3934}
3935
3937NTAPI
3939{
3940 PAGED_CODE();
3941
3942 /* Call the kernel */
3944 return STATUS_SUCCESS;
3945}
3946
3947/*
3948 * @implemented
3949 */
3951NTAPI
3958{
3959 /* Call the I/O Function */
3960 return IoCreateFile(FileHandle,
3964 NULL,
3965 0,
3967 FILE_OPEN,
3969 NULL,
3970 0,
3972 NULL,
3973 0);
3974}
3975
3977NTAPI
3980{
3981 /* Call the internal helper API */
3984 sizeof(FILE_BASIC_INFORMATION),
3986}
3987
3989NTAPI
3992{
3993 /* Call the internal helper API */
3998}
3999
4018NTAPI
4021{
4024 PIRP Irp;
4025 KIRQL OldIrql;
4026 BOOLEAN OurIrpsInList = FALSE;
4030 PLIST_ENTRY ListHead, NextEntry;
4031 PAGED_CODE();
4032 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
4033
4034 /* Check the previous mode */
4035 if (PreviousMode != KernelMode)
4036 {
4037 /* Enter SEH for probing */
4038 _SEH2_TRY
4039 {
4040 /* Probe the I/O Status Block */
4042 }
4044 {
4045 /* Return the exception code */
4047 }
4048 _SEH2_END;
4049 }
4050
4051 /* Reference the file object */
4053 0,
4056 (PVOID*)&FileObject,
4057 NULL);
4058 if (!NT_SUCCESS(Status)) return Status;
4059
4060 /* IRP cancellations are synchronized at APC_LEVEL. */
4062
4063 /* Get the current thread */
4065
4066 /* Update the operation counts */
4068
4069 /* Loop the list */
4070 ListHead = &Thread->IrpList;
4071 NextEntry = ListHead->Flink;
4072 while (ListHead != NextEntry)
4073 {
4074 /* Get the IRP and check if the File Object matches */
4075 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
4076 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
4077 {
4078 /* Cancel this IRP and keep looping */
4080 OurIrpsInList = TRUE;
4081 }
4082
4083 /* Go to the next entry */
4084 NextEntry = NextEntry->Flink;
4085 }
4086
4087 /* Lower the IRQL */
4089
4090 /* Check if we had found an IRP */
4091 if (OurIrpsInList)
4092 {
4093 /* Setup a 10ms wait */
4094 Interval.QuadPart = -100000;
4095
4096 /* Start looping */
4097 while (OurIrpsInList)
4098 {
4099 /* Do the wait */
4101 OurIrpsInList = FALSE;
4102
4103 /* Raise IRQL */
4105
4106 /* Now loop the list again */
4107 NextEntry = ListHead->Flink;
4108 while (NextEntry != ListHead)
4109 {
4110 /* Get the IRP and check if the File Object matches */
4111 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
4112 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
4113 {
4114 /* Keep looping */
4115 OurIrpsInList = TRUE;
4116 break;
4117 }
4118
4119 /* Go to the next entry */
4120 NextEntry = NextEntry->Flink;
4121 }
4122
4123 /* Lower the IRQL */
4125 }
4126 }
4127
4128 /* Enter SEH for writing back the I/O Status */
4129 _SEH2_TRY
4130 {
4131 /* Write success */
4134 }
4136 {
4137 /* Ignore exception */
4138 }
4139 _SEH2_END;
4140
4141 /* Dereference the file object and return success */
4143 return STATUS_SUCCESS;
4144}
4145
4146/*
4147 * @implemented
4148 */
4150NTAPI
4152{
4154 DUMMY_FILE_OBJECT LocalFileObject;
4155 HANDLE Handle;
4157 OPEN_PACKET OpenPacket;
4158 PAGED_CODE();
4159 IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName);
4160
4161 /* Setup the Open Packet */
4162 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
4163 OpenPacket.Type = IO_TYPE_OPEN_PACKET;
4164 OpenPacket.Size = sizeof(OPEN_PACKET);
4166 OpenPacket.ShareAccess = FILE_SHARE_READ |
4169 OpenPacket.Disposition = FILE_OPEN;
4170 OpenPacket.DeleteOnly = TRUE;
4171 OpenPacket.LocalFileObject = &LocalFileObject;
4172
4173 /* Update the operation counts */
4175
4176 /*
4177 * Attempt opening the file. This will call the I/O Parse Routine for
4178 * the File Object (IopParseDevice) which will use the dummy file obejct
4179 * send the IRP to its device object. Note that we have two statuses
4180 * to worry about: the Object Manager's status (in Status) and the I/O
4181 * status, which is in the Open Packet's Final Status, and determined
4182 * by the Parse Check member.
4183 */
4185 NULL,
4186 AccessMode,
4187 NULL,
4188 DELETE,
4189 &OpenPacket,
4190 &Handle);
4191 if (OpenPacket.ParseCheck == FALSE) return Status;
4192
4193 /* Retrn the Io status */
4194 return OpenPacket.FinalStatus;
4195}
4196
4197/* EOF */
#define PAGED_CODE()
@ ObjectNameInformation
Definition: DriverTester.h:55
unsigned char BOOLEAN
static GENERIC_MAPPING GenericMapping
Definition: SeInheritance.c:11
Type
Definition: Type.h:7
BOOLEAN NTAPI SeAccessCheck(_In_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext, _In_ BOOLEAN SubjectContextLocked, _In_ ACCESS_MASK DesiredAccess, _In_ ACCESS_MASK PreviouslyGrantedAccess, _Out_ PPRIVILEGE_SET *Privileges, _In_ PGENERIC_MAPPING GenericMapping, _In_ KPROCESSOR_MODE AccessMode, _Out_ PACCESS_MASK GrantedAccess, _Out_ PNTSTATUS AccessStatus)
Determines whether security access rights can be given to an object depending on the security descrip...
Definition: accesschk.c:1994
#define VOID
Definition: acefi.h:82
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_OPEN_FOR_FREE_SPACE_QUERY
Definition: constants.h:495
#define FILE_COMPLETE_IF_OPLOCKED
Definition: constants.h:493
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
#define DPRINT1
Definition: precomp.h:8
@ Update
Definition: registry.c:565
@ LocalDevice
Definition: bl.h:261
#define UNIMPLEMENTED
Definition: debug.h:115
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DEVICE_TYPE
Definition: guid.c:10
#define FILE_SHARE_READ
Definition: compat.h:136
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4147
#define ULONG_PTR
Definition: config.h:101
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define DO_EXCLUSIVE
Definition: env_spec_w32.h:395
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define NonPagedPool
Definition: env_spec_w32.h:307
ULONG ERESOURCE
Definition: env_spec_w32.h:594
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define DO_NEVER_LAST_DEVICE
Definition: env_spec_w32.h:402
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621
#define PagedPool
Definition: env_spec_w32.h:308
@ Success
Definition: eventcreate.c:712
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define ExGetPreviousMode
Definition: ex.h:140
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1675
IN PVCB IN PDIRENT OUT PULONG EaLength
Definition: fatprocs.h:878
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
VOID NTAPI FsRtlPTeardownPerFileObjectContexts(IN PFILE_OBJECT FileObject)
Definition: filtrctx.c:28
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
Definition: fltkernel.h:1236
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ SECURITY_INFORMATION SecurityInformation
Definition: fltkernel.h:1340
#define FILE_OPEN_BY_FILE_ID
Definition: from_kernel.h:41
@ FileNameInformation
Definition: from_kernel.h:70
@ FileNetworkOpenInformation
Definition: from_kernel.h:95
@ FileBasicInformation
Definition: from_kernel.h:65
#define FILE_MAXIMUM_DISPOSITION
Definition: from_kernel.h:59
#define FILE_NO_COMPRESSION
Definition: from_kernel.h:43
#define FILE_OPEN
Definition: from_kernel.h:54
#define FILE_CREATE
Definition: from_kernel.h:55
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_RESERVE_OPFILTER
Definition: from_kernel.h:45
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
#define FILE_RANDOM_ACCESS
Definition: from_kernel.h:38
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define FILE_SEQUENTIAL_ONLY
Definition: from_kernel.h:27
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
_In_ PLIST_ENTRY _In_ PSTRING _In_ USHORT _In_opt_ PSTRING _In_opt_ PSTRING _In_ ULONG _In_ ULONG _In_opt_ PVOID _In_opt_ PVOID FilterContext
Definition: fsrtlfuncs.h:746
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLfloat GLfloat p
Definition: glext.h:8902
VOID NTAPI KeFlushWriteBuffer(VOID)
Definition: misc.c:39
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
__in WDFOBJECT __in PCWDF_OBJECT_CONTEXT_TYPE_INFO TypeInfo
Definition: handleapi.cpp:601
HLOCAL NTAPI LocalHandle(LPCVOID pMem)
Definition: heapmem.c:1605
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
struct _FILE_NAME_INFORMATION * PFILE_NAME_INFORMATION
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
static __inline NTSTATUS IopLockFileObject(_In_ PFILE_OBJECT FileObject, _In_ KPROCESSOR_MODE WaitMode)
Definition: io_x.h:12
static __inline BOOLEAN IopValidateOpenPacket(IN POPEN_PACKET OpenPacket)
Definition: io_x.h:154
FORCEINLINE VOID IopQueueIrpToThread(IN PIRP Irp)
Definition: io_x.h:49
static __inline VOID IopUpdateOperationCount(IN IOP_TRANSFER_TYPE Type)
Definition: io_x.h:82
static __inline VOID IopUnlockFileObject(IN PFILE_OBJECT FileObject)
Definition: io_x.h:36
FORCEINLINE VOID IopUnQueueIrpFromThread(IN PIRP Irp)
Definition: io_x.h:66
NTSTATUS NTAPI IoQueryFileInformation(IN PFILE_OBJECT FileObject, IN FILE_INFORMATION_CLASS FileInformationClass, IN ULONG Length, OUT PVOID FileInformation, OUT PULONG ReturnedLength)
Definition: iofunc.c:1274
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define REPARSE_DATA_BUFFER_HEADER_SIZE
Definition: vista.c:17
DeviceType
Definition: mmdrv.h:42
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define FILE_BASIC_INFORMATION
Definition: disk.h:53
ObjectType
Definition: metafile.c:81
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static OUT PIO_STATUS_BLOCK OUT PVOID FileInformation
Definition: pipe.c:75
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
DWORD * PSECURITY_INFORMATION
Definition: ms-dtyp.idl:311
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
_Out_ PNDIS_HANDLE _Out_ PUINT FileLength
Definition: ndis.h:3228
_Must_inspect_result_ _Out_ PNDIS_STATUS _Out_ PNDIS_STATUS _Out_ PNDIS_HANDLE _Out_ PUINT _In_ UINT _In_ NDIS_HANDLE _In_ NDIS_HANDLE _In_ PNDIS_STRING _In_ UINT OpenOptions
Definition: ndis.h:6017
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define KeGetPreviousMode()
Definition: ketypes.h:1115
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
_In_ PVOID _In_ BOOLEAN Alertable
Definition: exfuncs.h:453
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
#define DOE_DELETE_PENDING
Definition: iotypes.h:150
#define FILE_PIPE_MESSAGE_TYPE
Definition: iotypes.h:76
#define FO_FILE_OBJECT_HAS_EXTENSION
Definition: iotypes.h:144
#define IO_ATTACH_DEVICE_API
Definition: iotypes.h:218
#define DOE_REMOVE_PROCESSED
Definition: iotypes.h:152
#define DOE_UNLOAD_PENDING
Definition: iotypes.h:149
#define FILE_PIPE_COMPLETE_OPERATION
Definition: iotypes.h:80