1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Kernel 3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: ntoskrnl/io/iomgr/file.c 5c2c66affSColin Finck * PURPOSE: Functions that deal with managing the FILE_OBJECT itself. 6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7c2c66affSColin Finck * Gunnar Dalsnes 8c2c66affSColin Finck * Eric Kohl 9c2c66affSColin Finck * Filip Navara (navaraf@reactos.org) 10890a2936SPierre Schweitzer * Pierre Schweitzer 11c2c66affSColin Finck */ 12c2c66affSColin Finck 13c2c66affSColin Finck /* INCLUDES *****************************************************************/ 14c2c66affSColin Finck 15c2c66affSColin Finck #include <ntoskrnl.h> 16c2c66affSColin Finck #define NDEBUG 17c2c66affSColin Finck #include <debug.h> 18c2c66affSColin Finck 19c2c66affSColin Finck extern ERESOURCE IopSecurityResource; 20c2c66affSColin Finck 21c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 22c2c66affSColin Finck 23c2c66affSColin Finck VOID 24c2c66affSColin Finck NTAPI 25c2c66affSColin Finck IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState, 26c2c66affSColin Finck IN OUT PULONG CreateOptions, 27c2c66affSColin Finck IN KPROCESSOR_MODE PreviousMode, 28c2c66affSColin Finck IN ULONG Disposition) 29c2c66affSColin Finck { 30c2c66affSColin Finck ACCESS_MASK DesiredAccess, ReadAccess, WriteAccess; 31c2c66affSColin Finck PRIVILEGE_SET Privileges; 32c2c66affSColin Finck BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE; 33c2c66affSColin Finck PAGED_CODE(); 34c2c66affSColin Finck 35c2c66affSColin Finck /* Don't do anything if privileges were checked already */ 36c2c66affSColin Finck if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return; 37c2c66affSColin Finck 38c2c66affSColin Finck /* Check if the file was actually opened for backup purposes */ 39c2c66affSColin Finck if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT) 40c2c66affSColin Finck { 41c2c66affSColin Finck /* Set the check flag since were doing it now */ 42c2c66affSColin Finck AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED; 43c2c66affSColin Finck 44c2c66affSColin Finck /* Set the access masks required */ 45c2c66affSColin Finck ReadAccess = READ_CONTROL | 46c2c66affSColin Finck ACCESS_SYSTEM_SECURITY | 47c2c66affSColin Finck FILE_GENERIC_READ | 48c2c66affSColin Finck FILE_TRAVERSE; 49c2c66affSColin Finck WriteAccess = WRITE_DAC | 50c2c66affSColin Finck WRITE_OWNER | 51c2c66affSColin Finck ACCESS_SYSTEM_SECURITY | 52c2c66affSColin Finck FILE_GENERIC_WRITE | 53c2c66affSColin Finck FILE_ADD_FILE | 54c2c66affSColin Finck FILE_ADD_SUBDIRECTORY | 55c2c66affSColin Finck DELETE; 56c2c66affSColin Finck DesiredAccess = AccessState->RemainingDesiredAccess; 57c2c66affSColin Finck 58c2c66affSColin Finck /* Check if desired access was the maximum */ 59c2c66affSColin Finck if (DesiredAccess & MAXIMUM_ALLOWED) 60c2c66affSColin Finck { 61c2c66affSColin Finck /* Then add all the access masks required */ 62c2c66affSColin Finck DesiredAccess |= (ReadAccess | WriteAccess); 63c2c66affSColin Finck } 64c2c66affSColin Finck 65c2c66affSColin Finck /* Check if the file already exists */ 66c2c66affSColin Finck if (Disposition & FILE_OPEN) 67c2c66affSColin Finck { 68c2c66affSColin Finck /* Check if desired access has the read mask */ 69c2c66affSColin Finck if (ReadAccess & DesiredAccess) 70c2c66affSColin Finck { 71c2c66affSColin Finck /* Setup the privilege check lookup */ 72c2c66affSColin Finck Privileges.PrivilegeCount = 1; 73c2c66affSColin Finck Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 74c2c66affSColin Finck Privileges.Privilege[0].Luid = SeBackupPrivilege; 75c2c66affSColin Finck Privileges.Privilege[0].Attributes = 0; 76c2c66affSColin Finck AccessGranted = SePrivilegeCheck(&Privileges, 77c2c66affSColin Finck &AccessState-> 78c2c66affSColin Finck SubjectSecurityContext, 79c2c66affSColin Finck PreviousMode); 80c2c66affSColin Finck if (AccessGranted) 81c2c66affSColin Finck { 82c2c66affSColin Finck /* Remember that backup was allowed */ 83c2c66affSColin Finck HaveBackupPriv = TRUE; 84c2c66affSColin Finck 85c2c66affSColin Finck /* Append the privileges and update the access state */ 86c2c66affSColin Finck SeAppendPrivileges(AccessState, &Privileges); 87c2c66affSColin Finck AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess); 88c2c66affSColin Finck AccessState->RemainingDesiredAccess &= ~ReadAccess; 89c2c66affSColin Finck DesiredAccess &= ~ReadAccess; 90c2c66affSColin Finck 91c2c66affSColin Finck /* Set backup privilege for the token */ 92c2c66affSColin Finck AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE; 93c2c66affSColin Finck } 94c2c66affSColin Finck } 95c2c66affSColin Finck } 96c2c66affSColin Finck else 97c2c66affSColin Finck { 98c2c66affSColin Finck /* Caller is creating the file, check restore privileges later */ 99c2c66affSColin Finck CheckRestore = TRUE; 100c2c66affSColin Finck } 101c2c66affSColin Finck 102c2c66affSColin Finck /* Check if caller wants write access or if it's creating a file */ 103c2c66affSColin Finck if ((WriteAccess & DesiredAccess) || (CheckRestore)) 104c2c66affSColin Finck { 105c2c66affSColin Finck /* Setup the privilege lookup and do it */ 106c2c66affSColin Finck Privileges.PrivilegeCount = 1; 107c2c66affSColin Finck Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 108c2c66affSColin Finck Privileges.Privilege[0].Luid = SeRestorePrivilege; 109c2c66affSColin Finck Privileges.Privilege[0].Attributes = 0; 110c2c66affSColin Finck AccessGranted = SePrivilegeCheck(&Privileges, 111c2c66affSColin Finck &AccessState->SubjectSecurityContext, 112c2c66affSColin Finck PreviousMode); 113c2c66affSColin Finck if (AccessGranted) 114c2c66affSColin Finck { 115c2c66affSColin Finck /* Remember that privilege was given */ 116c2c66affSColin Finck HaveBackupPriv = TRUE; 117c2c66affSColin Finck 118c2c66affSColin Finck /* Append the privileges and update the access state */ 119c2c66affSColin Finck SeAppendPrivileges(AccessState, &Privileges); 120c2c66affSColin Finck AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess); 121c2c66affSColin Finck AccessState->RemainingDesiredAccess &= ~WriteAccess; 122c2c66affSColin Finck 123c2c66affSColin Finck /* Set restore privilege for the token */ 124c2c66affSColin Finck AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE; 125c2c66affSColin Finck } 126c2c66affSColin Finck } 127c2c66affSColin Finck 128c2c66affSColin Finck /* If we don't have the privilege, remove the option */ 129c2c66affSColin Finck if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT; 130c2c66affSColin Finck } 131c2c66affSColin Finck } 132c2c66affSColin Finck 133c2c66affSColin Finck NTSTATUS 134c2c66affSColin Finck NTAPI 135c2c66affSColin Finck IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket, 136c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject) 137c2c66affSColin Finck { 138c2c66affSColin Finck /* Make sure the object is valid */ 139c2c66affSColin Finck if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags & 140c2c66affSColin Finck (DOE_UNLOAD_PENDING | 141c2c66affSColin Finck DOE_DELETE_PENDING | 142c2c66affSColin Finck DOE_REMOVE_PENDING | 143c2c66affSColin Finck DOE_REMOVE_PROCESSED)) || 144c2c66affSColin Finck (DeviceObject->Flags & DO_DEVICE_INITIALIZING)) 145c2c66affSColin Finck { 146c2c66affSColin Finck /* It's unloading or initializing, so fail */ 147c2c66affSColin Finck DPRINT1("You are seeing this because the following ROS driver: %wZ\n" 148c2c66affSColin Finck " sucks. Please fix it's AddDevice Routine\n", 149c2c66affSColin Finck &DeviceObject->DriverObject->DriverName); 150c2c66affSColin Finck return STATUS_NO_SUCH_DEVICE; 151c2c66affSColin Finck } 152c2c66affSColin Finck else if ((DeviceObject->Flags & DO_EXCLUSIVE) && 153c2c66affSColin Finck (DeviceObject->ReferenceCount) && 154c2c66affSColin Finck !(OpenPacket->RelatedFileObject) && 155c2c66affSColin Finck !(OpenPacket->Options & IO_ATTACH_DEVICE)) 156c2c66affSColin Finck { 157c2c66affSColin Finck return STATUS_ACCESS_DENIED; 158c2c66affSColin Finck } 159c2c66affSColin Finck 160c2c66affSColin Finck else 161c2c66affSColin Finck { 162c2c66affSColin Finck /* Increase reference count */ 163c2c66affSColin Finck InterlockedIncrement(&DeviceObject->ReferenceCount); 164c2c66affSColin Finck return STATUS_SUCCESS; 165c2c66affSColin Finck } 166c2c66affSColin Finck } 167c2c66affSColin Finck 168c2c66affSColin Finck VOID 169c2c66affSColin Finck NTAPI 170c2c66affSColin Finck IopDoNameTransmogrify(IN PIRP Irp, 171c2c66affSColin Finck IN PFILE_OBJECT FileObject, 172c2c66affSColin Finck IN PREPARSE_DATA_BUFFER DataBuffer) 173c2c66affSColin Finck { 174c2c66affSColin Finck PWSTR Buffer; 175c2c66affSColin Finck USHORT Length; 176c2c66affSColin Finck USHORT RequiredLength; 177c2c66affSColin Finck PWSTR NewBuffer; 178c2c66affSColin Finck 179c2c66affSColin Finck PAGED_CODE(); 180c2c66affSColin Finck 181c2c66affSColin Finck ASSERT(Irp->IoStatus.Status == STATUS_REPARSE); 182c2c66affSColin Finck ASSERT(Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT); 183c2c66affSColin Finck ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL); 184c2c66affSColin Finck ASSERT(DataBuffer != NULL); 185c2c66affSColin Finck ASSERT(DataBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT); 186c2c66affSColin Finck ASSERT(DataBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE); 187c2c66affSColin Finck ASSERT(DataBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE); 188c2c66affSColin Finck 189c2c66affSColin Finck /* First of all, validate data */ 190c2c66affSColin Finck if (DataBuffer->ReparseDataLength < REPARSE_DATA_BUFFER_HEADER_SIZE || 191c2c66affSColin Finck (DataBuffer->SymbolicLinkReparseBuffer.PrintNameLength + 192c2c66affSColin Finck DataBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + 193c2c66affSColin Finck FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0])) > MAXIMUM_REPARSE_DATA_BUFFER_SIZE) 194c2c66affSColin Finck { 195c2c66affSColin Finck Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID; 196c2c66affSColin Finck } 197c2c66affSColin Finck 198c2c66affSColin Finck /* Everything went right */ 199c2c66affSColin Finck if (NT_SUCCESS(Irp->IoStatus.Status)) 200c2c66affSColin Finck { 201c2c66affSColin Finck /* Compute buffer & length */ 202c2c66affSColin Finck Buffer = (PWSTR)((ULONG_PTR)DataBuffer->MountPointReparseBuffer.PathBuffer + 203c2c66affSColin Finck DataBuffer->MountPointReparseBuffer.SubstituteNameOffset); 204c2c66affSColin Finck Length = DataBuffer->MountPointReparseBuffer.SubstituteNameLength; 205c2c66affSColin Finck 206c2c66affSColin Finck /* Check we don't overflow */ 207c2c66affSColin Finck if (((ULONG)MAXUSHORT - DataBuffer->Reserved) <= (Length + sizeof(UNICODE_NULL))) 208c2c66affSColin Finck { 209c2c66affSColin Finck Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID; 210c2c66affSColin Finck } 211c2c66affSColin Finck else 212c2c66affSColin Finck { 213c2c66affSColin Finck /* Compute how much mem we'll need */ 214c2c66affSColin Finck RequiredLength = DataBuffer->Reserved + Length + sizeof(UNICODE_NULL); 215c2c66affSColin Finck 216c2c66affSColin Finck /* Check if FileObject can already hold what we need */ 217c2c66affSColin Finck if (FileObject->FileName.MaximumLength >= RequiredLength) 218c2c66affSColin Finck { 219c2c66affSColin Finck NewBuffer = FileObject->FileName.Buffer; 220c2c66affSColin Finck } 221c2c66affSColin Finck else 222c2c66affSColin Finck { 223c2c66affSColin Finck /* Allocate otherwise */ 224c2c66affSColin Finck NewBuffer = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_IO_NAME); 225c2c66affSColin Finck if (NewBuffer == NULL) 226c2c66affSColin Finck { 227c2c66affSColin Finck Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 228c2c66affSColin Finck } 229c2c66affSColin Finck } 230c2c66affSColin Finck } 231c2c66affSColin Finck } 232c2c66affSColin Finck 233c2c66affSColin Finck /* Everything went right */ 234c2c66affSColin Finck if (NT_SUCCESS(Irp->IoStatus.Status)) 235c2c66affSColin Finck { 236c2c66affSColin Finck /* Copy reserved */ 237c2c66affSColin Finck if (DataBuffer->Reserved) 238c2c66affSColin Finck { 239c2c66affSColin Finck RtlMoveMemory((PWSTR)((ULONG_PTR)NewBuffer + Length), 240c2c66affSColin Finck (PWSTR)((ULONG_PTR)FileObject->FileName.Buffer + FileObject->FileName.Length - DataBuffer->Reserved), 241c2c66affSColin Finck DataBuffer->Reserved); 242c2c66affSColin Finck } 243c2c66affSColin Finck 244c2c66affSColin Finck /* Then, buffer */ 245c2c66affSColin Finck if (Length) 246c2c66affSColin Finck { 247c2c66affSColin Finck RtlCopyMemory(NewBuffer, Buffer, Length); 248c2c66affSColin Finck } 249c2c66affSColin Finck 250c2c66affSColin Finck /* And finally replace buffer if new one was allocated */ 251c2c66affSColin Finck FileObject->FileName.Length = RequiredLength - sizeof(UNICODE_NULL); 252c2c66affSColin Finck if (NewBuffer != FileObject->FileName.Buffer) 253c2c66affSColin Finck { 254c2c66affSColin Finck if (FileObject->FileName.Buffer) 255c2c66affSColin Finck { 256c2c66affSColin Finck ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME); 257c2c66affSColin Finck } 258c2c66affSColin Finck 259c2c66affSColin Finck FileObject->FileName.Buffer = NewBuffer; 260c2c66affSColin Finck FileObject->FileName.MaximumLength = RequiredLength; 261c2c66affSColin Finck FileObject->FileName.Buffer[RequiredLength / sizeof(WCHAR) - 1] = UNICODE_NULL; 262c2c66affSColin Finck } 263c2c66affSColin Finck } 264c2c66affSColin Finck 265c2c66affSColin Finck /* We don't need them anymore - it was allocated by the driver */ 266c2c66affSColin Finck ExFreePool(DataBuffer); 267c2c66affSColin Finck } 268c2c66affSColin Finck 269c2c66affSColin Finck NTSTATUS 270c2c66affSColin Finck NTAPI 271c2c66affSColin Finck IopParseDevice(IN PVOID ParseObject, 272c2c66affSColin Finck IN PVOID ObjectType, 273c2c66affSColin Finck IN OUT PACCESS_STATE AccessState, 274c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 275c2c66affSColin Finck IN ULONG Attributes, 276c2c66affSColin Finck IN OUT PUNICODE_STRING CompleteName, 277c2c66affSColin Finck IN OUT PUNICODE_STRING RemainingName, 278c2c66affSColin Finck IN OUT PVOID Context, 279c2c66affSColin Finck IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, 280c2c66affSColin Finck OUT PVOID *Object) 281c2c66affSColin Finck { 282c2c66affSColin Finck POPEN_PACKET OpenPacket = (POPEN_PACKET)Context; 283c2c66affSColin Finck PDEVICE_OBJECT OriginalDeviceObject = (PDEVICE_OBJECT)ParseObject; 284c2c66affSColin Finck PDEVICE_OBJECT DeviceObject, OwnerDevice; 285c2c66affSColin Finck NTSTATUS Status; 286c2c66affSColin Finck PFILE_OBJECT FileObject; 287c2c66affSColin Finck PVPB Vpb = NULL; 288c2c66affSColin Finck PIRP Irp; 289ca9fd861STimo Kreuzer PIO_STACK_LOCATION StackLoc; 290c2c66affSColin Finck IO_SECURITY_CONTEXT SecurityContext; 291c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 292c2c66affSColin Finck BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile; 293c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 294c2c66affSColin Finck KIRQL OldIrql; 295c2c66affSColin Finck PDUMMY_FILE_OBJECT LocalFileObject; 296c2c66affSColin Finck PFILE_BASIC_INFORMATION FileBasicInfo; 297c2c66affSColin Finck ULONG ReturnLength; 298c2c66affSColin Finck KPROCESSOR_MODE CheckMode; 299c2c66affSColin Finck BOOLEAN VolumeOpen = FALSE; 300c2c66affSColin Finck ACCESS_MASK DesiredAccess, GrantedAccess; 301c2c66affSColin Finck BOOLEAN AccessGranted, LockHeld = FALSE; 302c2c66affSColin Finck PPRIVILEGE_SET Privileges = NULL; 303c2c66affSColin Finck UNICODE_STRING FileString; 304c2c66affSColin Finck USHORT Attempt; 305c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n", 306c2c66affSColin Finck ParseObject, RemainingName); 307c2c66affSColin Finck 308c2c66affSColin Finck for (Attempt = 0; Attempt < IOP_MAX_REPARSE_TRAVERSAL; ++Attempt) 309c2c66affSColin Finck { 310c2c66affSColin Finck /* Assume failure */ 311c2c66affSColin Finck *Object = NULL; 312c2c66affSColin Finck 313c2c66affSColin Finck /* Validate the open packet */ 314c2c66affSColin Finck if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH; 315c2c66affSColin Finck 316c2c66affSColin Finck /* Valide reparse point in case we traversed a mountpoint */ 317c2c66affSColin Finck if (OpenPacket->TraversedMountPoint) 318c2c66affSColin Finck { 319c2c66affSColin Finck /* This is a reparse point we understand */ 320c2c66affSColin Finck ASSERT(OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT); 321c2c66affSColin Finck 322c2c66affSColin Finck /* Make sure we're dealing with correct DO */ 323c2c66affSColin Finck if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK && 324c2c66affSColin Finck OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM && 325c2c66affSColin Finck OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK && 326c2c66affSColin Finck OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE) 327c2c66affSColin Finck { 328c2c66affSColin Finck OpenPacket->FinalStatus = STATUS_IO_REPARSE_DATA_INVALID; 329c2c66affSColin Finck return STATUS_IO_REPARSE_DATA_INVALID; 330c2c66affSColin Finck } 331c2c66affSColin Finck } 332c2c66affSColin Finck 333c2c66affSColin Finck /* Check if we have a related file object */ 334c2c66affSColin Finck if (OpenPacket->RelatedFileObject) 335c2c66affSColin Finck { 336c2c66affSColin Finck /* Use the related file object's device object */ 337c2c66affSColin Finck OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject; 338c2c66affSColin Finck } 339c2c66affSColin Finck 340c2c66affSColin Finck /* Validate device status */ 341c2c66affSColin Finck Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject); 342c2c66affSColin Finck if (!NT_SUCCESS(Status)) 343c2c66affSColin Finck { 344c2c66affSColin Finck /* We failed, return status */ 345c2c66affSColin Finck OpenPacket->FinalStatus = Status; 346c2c66affSColin Finck return Status; 347c2c66affSColin Finck } 348c2c66affSColin Finck 349c2c66affSColin Finck /* Map the generic mask and set the new mapping in the access state */ 350c2c66affSColin Finck RtlMapGenericMask(&AccessState->RemainingDesiredAccess, 351c2c66affSColin Finck &IoFileObjectType->TypeInfo.GenericMapping); 352c2c66affSColin Finck RtlMapGenericMask(&AccessState->OriginalDesiredAccess, 353c2c66affSColin Finck &IoFileObjectType->TypeInfo.GenericMapping); 354c2c66affSColin Finck SeSetAccessStateGenericMapping(AccessState, 355c2c66affSColin Finck &IoFileObjectType->TypeInfo.GenericMapping); 356c2c66affSColin Finck DesiredAccess = AccessState->RemainingDesiredAccess; 357c2c66affSColin Finck 358c2c66affSColin Finck /* Check what kind of access checks to do */ 359c2c66affSColin Finck if ((AccessMode != KernelMode) || 360c2c66affSColin Finck (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) 361c2c66affSColin Finck { 362c2c66affSColin Finck /* Call is from user-mode or kernel is forcing checks */ 363c2c66affSColin Finck CheckMode = UserMode; 364c2c66affSColin Finck } 365c2c66affSColin Finck else 366c2c66affSColin Finck { 367c2c66affSColin Finck /* Call is from the kernel */ 368c2c66affSColin Finck CheckMode = KernelMode; 369c2c66affSColin Finck } 370c2c66affSColin Finck 371c2c66affSColin Finck /* Check privilege for backup or restore operation */ 372c2c66affSColin Finck IopCheckBackupRestorePrivilege(AccessState, 373c2c66affSColin Finck &OpenPacket->CreateOptions, 374c2c66affSColin Finck CheckMode, 375c2c66affSColin Finck OpenPacket->Disposition); 376c2c66affSColin Finck 377c2c66affSColin Finck /* Check if we are re-parsing */ 378c2c66affSColin Finck if (((OpenPacket->Override) && !(RemainingName->Length)) || 379c2c66affSColin Finck (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED)) 380c2c66affSColin Finck { 381c2c66affSColin Finck /* Get granted access from the last call */ 382c2c66affSColin Finck DesiredAccess |= AccessState->PreviouslyGrantedAccess; 383c2c66affSColin Finck } 384c2c66affSColin Finck 385c2c66affSColin Finck /* Check if this is a volume open */ 386c2c66affSColin Finck if ((OpenPacket->RelatedFileObject) && 387c2c66affSColin Finck (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) && 388c2c66affSColin Finck !(RemainingName->Length)) 389c2c66affSColin Finck { 390c2c66affSColin Finck /* It is */ 391c2c66affSColin Finck VolumeOpen = TRUE; 392c2c66affSColin Finck } 393c2c66affSColin Finck 394c2c66affSColin Finck /* Now check if we need access checks */ 395c2c66affSColin Finck if (((AccessMode != KernelMode) || 396c2c66affSColin Finck (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) && 397c2c66affSColin Finck (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) && 398c2c66affSColin Finck !(OpenPacket->Override)) 399c2c66affSColin Finck { 400c2c66affSColin Finck KeEnterCriticalRegion(); 401c2c66affSColin Finck ExAcquireResourceSharedLite(&IopSecurityResource, TRUE); 402c2c66affSColin Finck 403c2c66affSColin Finck /* Check if a device object is being parsed */ 404c2c66affSColin Finck if (!RemainingName->Length) 405c2c66affSColin Finck { 406c2c66affSColin Finck /* Lock the subject context */ 407c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 408c2c66affSColin Finck LockHeld = TRUE; 409c2c66affSColin Finck 410c2c66affSColin Finck /* Do access check */ 411c2c66affSColin Finck AccessGranted = SeAccessCheck(OriginalDeviceObject-> 412c2c66affSColin Finck SecurityDescriptor, 413c2c66affSColin Finck &AccessState->SubjectSecurityContext, 414c2c66affSColin Finck LockHeld, 415c2c66affSColin Finck DesiredAccess, 416c2c66affSColin Finck 0, 417c2c66affSColin Finck &Privileges, 418c2c66affSColin Finck &IoFileObjectType-> 419c2c66affSColin Finck TypeInfo.GenericMapping, 420c2c66affSColin Finck UserMode, 421c2c66affSColin Finck &GrantedAccess, 422c2c66affSColin Finck &Status); 423c2c66affSColin Finck if (Privileges) 424c2c66affSColin Finck { 425c2c66affSColin Finck /* Append and free the privileges */ 426c2c66affSColin Finck SeAppendPrivileges(AccessState, Privileges); 427c2c66affSColin Finck SeFreePrivileges(Privileges); 428c2c66affSColin Finck } 429c2c66affSColin Finck 430c2c66affSColin Finck /* Check if we got access */ 431c2c66affSColin Finck if (AccessGranted) 432c2c66affSColin Finck { 433c2c66affSColin Finck /* Update access state */ 434c2c66affSColin Finck AccessState->PreviouslyGrantedAccess |= GrantedAccess; 435890a2936SPierre Schweitzer AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 436c2c66affSColin Finck MAXIMUM_ALLOWED); 437c2c66affSColin Finck OpenPacket->Override= TRUE; 438c2c66affSColin Finck } 439c2c66affSColin Finck 440c2c66affSColin Finck FileString.Length = 8; 441c2c66affSColin Finck FileString.MaximumLength = 8; 442c2c66affSColin Finck FileString.Buffer = L"File"; 443c2c66affSColin Finck 444c2c66affSColin Finck /* Do Audit/Alarm for open operation */ 445c2c66affSColin Finck SeOpenObjectAuditAlarm(&FileString, 446c2c66affSColin Finck OriginalDeviceObject, 447c2c66affSColin Finck CompleteName, 448c2c66affSColin Finck OriginalDeviceObject->SecurityDescriptor, 449c2c66affSColin Finck AccessState, 450c2c66affSColin Finck FALSE, 451c2c66affSColin Finck AccessGranted, 452c2c66affSColin Finck UserMode, 453c2c66affSColin Finck &AccessState->GenerateOnClose); 454c2c66affSColin Finck } 455c2c66affSColin Finck else 456c2c66affSColin Finck { 457c2c66affSColin Finck /* Check if we need to do traverse validation */ 458c2c66affSColin Finck if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) || 459c2c66affSColin Finck ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) || 460c2c66affSColin Finck (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM))) 461c2c66affSColin Finck { 462c2c66affSColin Finck /* Check if this is a restricted token */ 463c2c66affSColin Finck if (!(AccessState->Flags & TOKEN_IS_RESTRICTED)) 464c2c66affSColin Finck { 465c2c66affSColin Finck /* Do the FAST traverse check */ 466c2c66affSColin Finck AccessGranted = SeFastTraverseCheck(OriginalDeviceObject->SecurityDescriptor, 467c2c66affSColin Finck AccessState, 468c2c66affSColin Finck FILE_TRAVERSE, 469c2c66affSColin Finck UserMode); 470c2c66affSColin Finck } 471c2c66affSColin Finck else 472c2c66affSColin Finck { 473c2c66affSColin Finck /* Fail */ 474c2c66affSColin Finck AccessGranted = FALSE; 475c2c66affSColin Finck } 476c2c66affSColin Finck 477c2c66affSColin Finck /* Check if we failed to get access */ 478c2c66affSColin Finck if (!AccessGranted) 479c2c66affSColin Finck { 480c2c66affSColin Finck /* Lock the subject context */ 481c2c66affSColin Finck SeLockSubjectContext(&AccessState->SubjectSecurityContext); 482c2c66affSColin Finck LockHeld = TRUE; 483c2c66affSColin Finck 484c2c66affSColin Finck /* Do access check */ 485c2c66affSColin Finck AccessGranted = SeAccessCheck(OriginalDeviceObject-> 486c2c66affSColin Finck SecurityDescriptor, 487c2c66affSColin Finck &AccessState->SubjectSecurityContext, 488c2c66affSColin Finck LockHeld, 489c2c66affSColin Finck FILE_TRAVERSE, 490c2c66affSColin Finck 0, 491c2c66affSColin Finck &Privileges, 492c2c66affSColin Finck &IoFileObjectType-> 493c2c66affSColin Finck TypeInfo.GenericMapping, 494c2c66affSColin Finck UserMode, 495c2c66affSColin Finck &GrantedAccess, 496c2c66affSColin Finck &Status); 497c2c66affSColin Finck if (Privileges) 498c2c66affSColin Finck { 499c2c66affSColin Finck /* Append and free the privileges */ 500c2c66affSColin Finck SeAppendPrivileges(AccessState, Privileges); 501c2c66affSColin Finck SeFreePrivileges(Privileges); 502c2c66affSColin Finck } 503c2c66affSColin Finck } 504c2c66affSColin Finck 505c2c66affSColin Finck /* FIXME: Do Audit/Alarm for traverse check */ 506c2c66affSColin Finck } 507c2c66affSColin Finck else 508c2c66affSColin Finck { 509c2c66affSColin Finck /* Access automatically granted */ 510c2c66affSColin Finck AccessGranted = TRUE; 511c2c66affSColin Finck } 512c2c66affSColin Finck } 513c2c66affSColin Finck 514c2c66affSColin Finck ExReleaseResourceLite(&IopSecurityResource); 515c2c66affSColin Finck KeLeaveCriticalRegion(); 516c2c66affSColin Finck 517c2c66affSColin Finck /* Check if we hold the lock */ 518c2c66affSColin Finck if (LockHeld) 519c2c66affSColin Finck { 520c2c66affSColin Finck /* Release it */ 521c2c66affSColin Finck SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 522c2c66affSColin Finck } 523c2c66affSColin Finck 524c2c66affSColin Finck /* Check if access failed */ 525c2c66affSColin Finck if (!AccessGranted) 526c2c66affSColin Finck { 527c2c66affSColin Finck /* Dereference the device and fail */ 528c2c66affSColin Finck DPRINT1("Traverse access failed!\n"); 529c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 530c2c66affSColin Finck return STATUS_ACCESS_DENIED; 531c2c66affSColin Finck } 532c2c66affSColin Finck } 533c2c66affSColin Finck 534c2c66affSColin Finck /* Check if we can simply use a dummy file */ 535c2c66affSColin Finck UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly)); 536c2c66affSColin Finck 537fc5a61d8SPierre Schweitzer #if 1 538c2c66affSColin Finck /* FIXME: Small hack still exists, have to check why... 539c2c66affSColin Finck * This is triggered multiple times by usetup and then once per boot. 540c2c66affSColin Finck */ 541c2c66affSColin Finck if (ExpInTextModeSetup && 542c2c66affSColin Finck !(DirectOpen) && 543c2c66affSColin Finck !(RemainingName->Length) && 544c2c66affSColin Finck !(OpenPacket->RelatedFileObject) && 545c2c66affSColin Finck ((wcsstr(CompleteName->Buffer, L"Harddisk")) || 546c2c66affSColin Finck (wcsstr(CompleteName->Buffer, L"Floppy"))) && 547c2c66affSColin Finck !(UseDummyFile)) 548c2c66affSColin Finck { 549c2c66affSColin Finck DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n", 550c2c66affSColin Finck DesiredAccess & ~(SYNCHRONIZE | 551c2c66affSColin Finck FILE_READ_ATTRIBUTES | 552c2c66affSColin Finck READ_CONTROL | 553c2c66affSColin Finck ACCESS_SYSTEM_SECURITY | 554c2c66affSColin Finck WRITE_OWNER | 555c2c66affSColin Finck WRITE_DAC)); 556c2c66affSColin Finck DirectOpen = TRUE; 557c2c66affSColin Finck } 558c2c66affSColin Finck #endif 559c2c66affSColin Finck 560c2c66affSColin Finck /* Check if this is a direct open */ 561c2c66affSColin Finck if (!(RemainingName->Length) && 562c2c66affSColin Finck !(OpenPacket->RelatedFileObject) && 563c2c66affSColin Finck ((DesiredAccess & ~(SYNCHRONIZE | 564c2c66affSColin Finck FILE_READ_ATTRIBUTES | 565c2c66affSColin Finck READ_CONTROL | 566c2c66affSColin Finck ACCESS_SYSTEM_SECURITY | 567c2c66affSColin Finck WRITE_OWNER | 568c2c66affSColin Finck WRITE_DAC)) == 0) && 569c2c66affSColin Finck !(UseDummyFile)) 570c2c66affSColin Finck { 571c2c66affSColin Finck /* Remember this for later */ 572c2c66affSColin Finck DirectOpen = TRUE; 573c2c66affSColin Finck } 574c2c66affSColin Finck 575c2c66affSColin Finck /* Check if we have a related FO that wasn't a direct open */ 576c2c66affSColin Finck if ((OpenPacket->RelatedFileObject) && 577c2c66affSColin Finck !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 578c2c66affSColin Finck { 579c2c66affSColin Finck /* The device object is the one we were given */ 580c2c66affSColin Finck DeviceObject = ParseObject; 581c2c66affSColin Finck 582c2c66affSColin Finck /* Check if the related FO had a VPB */ 583c2c66affSColin Finck if (OpenPacket->RelatedFileObject->Vpb) 584c2c66affSColin Finck { 585c2c66affSColin Finck /* Yes, remember it */ 586c2c66affSColin Finck Vpb = OpenPacket->RelatedFileObject->Vpb; 587c2c66affSColin Finck 588c2c66affSColin Finck /* Reference it */ 589c2c66affSColin Finck InterlockedIncrement((PLONG)&Vpb->ReferenceCount); 590c2c66affSColin Finck 591c2c66affSColin Finck /* Check if we were given a specific top level device to use */ 592c2c66affSColin Finck if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) 593c2c66affSColin Finck { 594c2c66affSColin Finck DeviceObject = Vpb->DeviceObject; 595c2c66affSColin Finck } 596c2c66affSColin Finck } 597c2c66affSColin Finck } 598c2c66affSColin Finck else 599c2c66affSColin Finck { 600c2c66affSColin Finck /* Check if it has a VPB */ 601c2c66affSColin Finck if ((OriginalDeviceObject->Vpb) && !(DirectOpen)) 602c2c66affSColin Finck { 603c2c66affSColin Finck /* Check if the VPB is mounted, and mount it */ 604c2c66affSColin Finck Vpb = IopCheckVpbMounted(OpenPacket, 605c2c66affSColin Finck OriginalDeviceObject, 606c2c66affSColin Finck RemainingName, 607c2c66affSColin Finck &Status); 608c2c66affSColin Finck if (!Vpb) return Status; 609c2c66affSColin Finck 610c2c66affSColin Finck /* Get the VPB's device object */ 611c2c66affSColin Finck DeviceObject = Vpb->DeviceObject; 612c2c66affSColin Finck } 613c2c66affSColin Finck else 614c2c66affSColin Finck { 615c2c66affSColin Finck /* The device object is the one we were given */ 616c2c66affSColin Finck DeviceObject = OriginalDeviceObject; 617c2c66affSColin Finck } 618c2c66affSColin Finck 619c2c66affSColin Finck /* If we weren't given a specific top level device, look for an attached device */ 620c2c66affSColin Finck if (!(OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) && 621c2c66affSColin Finck DeviceObject->AttachedDevice) 622c2c66affSColin Finck { 623c2c66affSColin Finck /* Get the attached device */ 624c2c66affSColin Finck DeviceObject = IoGetAttachedDevice(DeviceObject); 625c2c66affSColin Finck } 626c2c66affSColin Finck } 627c2c66affSColin Finck 628c2c66affSColin Finck if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) 629c2c66affSColin Finck { 630c2c66affSColin Finck // FIXME: Verify our device object is good to use 631c2c66affSColin Finck ASSERT(DirectOpen == FALSE); 632c2c66affSColin Finck } 633c2c66affSColin Finck 634c2c66affSColin Finck /* If we traversed a mount point, reset the information */ 635c2c66affSColin Finck if (OpenPacket->TraversedMountPoint) 636c2c66affSColin Finck { 637c2c66affSColin Finck OpenPacket->TraversedMountPoint = FALSE; 638c2c66affSColin Finck } 639c2c66affSColin Finck 640c2c66affSColin Finck /* Check if this is a secure FSD */ 641c2c66affSColin Finck if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) && 642c2c66affSColin Finck ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) && 643c2c66affSColin Finck (!VolumeOpen)) 644c2c66affSColin Finck { 6456d0c07c4SPierre Schweitzer Privileges = NULL; 6466d0c07c4SPierre Schweitzer GrantedAccess = 0; 6476d0c07c4SPierre Schweitzer 6486d0c07c4SPierre Schweitzer KeEnterCriticalRegion(); 6496d0c07c4SPierre Schweitzer ExAcquireResourceSharedLite(&IopSecurityResource, TRUE); 6506d0c07c4SPierre Schweitzer 6516d0c07c4SPierre Schweitzer /* Lock the subject context */ 6526d0c07c4SPierre Schweitzer SeLockSubjectContext(&AccessState->SubjectSecurityContext); 6536d0c07c4SPierre Schweitzer 6546d0c07c4SPierre Schweitzer /* Do access check */ 6556d0c07c4SPierre Schweitzer AccessGranted = SeAccessCheck(OriginalDeviceObject->SecurityDescriptor, 6566d0c07c4SPierre Schweitzer &AccessState->SubjectSecurityContext, 6576d0c07c4SPierre Schweitzer TRUE, 6586d0c07c4SPierre Schweitzer DesiredAccess, 6596d0c07c4SPierre Schweitzer 0, 6606d0c07c4SPierre Schweitzer &Privileges, 6616d0c07c4SPierre Schweitzer &IoFileObjectType->TypeInfo.GenericMapping, 6626d0c07c4SPierre Schweitzer UserMode, 6636d0c07c4SPierre Schweitzer &GrantedAccess, 6646d0c07c4SPierre Schweitzer &Status); 6656d0c07c4SPierre Schweitzer if (Privileges != NULL) 6666d0c07c4SPierre Schweitzer { 6676d0c07c4SPierre Schweitzer /* Append and free the privileges */ 6686d0c07c4SPierre Schweitzer SeAppendPrivileges(AccessState, Privileges); 6696d0c07c4SPierre Schweitzer SeFreePrivileges(Privileges); 6706d0c07c4SPierre Schweitzer } 6716d0c07c4SPierre Schweitzer 6726d0c07c4SPierre Schweitzer /* Check if we got access */ 6736d0c07c4SPierre Schweitzer if (GrantedAccess) 6746d0c07c4SPierre Schweitzer { 6756d0c07c4SPierre Schweitzer AccessState->PreviouslyGrantedAccess |= GrantedAccess; 6766d0c07c4SPierre Schweitzer AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); 6776d0c07c4SPierre Schweitzer } 6786d0c07c4SPierre Schweitzer 6796d0c07c4SPierre Schweitzer FileString.Length = 8; 6806d0c07c4SPierre Schweitzer FileString.MaximumLength = 8; 6816d0c07c4SPierre Schweitzer FileString.Buffer = L"File"; 6826d0c07c4SPierre Schweitzer 6836d0c07c4SPierre Schweitzer /* Do Audit/Alarm for open operation 6846d0c07c4SPierre Schweitzer * NOTA: we audit target device object 6856d0c07c4SPierre Schweitzer */ 6866d0c07c4SPierre Schweitzer SeOpenObjectAuditAlarm(&FileString, 6876d0c07c4SPierre Schweitzer DeviceObject, 6886d0c07c4SPierre Schweitzer CompleteName, 6896d0c07c4SPierre Schweitzer OriginalDeviceObject->SecurityDescriptor, 6906d0c07c4SPierre Schweitzer AccessState, 6916d0c07c4SPierre Schweitzer FALSE, 6926d0c07c4SPierre Schweitzer AccessGranted, 6936d0c07c4SPierre Schweitzer UserMode, 6946d0c07c4SPierre Schweitzer &AccessState->GenerateOnClose); 6956d0c07c4SPierre Schweitzer 6966d0c07c4SPierre Schweitzer SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 6976d0c07c4SPierre Schweitzer 6986d0c07c4SPierre Schweitzer ExReleaseResourceLite(&IopSecurityResource); 6996d0c07c4SPierre Schweitzer KeLeaveCriticalRegion(); 7006d0c07c4SPierre Schweitzer 7016d0c07c4SPierre Schweitzer /* Check if access failed */ 7026d0c07c4SPierre Schweitzer if (!AccessGranted) 7036d0c07c4SPierre Schweitzer { 7046d0c07c4SPierre Schweitzer /* Dereference the device and fail */ 7056d0c07c4SPierre Schweitzer IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 7066d0c07c4SPierre Schweitzer if (Vpb) IopDereferenceVpbAndFree(Vpb); 7076d0c07c4SPierre Schweitzer return STATUS_ACCESS_DENIED; 7086d0c07c4SPierre Schweitzer } 709c2c66affSColin Finck } 710c2c66affSColin Finck 711c2c66affSColin Finck /* Allocate the IRP */ 712c2c66affSColin Finck Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); 713c2c66affSColin Finck if (!Irp) 714c2c66affSColin Finck { 715c2c66affSColin Finck /* Dereference the device and VPB, then fail */ 716c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 717c2c66affSColin Finck if (Vpb) IopDereferenceVpbAndFree(Vpb); 718c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 719c2c66affSColin Finck } 720c2c66affSColin Finck 721c2c66affSColin Finck /* Now set the IRP data */ 722c2c66affSColin Finck Irp->RequestorMode = AccessMode; 723c2c66affSColin Finck Irp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API | IRP_DEFER_IO_COMPLETION; 724c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 725c2c66affSColin Finck Irp->UserIosb = &IoStatusBlock; 726c2c66affSColin Finck Irp->MdlAddress = NULL; 727c2c66affSColin Finck Irp->PendingReturned = FALSE; 728c2c66affSColin Finck Irp->UserEvent = NULL; 729c2c66affSColin Finck Irp->Cancel = FALSE; 730c2c66affSColin Finck Irp->CancelRoutine = NULL; 731c2c66affSColin Finck Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 732c2c66affSColin Finck 733c2c66affSColin Finck /* Setup the security context */ 734c2c66affSColin Finck SecurityContext.SecurityQos = SecurityQos; 735c2c66affSColin Finck SecurityContext.AccessState = AccessState; 736c2c66affSColin Finck SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess; 737c2c66affSColin Finck SecurityContext.FullCreateOptions = OpenPacket->CreateOptions; 738c2c66affSColin Finck 739c2c66affSColin Finck /* Get the I/O Stack location */ 740ca9fd861STimo Kreuzer StackLoc = IoGetNextIrpStackLocation(Irp); 741c2c66affSColin Finck StackLoc->Control = 0; 742c2c66affSColin Finck 743c2c66affSColin Finck /* Check what kind of file this is */ 744c2c66affSColin Finck switch (OpenPacket->CreateFileType) 745c2c66affSColin Finck { 746c2c66affSColin Finck /* Normal file */ 747c2c66affSColin Finck case CreateFileTypeNone: 748c2c66affSColin Finck 749c2c66affSColin Finck /* Set the major function and EA Length */ 750c2c66affSColin Finck StackLoc->MajorFunction = IRP_MJ_CREATE; 751c2c66affSColin Finck StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength; 752c2c66affSColin Finck 753c2c66affSColin Finck /* Set the flags */ 754c2c66affSColin Finck StackLoc->Flags = (UCHAR)OpenPacket->Options; 755c2c66affSColin Finck StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ? SL_CASE_SENSITIVE: 0; 756c2c66affSColin Finck break; 757c2c66affSColin Finck 758c2c66affSColin Finck /* Named pipe */ 759c2c66affSColin Finck case CreateFileTypeNamedPipe: 760c2c66affSColin Finck 761c2c66affSColin Finck /* Set the named pipe MJ and set the parameters */ 762c2c66affSColin Finck StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE; 763c2c66affSColin Finck StackLoc->Parameters.CreatePipe.Parameters = OpenPacket->ExtraCreateParameters; 764c2c66affSColin Finck break; 765c2c66affSColin Finck 766c2c66affSColin Finck /* Mailslot */ 767c2c66affSColin Finck case CreateFileTypeMailslot: 768c2c66affSColin Finck 769c2c66affSColin Finck /* Set the mailslot MJ and set the parameters */ 770c2c66affSColin Finck StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT; 771c2c66affSColin Finck StackLoc->Parameters.CreateMailslot.Parameters = OpenPacket->ExtraCreateParameters; 772c2c66affSColin Finck break; 773c2c66affSColin Finck } 774c2c66affSColin Finck 775c2c66affSColin Finck /* Set the common data */ 776c2c66affSColin Finck Irp->Overlay.AllocationSize = OpenPacket->AllocationSize; 777c2c66affSColin Finck Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer; 778c2c66affSColin Finck StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) | 779c2c66affSColin Finck (OpenPacket->CreateOptions & 780c2c66affSColin Finck 0xFFFFFF); 781c2c66affSColin Finck StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes; 782c2c66affSColin Finck StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess; 783c2c66affSColin Finck StackLoc->Parameters.Create.SecurityContext = &SecurityContext; 784c2c66affSColin Finck 785c2c66affSColin Finck /* Check if we really need to create an object */ 786c2c66affSColin Finck if (!UseDummyFile) 787c2c66affSColin Finck { 788c2c66affSColin Finck ULONG ObjectSize = sizeof(FILE_OBJECT); 789c2c66affSColin Finck 790c2c66affSColin Finck /* Tag on space for a file object extension */ 791c2c66affSColin Finck if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION) 792c2c66affSColin Finck ObjectSize += sizeof(FILE_OBJECT_EXTENSION); 793c2c66affSColin Finck 794c2c66affSColin Finck /* Create the actual file object */ 795c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 796c2c66affSColin Finck NULL, 797c2c66affSColin Finck Attributes, 798c2c66affSColin Finck NULL, 799c2c66affSColin Finck NULL); 800c2c66affSColin Finck Status = ObCreateObject(KernelMode, 801c2c66affSColin Finck IoFileObjectType, 802c2c66affSColin Finck &ObjectAttributes, 803c2c66affSColin Finck AccessMode, 804c2c66affSColin Finck NULL, 805c2c66affSColin Finck ObjectSize, 806c2c66affSColin Finck 0, 807c2c66affSColin Finck 0, 808c2c66affSColin Finck (PVOID*)&FileObject); 809c2c66affSColin Finck if (!NT_SUCCESS(Status)) 810c2c66affSColin Finck { 811c2c66affSColin Finck /* Create failed, free the IRP */ 812c2c66affSColin Finck IoFreeIrp(Irp); 813c2c66affSColin Finck 814c2c66affSColin Finck /* Dereference the device and VPB */ 815c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 816c2c66affSColin Finck if (Vpb) IopDereferenceVpbAndFree(Vpb); 817c2c66affSColin Finck 818c2c66affSColin Finck /* We failed, return status */ 819c2c66affSColin Finck OpenPacket->FinalStatus = Status; 820c2c66affSColin Finck return Status; 821c2c66affSColin Finck } 822c2c66affSColin Finck 823c2c66affSColin Finck /* Clear the file object */ 824c2c66affSColin Finck RtlZeroMemory(FileObject, sizeof(FILE_OBJECT)); 825c2c66affSColin Finck 826c2c66affSColin Finck /* Check if this is Synch I/O */ 827c2c66affSColin Finck if (OpenPacket->CreateOptions & 828c2c66affSColin Finck (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) 829c2c66affSColin Finck { 830c2c66affSColin Finck /* Set the synch flag */ 831c2c66affSColin Finck FileObject->Flags |= FO_SYNCHRONOUS_IO; 832c2c66affSColin Finck 833c2c66affSColin Finck /* Check if it's also alertable */ 834c2c66affSColin Finck if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) 835c2c66affSColin Finck { 836c2c66affSColin Finck /* It is, set the alertable flag */ 837c2c66affSColin Finck FileObject->Flags |= FO_ALERTABLE_IO; 838c2c66affSColin Finck } 839c2c66affSColin Finck } 840c2c66affSColin Finck 841c2c66affSColin Finck /* Check if this is synch I/O */ 842c2c66affSColin Finck if (FileObject->Flags & FO_SYNCHRONOUS_IO) 843c2c66affSColin Finck { 844c2c66affSColin Finck /* Initialize the event */ 845c2c66affSColin Finck KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE); 846c2c66affSColin Finck } 847c2c66affSColin Finck 848c2c66affSColin Finck /* Check if the caller requested no intermediate buffering */ 849c2c66affSColin Finck if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) 850c2c66affSColin Finck { 851c2c66affSColin Finck /* Set the correct flag for the FSD to read */ 852c2c66affSColin Finck FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING; 853c2c66affSColin Finck } 854c2c66affSColin Finck 855c2c66affSColin Finck /* Check if the caller requested write through support */ 856c2c66affSColin Finck if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH) 857c2c66affSColin Finck { 858c2c66affSColin Finck /* Set the correct flag for the FSD to read */ 859c2c66affSColin Finck FileObject->Flags |= FO_WRITE_THROUGH; 860c2c66affSColin Finck } 861c2c66affSColin Finck 862c2c66affSColin Finck /* Check if the caller says the file will be only read sequentially */ 863c2c66affSColin Finck if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY) 864c2c66affSColin Finck { 865c2c66affSColin Finck /* Set the correct flag for the FSD to read */ 866c2c66affSColin Finck FileObject->Flags |= FO_SEQUENTIAL_ONLY; 867c2c66affSColin Finck } 868c2c66affSColin Finck 869c2c66affSColin Finck /* Check if the caller believes the file will be only read randomly */ 870c2c66affSColin Finck if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS) 871c2c66affSColin Finck { 872c2c66affSColin Finck /* Set the correct flag for the FSD to read */ 873c2c66affSColin Finck FileObject->Flags |= FO_RANDOM_ACCESS; 874c2c66affSColin Finck } 875c2c66affSColin Finck 876c2c66affSColin Finck /* Check if we were asked to setup a file object extension */ 877c2c66affSColin Finck if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION) 878c2c66affSColin Finck { 879c2c66affSColin Finck PFILE_OBJECT_EXTENSION FileObjectExtension; 880c2c66affSColin Finck 881c2c66affSColin Finck /* Make sure the file object knows it has an extension */ 882c2c66affSColin Finck FileObject->Flags |= FO_FILE_OBJECT_HAS_EXTENSION; 883c2c66affSColin Finck 884c2c66affSColin Finck FileObjectExtension = (PFILE_OBJECT_EXTENSION)(FileObject + 1); 885c2c66affSColin Finck FileObject->FileObjectExtension = FileObjectExtension; 886c2c66affSColin Finck 887c2c66affSColin Finck /* Add the top level device which we'll send the request to */ 888c2c66affSColin Finck if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) 889c2c66affSColin Finck { 890c2c66affSColin Finck FileObjectExtension->TopDeviceObjectHint = DeviceObject; 891c2c66affSColin Finck } 892c2c66affSColin Finck } 893c2c66affSColin Finck } 894c2c66affSColin Finck else 895c2c66affSColin Finck { 896c2c66affSColin Finck /* Use the dummy object instead */ 897c2c66affSColin Finck LocalFileObject = OpenPacket->LocalFileObject; 898c2c66affSColin Finck RtlZeroMemory(LocalFileObject, sizeof(DUMMY_FILE_OBJECT)); 899c2c66affSColin Finck 900c2c66affSColin Finck /* Set it up */ 901c2c66affSColin Finck FileObject = (PFILE_OBJECT)&LocalFileObject->ObjectHeader.Body; 902c2c66affSColin Finck LocalFileObject->ObjectHeader.Type = IoFileObjectType; 903c2c66affSColin Finck LocalFileObject->ObjectHeader.PointerCount = 1; 904c2c66affSColin Finck } 905c2c66affSColin Finck 906c2c66affSColin Finck /* Setup the file header */ 907c2c66affSColin Finck FileObject->Type = IO_TYPE_FILE; 908c2c66affSColin Finck FileObject->Size = sizeof(FILE_OBJECT); 909c2c66affSColin Finck FileObject->RelatedFileObject = OpenPacket->RelatedFileObject; 910c2c66affSColin Finck FileObject->DeviceObject = OriginalDeviceObject; 911c2c66affSColin Finck 912c2c66affSColin Finck /* Check if this is a direct device open */ 913c2c66affSColin Finck if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN; 914c2c66affSColin Finck 915c2c66affSColin Finck /* Check if the caller wants case sensitivity */ 916c2c66affSColin Finck if (!(Attributes & OBJ_CASE_INSENSITIVE)) 917c2c66affSColin Finck { 918c2c66affSColin Finck /* Tell the driver about it */ 919c2c66affSColin Finck FileObject->Flags |= FO_OPENED_CASE_SENSITIVE; 920c2c66affSColin Finck } 921c2c66affSColin Finck 922c2c66affSColin Finck /* Now set the file object */ 923c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 924c2c66affSColin Finck StackLoc->FileObject = FileObject; 925c2c66affSColin Finck 926c2c66affSColin Finck /* Check if the file object has a name */ 927c2c66affSColin Finck if (RemainingName->Length) 928c2c66affSColin Finck { 929c2c66affSColin Finck /* Setup the unicode string */ 930c2c66affSColin Finck FileObject->FileName.MaximumLength = RemainingName->Length + 931c2c66affSColin Finck sizeof(WCHAR); 932c2c66affSColin Finck FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool, 933c2c66affSColin Finck FileObject-> 934c2c66affSColin Finck FileName. 935c2c66affSColin Finck MaximumLength, 936c2c66affSColin Finck TAG_IO_NAME); 937c2c66affSColin Finck if (!FileObject->FileName.Buffer) 938c2c66affSColin Finck { 939c2c66affSColin Finck /* Failed to allocate the name, free the IRP */ 940c2c66affSColin Finck IoFreeIrp(Irp); 941c2c66affSColin Finck 942c2c66affSColin Finck /* Dereference the device object and VPB */ 943c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 944c2c66affSColin Finck if (Vpb) IopDereferenceVpbAndFree(Vpb); 945c2c66affSColin Finck 946c2c66affSColin Finck /* Clear the FO and dereference it */ 947c2c66affSColin Finck FileObject->DeviceObject = NULL; 948c2c66affSColin Finck if (!UseDummyFile) ObDereferenceObject(FileObject); 949c2c66affSColin Finck 950c2c66affSColin Finck /* Fail */ 951c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 952c2c66affSColin Finck } 953c2c66affSColin Finck } 954c2c66affSColin Finck 955c2c66affSColin Finck /* Copy the name */ 956c2c66affSColin Finck RtlCopyUnicodeString(&FileObject->FileName, RemainingName); 957c2c66affSColin Finck 958c2c66affSColin Finck /* Initialize the File Object event and set the FO */ 959c2c66affSColin Finck KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE); 960c2c66affSColin Finck OpenPacket->FileObject = FileObject; 961c2c66affSColin Finck 962c2c66affSColin Finck /* Queue the IRP and call the driver */ 963c2c66affSColin Finck IopQueueIrpToThread(Irp); 964c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 965c2c66affSColin Finck if (Status == STATUS_PENDING) 966c2c66affSColin Finck { 967c2c66affSColin Finck /* Wait for the driver to complete the create */ 968c2c66affSColin Finck KeWaitForSingleObject(&FileObject->Event, 969c2c66affSColin Finck Executive, 970c2c66affSColin Finck KernelMode, 971c2c66affSColin Finck FALSE, 972c2c66affSColin Finck NULL); 973c2c66affSColin Finck 974c2c66affSColin Finck /* Get the new status */ 975c2c66affSColin Finck Status = IoStatusBlock.Status; 976c2c66affSColin Finck } 977c2c66affSColin Finck else 978c2c66affSColin Finck { 979c2c66affSColin Finck /* We'll have to complete it ourselves */ 980c2c66affSColin Finck ASSERT(!Irp->PendingReturned); 981c2c66affSColin Finck ASSERT(!Irp->MdlAddress); 982c2c66affSColin Finck 983c2c66affSColin Finck /* Handle name change if required */ 984c2c66affSColin Finck if (Status == STATUS_REPARSE) 985c2c66affSColin Finck { 986c2c66affSColin Finck /* Check this is a mount point */ 987c2c66affSColin Finck if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) 988c2c66affSColin Finck { 989c2c66affSColin Finck PREPARSE_DATA_BUFFER ReparseData; 990c2c66affSColin Finck 991c2c66affSColin Finck /* Reparse point attributes were passed by the driver in the auxiliary buffer */ 992c2c66affSColin Finck ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL); 993c2c66affSColin Finck ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; 994c2c66affSColin Finck 995c2c66affSColin Finck ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT); 996c2c66affSColin Finck ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE); 997c2c66affSColin Finck ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE); 998c2c66affSColin Finck 999c2c66affSColin Finck IopDoNameTransmogrify(Irp, FileObject, ReparseData); 1000c2c66affSColin Finck } 1001c2c66affSColin Finck } 1002c2c66affSColin Finck 1003c2c66affSColin Finck /* Completion happens at APC_LEVEL */ 1004c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 1005c2c66affSColin Finck 1006c2c66affSColin Finck /* Get the new I/O Status block ourselves */ 1007c2c66affSColin Finck IoStatusBlock = Irp->IoStatus; 1008c2c66affSColin Finck Status = IoStatusBlock.Status; 1009c2c66affSColin Finck 1010c2c66affSColin Finck /* Manually signal the even, we can't have any waiters */ 1011c2c66affSColin Finck FileObject->Event.Header.SignalState = 1; 1012c2c66affSColin Finck 1013c2c66affSColin Finck /* Now that we've signaled the events, de-associate the IRP */ 1014c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 1015c2c66affSColin Finck 1016c2c66affSColin Finck /* Check if the IRP had an input buffer */ 1017c2c66affSColin Finck if ((Irp->Flags & IRP_BUFFERED_IO) && 1018c2c66affSColin Finck (Irp->Flags & IRP_DEALLOCATE_BUFFER)) 1019c2c66affSColin Finck { 1020c2c66affSColin Finck /* Free it. A driver might've tacked one on */ 1021c2c66affSColin Finck ExFreePool(Irp->AssociatedIrp.SystemBuffer); 1022c2c66affSColin Finck } 1023c2c66affSColin Finck 1024c2c66affSColin Finck /* Free the IRP and bring the IRQL back down */ 1025c2c66affSColin Finck IoFreeIrp(Irp); 1026c2c66affSColin Finck KeLowerIrql(OldIrql); 1027c2c66affSColin Finck } 1028c2c66affSColin Finck 1029c2c66affSColin Finck /* Copy the I/O Status */ 1030c2c66affSColin Finck OpenPacket->Information = IoStatusBlock.Information; 1031c2c66affSColin Finck 1032c2c66affSColin Finck /* The driver failed to create the file */ 1033c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1034c2c66affSColin Finck { 1035c2c66affSColin Finck /* Check if we have a name */ 1036c2c66affSColin Finck if (FileObject->FileName.Length) 1037c2c66affSColin Finck { 1038c2c66affSColin Finck /* Free it */ 1039c2c66affSColin Finck ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME); 1040c2c66affSColin Finck FileObject->FileName.Length = 0; 1041c2c66affSColin Finck } 1042c2c66affSColin Finck 1043c2c66affSColin Finck /* Clear its device object */ 1044c2c66affSColin Finck FileObject->DeviceObject = NULL; 1045c2c66affSColin Finck 1046c2c66affSColin Finck /* Save this now because the FO might go away */ 1047c2c66affSColin Finck OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ? 1048c2c66affSColin Finck TRUE : FALSE; 1049c2c66affSColin Finck 1050c2c66affSColin Finck /* Clear the file object in the open packet */ 1051c2c66affSColin Finck OpenPacket->FileObject = NULL; 1052c2c66affSColin Finck 1053c2c66affSColin Finck /* Dereference the file object */ 1054c2c66affSColin Finck if (!UseDummyFile) ObDereferenceObject(FileObject); 1055c2c66affSColin Finck 1056c2c66affSColin Finck /* Dereference the device object */ 1057c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 1058c2c66affSColin Finck 1059c2c66affSColin Finck /* Unless the driver cancelled the open, dereference the VPB */ 1060c2c66affSColin Finck if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb); 1061c2c66affSColin Finck 1062c2c66affSColin Finck /* Set the status and return */ 1063c2c66affSColin Finck OpenPacket->FinalStatus = Status; 1064c2c66affSColin Finck return Status; 1065c2c66affSColin Finck } 1066c2c66affSColin Finck else if (Status == STATUS_REPARSE) 1067c2c66affSColin Finck { 1068c2c66affSColin Finck if (OpenPacket->Information == IO_REPARSE || 1069c2c66affSColin Finck OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT) 1070c2c66affSColin Finck { 1071c2c66affSColin Finck /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */ 1072c2c66affSColin Finck if (CompleteName->MaximumLength < FileObject->FileName.Length) 1073c2c66affSColin Finck { 1074c2c66affSColin Finck PWSTR NewCompleteName; 1075c2c66affSColin Finck 1076c2c66affSColin Finck /* Allocate a new buffer for the string */ 1077c2c66affSColin Finck NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME); 1078c2c66affSColin Finck if (NewCompleteName == NULL) 1079c2c66affSColin Finck { 1080c2c66affSColin Finck OpenPacket->FinalStatus = STATUS_INSUFFICIENT_RESOURCES; 1081c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1082c2c66affSColin Finck } 1083c2c66affSColin Finck 1084c2c66affSColin Finck /* Release the old one */ 1085c2c66affSColin Finck if (CompleteName->Buffer != NULL) 1086c2c66affSColin Finck { 1087c2c66affSColin Finck ExFreePoolWithTag(CompleteName->Buffer, 0); 1088c2c66affSColin Finck } 1089c2c66affSColin Finck 1090c2c66affSColin Finck /* And setup the new one */ 1091c2c66affSColin Finck CompleteName->Buffer = NewCompleteName; 1092c2c66affSColin Finck CompleteName->MaximumLength = FileObject->FileName.Length; 1093c2c66affSColin Finck } 1094c2c66affSColin Finck 1095c2c66affSColin Finck /* Copy our new complete name */ 1096c2c66affSColin Finck RtlCopyUnicodeString(CompleteName, &FileObject->FileName); 1097c2c66affSColin Finck 1098c2c66affSColin Finck if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT) 1099c2c66affSColin Finck { 1100c2c66affSColin Finck OpenPacket->RelatedFileObject = NULL; 1101c2c66affSColin Finck } 1102c2c66affSColin Finck } 1103c2c66affSColin Finck 1104c2c66affSColin Finck /* Check if we have a name */ 1105c2c66affSColin Finck if (FileObject->FileName.Length) 1106c2c66affSColin Finck { 1107c2c66affSColin Finck /* Free it */ 1108c2c66affSColin Finck ExFreePoolWithTag(FileObject->FileName.Buffer, 0); 1109c2c66affSColin Finck FileObject->FileName.Length = 0; 1110c2c66affSColin Finck } 1111c2c66affSColin Finck 1112c2c66affSColin Finck /* Clear its device object */ 1113c2c66affSColin Finck FileObject->DeviceObject = NULL; 1114c2c66affSColin Finck 1115c2c66affSColin Finck /* Clear the file object in the open packet */ 1116c2c66affSColin Finck OpenPacket->FileObject = NULL; 1117c2c66affSColin Finck 1118c2c66affSColin Finck /* Dereference the file object */ 1119c2c66affSColin Finck if (!UseDummyFile) ObDereferenceObject(FileObject); 1120c2c66affSColin Finck 1121c2c66affSColin Finck /* Dereference the device object */ 1122c2c66affSColin Finck IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 1123c2c66affSColin Finck 1124c2c66affSColin Finck /* Unless the driver cancelled the open, dereference the VPB */ 1125c2c66affSColin Finck if (Vpb != NULL) IopDereferenceVpbAndFree(Vpb); 1126c2c66affSColin Finck 1127c2c66affSColin Finck if (OpenPacket->Information != IO_REMOUNT) 1128c2c66affSColin Finck { 1129c2c66affSColin Finck OpenPacket->RelatedFileObject = NULL; 1130c2c66affSColin Finck 1131c2c66affSColin Finck /* Inform we traversed a mount point for later attempt */ 1132c2c66affSColin Finck if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT) 1133c2c66affSColin Finck { 1134c2c66affSColin Finck OpenPacket->TraversedMountPoint = 1; 1135c2c66affSColin Finck } 1136c2c66affSColin Finck 1137c2c66affSColin Finck /* In case we override checks, but got this on volume open, fail hard */ 1138c2c66affSColin Finck if (OpenPacket->Override) 1139c2c66affSColin Finck { 1140c2c66affSColin Finck KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN, 1141c2c66affSColin Finck (ULONG_PTR)OriginalDeviceObject, 1142c2c66affSColin Finck (ULONG_PTR)DeviceObject, 1143c2c66affSColin Finck (ULONG_PTR)CompleteName, 1144c2c66affSColin Finck OpenPacket->Information); 1145c2c66affSColin Finck } 1146c2c66affSColin Finck 1147c2c66affSColin Finck /* Return to IO/OB so that information can be upgraded */ 1148c2c66affSColin Finck return STATUS_REPARSE; 1149c2c66affSColin Finck } 1150c2c66affSColin Finck 1151c2c66affSColin Finck /* Loop again and reattempt an opening */ 1152c2c66affSColin Finck continue; 1153c2c66affSColin Finck } 1154c2c66affSColin Finck 1155c2c66affSColin Finck break; 1156c2c66affSColin Finck } 1157c2c66affSColin Finck 1158c2c66affSColin Finck if (Attempt == IOP_MAX_REPARSE_TRAVERSAL) 1159c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 1160c2c66affSColin Finck 1161c2c66affSColin Finck /* Get the owner of the File Object */ 1162c2c66affSColin Finck OwnerDevice = IoGetRelatedDeviceObject(FileObject); 1163c2c66affSColin Finck 1164c2c66affSColin Finck /* 1165c2c66affSColin Finck * It's possible that the device to whom we sent the IRP to 1166c2c66affSColin Finck * isn't actually the device that ended opening the file object 1167c2c66affSColin Finck * internally. 1168c2c66affSColin Finck */ 1169c2c66affSColin Finck if (OwnerDevice != DeviceObject) 1170c2c66affSColin Finck { 1171c2c66affSColin Finck /* We have to de-reference the VPB we had associated */ 1172c2c66affSColin Finck if (Vpb) IopDereferenceVpbAndFree(Vpb); 1173c2c66affSColin Finck 1174c2c66affSColin Finck /* And re-associate with the actual one */ 1175c2c66affSColin Finck Vpb = FileObject->Vpb; 1176c2c66affSColin Finck if (Vpb) InterlockedIncrement((PLONG)&Vpb->ReferenceCount); 1177c2c66affSColin Finck } 1178c2c66affSColin Finck 1179c2c66affSColin Finck /* Make sure we are not using a dummy */ 1180c2c66affSColin Finck if (!UseDummyFile) 1181c2c66affSColin Finck { 1182c2c66affSColin Finck /* Check if this was a volume open */ 1183c2c66affSColin Finck if ((!(FileObject->RelatedFileObject) || 1184c2c66affSColin Finck (FileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN)) && 1185c2c66affSColin Finck !(FileObject->FileName.Length)) 1186c2c66affSColin Finck { 1187c2c66affSColin Finck /* All signs point to it, but make sure it was actually an FSD */ 1188c2c66affSColin Finck if ((OwnerDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) || 1189c2c66affSColin Finck (OwnerDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || 1190c2c66affSColin Finck (OwnerDevice->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) || 1191c2c66affSColin Finck (OwnerDevice->DeviceType == FILE_DEVICE_FILE_SYSTEM)) 1192c2c66affSColin Finck { 1193c2c66affSColin Finck /* The owner device is an FSD, so this is a volume open for real */ 1194c2c66affSColin Finck FileObject->Flags |= FO_VOLUME_OPEN; 1195c2c66affSColin Finck } 1196c2c66affSColin Finck } 1197c2c66affSColin Finck 1198c2c66affSColin Finck /* Reference the object and set the parse check */ 1199c2c66affSColin Finck ObReferenceObject(FileObject); 1200c2c66affSColin Finck *Object = FileObject; 1201c2c66affSColin Finck OpenPacket->FinalStatus = IoStatusBlock.Status; 1202c2c66affSColin Finck OpenPacket->ParseCheck = TRUE; 1203c2c66affSColin Finck return OpenPacket->FinalStatus; 1204c2c66affSColin Finck } 1205c2c66affSColin Finck else 1206c2c66affSColin Finck { 1207c2c66affSColin Finck /* Check if this was a query */ 1208c2c66affSColin Finck if (OpenPacket->QueryOnly) 1209c2c66affSColin Finck { 1210c2c66affSColin Finck /* Check if the caller wants basic info only */ 1211c2c66affSColin Finck if (!OpenPacket->FullAttributes) 1212c2c66affSColin Finck { 1213c2c66affSColin Finck /* Allocate the buffer */ 1214c2c66affSColin Finck FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool, 1215c2c66affSColin Finck sizeof(*FileBasicInfo), 1216c2c66affSColin Finck TAG_IO); 1217c2c66affSColin Finck if (FileBasicInfo) 1218c2c66affSColin Finck { 1219c2c66affSColin Finck /* Do the query */ 1220c2c66affSColin Finck Status = IoQueryFileInformation(FileObject, 1221c2c66affSColin Finck FileBasicInformation, 1222c2c66affSColin Finck sizeof(*FileBasicInfo), 1223c2c66affSColin Finck FileBasicInfo, 1224c2c66affSColin Finck &ReturnLength); 1225c2c66affSColin Finck if (NT_SUCCESS(Status)) 1226c2c66affSColin Finck { 1227c2c66affSColin Finck /* Copy the data */ 1228c2c66affSColin Finck RtlCopyMemory(OpenPacket->BasicInformation, 1229c2c66affSColin Finck FileBasicInfo, 1230c2c66affSColin Finck ReturnLength); 1231c2c66affSColin Finck } 1232c2c66affSColin Finck 1233c2c66affSColin Finck /* Free our buffer */ 1234c2c66affSColin Finck ExFreePoolWithTag(FileBasicInfo, TAG_IO); 1235c2c66affSColin Finck } 1236c2c66affSColin Finck else 1237c2c66affSColin Finck { 1238c2c66affSColin Finck /* Fail */ 1239c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 1240c2c66affSColin Finck } 1241c2c66affSColin Finck } 1242c2c66affSColin Finck else 1243c2c66affSColin Finck { 1244c2c66affSColin Finck /* This is a full query */ 1245c2c66affSColin Finck Status = IoQueryFileInformation( 1246c2c66affSColin Finck FileObject, 1247c2c66affSColin Finck FileNetworkOpenInformation, 1248c2c66affSColin Finck sizeof(FILE_NETWORK_OPEN_INFORMATION), 1249c2c66affSColin Finck OpenPacket->NetworkInformation, 1250c2c66affSColin Finck &ReturnLength); 1251c2c66affSColin Finck if (!NT_SUCCESS(Status)) ASSERT(Status != STATUS_NOT_IMPLEMENTED); 1252c2c66affSColin Finck } 1253c2c66affSColin Finck } 1254c2c66affSColin Finck 1255c2c66affSColin Finck /* Delete the file object */ 1256c2c66affSColin Finck IopDeleteFile(FileObject); 1257c2c66affSColin Finck 1258c2c66affSColin Finck /* Clear out the file */ 1259c2c66affSColin Finck OpenPacket->FileObject = NULL; 1260c2c66affSColin Finck 1261c2c66affSColin Finck /* Set and return status */ 1262c2c66affSColin Finck OpenPacket->FinalStatus = Status; 1263c2c66affSColin Finck OpenPacket->ParseCheck = TRUE; 1264c2c66affSColin Finck return Status; 1265c2c66affSColin Finck } 1266c2c66affSColin Finck } 1267c2c66affSColin Finck 1268c2c66affSColin Finck NTSTATUS 1269c2c66affSColin Finck NTAPI 1270c2c66affSColin Finck IopParseFile(IN PVOID ParseObject, 1271c2c66affSColin Finck IN PVOID ObjectType, 1272c2c66affSColin Finck IN OUT PACCESS_STATE AccessState, 1273c2c66affSColin Finck IN KPROCESSOR_MODE AccessMode, 1274c2c66affSColin Finck IN ULONG Attributes, 1275c2c66affSColin Finck IN OUT PUNICODE_STRING CompleteName, 1276c2c66affSColin Finck IN OUT PUNICODE_STRING RemainingName, 1277c2c66affSColin Finck IN OUT PVOID Context OPTIONAL, 1278c2c66affSColin Finck IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, 1279c2c66affSColin Finck OUT PVOID *Object) 1280c2c66affSColin Finck { 1281c2c66affSColin Finck PVOID DeviceObject; 1282c2c66affSColin Finck POPEN_PACKET OpenPacket = (POPEN_PACKET)Context; 1283c2c66affSColin Finck 1284c2c66affSColin Finck /* Validate the open packet */ 1285c2c66affSColin Finck if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH; 1286c2c66affSColin Finck 1287c2c66affSColin Finck /* Get the device object */ 1288c2c66affSColin Finck DeviceObject = IoGetRelatedDeviceObject(ParseObject); 1289c2c66affSColin Finck OpenPacket->RelatedFileObject = ParseObject; 1290c2c66affSColin Finck 1291c2c66affSColin Finck /* Call the main routine */ 1292c2c66affSColin Finck return IopParseDevice(DeviceObject, 1293c2c66affSColin Finck ObjectType, 1294c2c66affSColin Finck AccessState, 1295c2c66affSColin Finck AccessMode, 1296c2c66affSColin Finck Attributes, 1297c2c66affSColin Finck CompleteName, 1298c2c66affSColin Finck RemainingName, 1299c2c66affSColin Finck OpenPacket, 1300c2c66affSColin Finck SecurityQos, 1301c2c66affSColin Finck Object); 1302c2c66affSColin Finck } 1303c2c66affSColin Finck 1304c2c66affSColin Finck VOID 1305c2c66affSColin Finck NTAPI 1306c2c66affSColin Finck IopDeleteFile(IN PVOID ObjectBody) 1307c2c66affSColin Finck { 1308c2c66affSColin Finck PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 1309c2c66affSColin Finck PIRP Irp; 1310c2c66affSColin Finck PIO_STACK_LOCATION StackPtr; 1311c2c66affSColin Finck NTSTATUS Status; 1312c2c66affSColin Finck KEVENT Event; 1313c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 1314c2c66affSColin Finck BOOLEAN DereferenceDone = FALSE; 1315c2c66affSColin Finck PVPB Vpb; 1316c2c66affSColin Finck KIRQL OldIrql; 1317c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 1318c2c66affSColin Finck 1319c2c66affSColin Finck /* Check if the file has a device object */ 1320c2c66affSColin Finck if (FileObject->DeviceObject) 1321c2c66affSColin Finck { 1322c2c66affSColin Finck /* Check if this is a direct open or not */ 1323c2c66affSColin Finck if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 1324c2c66affSColin Finck { 1325c2c66affSColin Finck /* Get the attached device */ 1326c2c66affSColin Finck DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 1327c2c66affSColin Finck } 1328c2c66affSColin Finck else 1329c2c66affSColin Finck { 1330c2c66affSColin Finck /* Use the file object's device object */ 1331c2c66affSColin Finck DeviceObject = IoGetRelatedDeviceObject(FileObject); 1332c2c66affSColin Finck } 1333c2c66affSColin Finck 1334c2c66affSColin Finck /* Sanity check */ 1335c2c66affSColin Finck ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) || 1336c2c66affSColin Finck (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE)); 1337c2c66affSColin Finck 1338c2c66affSColin Finck /* Check if the handle wasn't created yet */ 1339c2c66affSColin Finck if (!(FileObject->Flags & FO_HANDLE_CREATED)) 1340c2c66affSColin Finck { 1341c2c66affSColin Finck /* Send the cleanup IRP */ 1342c2c66affSColin Finck IopCloseFile(NULL, ObjectBody, 0, 1, 1); 1343c2c66affSColin Finck } 1344c2c66affSColin Finck 1345c2c66affSColin Finck /* Clear and set up Events */ 1346c2c66affSColin Finck KeClearEvent(&FileObject->Event); 1347c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 1348c2c66affSColin Finck 1349c2c66affSColin Finck /* Allocate an IRP */ 1350c2c66affSColin Finck Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 1351c2c66affSColin Finck 1352c2c66affSColin Finck /* Set it up */ 1353c2c66affSColin Finck Irp->UserEvent = &Event; 1354c2c66affSColin Finck Irp->UserIosb = &Irp->IoStatus; 1355c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 1356c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 1357c2c66affSColin Finck Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 1358c2c66affSColin Finck 1359c2c66affSColin Finck /* Set up Stack Pointer Data */ 1360c2c66affSColin Finck StackPtr = IoGetNextIrpStackLocation(Irp); 1361c2c66affSColin Finck StackPtr->MajorFunction = IRP_MJ_CLOSE; 1362c2c66affSColin Finck StackPtr->FileObject = FileObject; 1363c2c66affSColin Finck 1364c2c66affSColin Finck /* Queue the IRP */ 1365c2c66affSColin Finck IopQueueIrpToThread(Irp); 1366c2c66affSColin Finck 1367c2c66affSColin Finck /* Get the VPB and check if this isn't a direct open */ 1368c2c66affSColin Finck Vpb = FileObject->Vpb; 1369c2c66affSColin Finck if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 1370c2c66affSColin Finck { 1371c2c66affSColin Finck /* Dereference the VPB before the close */ 1372c2c66affSColin Finck InterlockedDecrement((PLONG)&Vpb->ReferenceCount); 1373c2c66affSColin Finck } 1374c2c66affSColin Finck 1375c2c66affSColin Finck /* Check if the FS will never disappear by itself */ 1376c2c66affSColin Finck if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE) 1377c2c66affSColin Finck { 1378c2c66affSColin Finck /* Dereference it */ 1379c2c66affSColin Finck InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount); 1380c2c66affSColin Finck DereferenceDone = TRUE; 1381c2c66affSColin Finck } 1382c2c66affSColin Finck 1383c2c66affSColin Finck /* Call the FS Driver */ 1384c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1385c2c66affSColin Finck if (Status == STATUS_PENDING) 1386c2c66affSColin Finck { 1387c2c66affSColin Finck /* Wait for completion */ 1388c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1389c2c66affSColin Finck } 1390c2c66affSColin Finck 1391c2c66affSColin Finck /* De-queue the IRP */ 1392c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 1393c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 1394c2c66affSColin Finck KeLowerIrql(OldIrql); 1395c2c66affSColin Finck 1396c2c66affSColin Finck /* Free the IRP */ 1397c2c66affSColin Finck IoFreeIrp(Irp); 1398c2c66affSColin Finck 1399c2c66affSColin Finck /* Clear the file name */ 1400c2c66affSColin Finck if (FileObject->FileName.Buffer) 1401c2c66affSColin Finck { 1402c2c66affSColin Finck ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME); 1403c2c66affSColin Finck FileObject->FileName.Buffer = NULL; 1404c2c66affSColin Finck } 1405c2c66affSColin Finck 1406c2c66affSColin Finck /* Check if the FO had a completion port */ 1407c2c66affSColin Finck if (FileObject->CompletionContext) 1408c2c66affSColin Finck { 1409c2c66affSColin Finck /* Free it */ 1410c2c66affSColin Finck ObDereferenceObject(FileObject->CompletionContext->Port); 1411c2c66affSColin Finck ExFreePool(FileObject->CompletionContext); 1412c2c66affSColin Finck } 1413c2c66affSColin Finck 1414c2c66affSColin Finck /* Check if the FO had extension */ 1415c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 1416c2c66affSColin Finck { 1417c2c66affSColin Finck /* Release filter context structure if any */ 1418c2c66affSColin Finck FsRtlPTeardownPerFileObjectContexts(FileObject); 1419c2c66affSColin Finck } 1420c2c66affSColin Finck 1421c2c66affSColin Finck /* Check if dereference has been done yet */ 1422c2c66affSColin Finck if (!DereferenceDone) 1423c2c66affSColin Finck { 1424c2c66affSColin Finck /* Dereference device object */ 1425c2c66affSColin Finck IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE); 1426c2c66affSColin Finck } 1427c2c66affSColin Finck } 1428c2c66affSColin Finck } 1429c2c66affSColin Finck 1430c2c66affSColin Finck PDEVICE_OBJECT 1431c2c66affSColin Finck NTAPI 1432c2c66affSColin Finck IopGetDeviceAttachmentBase(IN PDEVICE_OBJECT DeviceObject) 1433c2c66affSColin Finck { 1434c2c66affSColin Finck PDEVICE_OBJECT PDO = DeviceObject; 1435c2c66affSColin Finck 1436c2c66affSColin Finck /* Go down the stack to attempt to get the PDO */ 1437c2c66affSColin Finck for (; ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo != NULL; 1438c2c66affSColin Finck PDO = ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo); 1439c2c66affSColin Finck 1440c2c66affSColin Finck return PDO; 1441c2c66affSColin Finck } 1442c2c66affSColin Finck 1443c2c66affSColin Finck PDEVICE_OBJECT 1444c2c66affSColin Finck NTAPI 1445c2c66affSColin Finck IopGetDevicePDO(IN PDEVICE_OBJECT DeviceObject) 1446c2c66affSColin Finck { 1447c2c66affSColin Finck KIRQL OldIrql; 1448c2c66affSColin Finck PDEVICE_OBJECT PDO; 1449c2c66affSColin Finck 1450c2c66affSColin Finck ASSERT(DeviceObject != NULL); 1451c2c66affSColin Finck 1452c2c66affSColin Finck OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock); 1453c2c66affSColin Finck /* Get the base DO */ 1454c2c66affSColin Finck PDO = IopGetDeviceAttachmentBase(DeviceObject); 1455c2c66affSColin Finck /* Check whether that's really a PDO and if so, keep it */ 1456c2c66affSColin Finck if ((PDO->Flags & DO_BUS_ENUMERATED_DEVICE) != DO_BUS_ENUMERATED_DEVICE) 1457c2c66affSColin Finck { 1458c2c66affSColin Finck PDO = NULL; 1459c2c66affSColin Finck } 1460c2c66affSColin Finck else 1461c2c66affSColin Finck { 1462c2c66affSColin Finck ObReferenceObject(PDO); 1463c2c66affSColin Finck } 1464c2c66affSColin Finck KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql); 1465c2c66affSColin Finck 1466c2c66affSColin Finck return PDO; 1467c2c66affSColin Finck } 1468c2c66affSColin Finck 1469c2c66affSColin Finck NTSTATUS 1470c2c66affSColin Finck NTAPI 1471c2c66affSColin Finck IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject, 1472c2c66affSColin Finck IN PSECURITY_INFORMATION SecurityInformation, 1473c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor, 1474c2c66affSColin Finck IN POOL_TYPE PoolType, 1475c2c66affSColin Finck IN PGENERIC_MAPPING GenericMapping) 1476c2c66affSColin Finck { 1477c2c66affSColin Finck NTSTATUS Status; 1478c2c66affSColin Finck PSECURITY_DESCRIPTOR OldSecurityDescriptor, CachedSecurityDescriptor, NewSecurityDescriptor; 1479c2c66affSColin Finck 1480c2c66affSColin Finck PAGED_CODE(); 1481c2c66affSColin Finck 1482c2c66affSColin Finck /* Keep attempting till we find our old SD or fail */ 1483c2c66affSColin Finck while (TRUE) 1484c2c66affSColin Finck { 1485c2c66affSColin Finck KeEnterCriticalRegion(); 1486c2c66affSColin Finck ExAcquireResourceSharedLite(&IopSecurityResource, TRUE); 1487c2c66affSColin Finck 1488c2c66affSColin Finck /* Get our old SD and reference it */ 1489c2c66affSColin Finck OldSecurityDescriptor = DeviceObject->SecurityDescriptor; 1490c2c66affSColin Finck if (OldSecurityDescriptor != NULL) 1491c2c66affSColin Finck { 1492c2c66affSColin Finck ObReferenceSecurityDescriptor(OldSecurityDescriptor, 1); 1493c2c66affSColin Finck } 1494c2c66affSColin Finck 1495c2c66affSColin Finck ExReleaseResourceLite(&IopSecurityResource); 1496c2c66affSColin Finck KeLeaveCriticalRegion(); 1497c2c66affSColin Finck 1498c2c66affSColin Finck /* Set the SD information */ 1499c2c66affSColin Finck NewSecurityDescriptor = OldSecurityDescriptor; 1500c2c66affSColin Finck Status = SeSetSecurityDescriptorInfo(NULL, SecurityInformation, 1501c2c66affSColin Finck SecurityDescriptor, &NewSecurityDescriptor, 1502c2c66affSColin Finck PoolType, GenericMapping); 1503c2c66affSColin Finck 1504c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1505c2c66affSColin Finck { 1506c2c66affSColin Finck if (OldSecurityDescriptor != NULL) 1507c2c66affSColin Finck { 1508c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); 1509c2c66affSColin Finck } 1510c2c66affSColin Finck 1511c2c66affSColin Finck break; 1512c2c66affSColin Finck } 1513c2c66affSColin Finck 1514c2c66affSColin Finck /* Add the new DS to the internal cache */ 1515c2c66affSColin Finck Status = ObLogSecurityDescriptor(NewSecurityDescriptor, 1516c2c66affSColin Finck &CachedSecurityDescriptor, 1); 1517c2c66affSColin Finck ExFreePool(NewSecurityDescriptor); 1518c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1519c2c66affSColin Finck { 1520c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); 1521c2c66affSColin Finck break; 1522c2c66affSColin Finck } 1523c2c66affSColin Finck 1524c2c66affSColin Finck KeEnterCriticalRegion(); 1525c2c66affSColin Finck ExAcquireResourceExclusiveLite(&IopSecurityResource, TRUE); 1526c2c66affSColin Finck /* Check if someone changed it in our back */ 1527c2c66affSColin Finck if (DeviceObject->SecurityDescriptor == OldSecurityDescriptor) 1528c2c66affSColin Finck { 1529c2c66affSColin Finck /* We're clear, do the swap */ 1530c2c66affSColin Finck DeviceObject->SecurityDescriptor = CachedSecurityDescriptor; 1531c2c66affSColin Finck ExReleaseResourceLite(&IopSecurityResource); 1532c2c66affSColin Finck KeLeaveCriticalRegion(); 1533c2c66affSColin Finck 1534c2c66affSColin Finck /* And dereference old SD (twice - us + not in use) */ 1535c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 2); 1536c2c66affSColin Finck 1537c2c66affSColin Finck break; 1538c2c66affSColin Finck } 1539c2c66affSColin Finck ExReleaseResourceLite(&IopSecurityResource); 1540c2c66affSColin Finck KeLeaveCriticalRegion(); 1541c2c66affSColin Finck 1542c2c66affSColin Finck /* If so, try again */ 1543c2c66affSColin Finck ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); 1544c2c66affSColin Finck ObDereferenceSecurityDescriptor(CachedSecurityDescriptor, 1); 1545c2c66affSColin Finck } 1546c2c66affSColin Finck 1547c2c66affSColin Finck return Status; 1548c2c66affSColin Finck } 1549c2c66affSColin Finck 1550c2c66affSColin Finck NTSTATUS 1551c2c66affSColin Finck NTAPI 1552c2c66affSColin Finck IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject, 1553c2c66affSColin Finck IN PDEVICE_OBJECT PhysicalDeviceObject, 1554c2c66affSColin Finck IN PSECURITY_INFORMATION SecurityInformation, 1555c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor, 1556c2c66affSColin Finck IN POOL_TYPE PoolType, 1557c2c66affSColin Finck IN PGENERIC_MAPPING GenericMapping) 1558c2c66affSColin Finck { 1559c2c66affSColin Finck PDEVICE_OBJECT CurrentDO = PhysicalDeviceObject, NextDevice; 1560c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS, TmpStatus; 1561c2c66affSColin Finck 1562c2c66affSColin Finck PAGED_CODE(); 1563c2c66affSColin Finck 1564c2c66affSColin Finck ASSERT(PhysicalDeviceObject != NULL); 1565c2c66affSColin Finck 1566c2c66affSColin Finck /* We always reference the DO we're working on */ 1567c2c66affSColin Finck ObReferenceObject(CurrentDO); 1568c2c66affSColin Finck 1569c2c66affSColin Finck /* Go up from PDO to latest DO */ 1570c2c66affSColin Finck do 1571c2c66affSColin Finck { 1572c2c66affSColin Finck /* Attempt to set the new SD on it */ 1573c2c66affSColin Finck TmpStatus = IopSetDeviceSecurityDescriptor(CurrentDO, SecurityInformation, 1574c2c66affSColin Finck SecurityDescriptor, PoolType, 1575c2c66affSColin Finck GenericMapping); 1576c2c66affSColin Finck /* Was our last one? Remember that status then */ 1577c2c66affSColin Finck if (CurrentDO == UpperDeviceObject) 1578c2c66affSColin Finck { 1579c2c66affSColin Finck Status = TmpStatus; 1580c2c66affSColin Finck } 1581c2c66affSColin Finck 1582c2c66affSColin Finck /* Try to move to the next DO (and thus, reference it) */ 1583c2c66affSColin Finck NextDevice = CurrentDO->AttachedDevice; 1584c2c66affSColin Finck if (NextDevice) 1585c2c66affSColin Finck { 1586c2c66affSColin Finck ObReferenceObject(NextDevice); 1587c2c66affSColin Finck } 1588c2c66affSColin Finck 1589c2c66affSColin Finck /* Dereference current DO and move to the next one */ 1590c2c66affSColin Finck ObDereferenceObject(CurrentDO); 1591c2c66affSColin Finck CurrentDO = NextDevice; 1592c2c66affSColin Finck } 1593c2c66affSColin Finck while (CurrentDO != NULL); 1594c2c66affSColin Finck 1595c2c66affSColin Finck return Status; 1596c2c66affSColin Finck } 1597c2c66affSColin Finck 1598c2c66affSColin Finck NTSTATUS 1599c2c66affSColin Finck NTAPI 1600c2c66affSColin Finck IopGetSetSecurityObject(IN PVOID ObjectBody, 1601c2c66affSColin Finck IN SECURITY_OPERATION_CODE OperationCode, 1602c2c66affSColin Finck IN PSECURITY_INFORMATION SecurityInformation, 1603c2c66affSColin Finck IN PSECURITY_DESCRIPTOR SecurityDescriptor, 1604c2c66affSColin Finck IN OUT PULONG BufferLength, 1605c2c66affSColin Finck IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor, 1606c2c66affSColin Finck IN POOL_TYPE PoolType, 1607c2c66affSColin Finck IN OUT PGENERIC_MAPPING GenericMapping) 1608c2c66affSColin Finck { 1609c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 1610c2c66affSColin Finck PIO_STACK_LOCATION StackPtr; 1611c2c66affSColin Finck PFILE_OBJECT FileObject; 1612c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 1613c2c66affSColin Finck PIRP Irp; 1614c2c66affSColin Finck BOOLEAN LocalEvent = FALSE; 1615c2c66affSColin Finck KEVENT Event; 1616c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 1617c2c66affSColin Finck PAGED_CODE(); 1618c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 1619c2c66affSColin Finck 1620c2c66affSColin Finck /* Check if this is a device or file */ 1621c2c66affSColin Finck if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE) 1622c2c66affSColin Finck { 1623c2c66affSColin Finck /* It's a device */ 1624c2c66affSColin Finck DeviceObject = (PDEVICE_OBJECT)ObjectBody; 1625c2c66affSColin Finck FileObject = NULL; 1626c2c66affSColin Finck } 1627c2c66affSColin Finck else 1628c2c66affSColin Finck { 1629c2c66affSColin Finck /* It's a file */ 1630c2c66affSColin Finck FileObject = (PFILE_OBJECT)ObjectBody; 1631c2c66affSColin Finck 1632c2c66affSColin Finck /* Check if this is a direct open */ 1633c2c66affSColin Finck if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 1634c2c66affSColin Finck { 1635c2c66affSColin Finck /* Get the Device Object */ 1636c2c66affSColin Finck DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 1637c2c66affSColin Finck } 1638c2c66affSColin Finck else 1639c2c66affSColin Finck { 1640c2c66affSColin Finck /* Otherwise, use the direct device*/ 1641c2c66affSColin Finck DeviceObject = FileObject->DeviceObject; 1642c2c66affSColin Finck } 1643c2c66affSColin Finck } 1644c2c66affSColin Finck 1645c2c66affSColin Finck /* Check if the request was for a device object */ 1646c2c66affSColin Finck if (!(FileObject) || 1647c2c66affSColin Finck (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) || 1648c2c66affSColin Finck (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 1649c2c66affSColin Finck { 1650c2c66affSColin Finck /* Check what kind of request this was */ 1651c2c66affSColin Finck if (OperationCode == QuerySecurityDescriptor) 1652c2c66affSColin Finck { 1653c2c66affSColin Finck return SeQuerySecurityDescriptorInfo(SecurityInformation, 1654c2c66affSColin Finck SecurityDescriptor, 1655c2c66affSColin Finck BufferLength, 1656c2c66affSColin Finck &DeviceObject->SecurityDescriptor); 1657c2c66affSColin Finck } 1658c2c66affSColin Finck else if (OperationCode == DeleteSecurityDescriptor) 1659c2c66affSColin Finck { 1660c2c66affSColin Finck /* Simply return success */ 1661c2c66affSColin Finck return STATUS_SUCCESS; 1662c2c66affSColin Finck } 1663c2c66affSColin Finck else if (OperationCode == AssignSecurityDescriptor) 1664c2c66affSColin Finck { 1665c2c66affSColin Finck Status = STATUS_SUCCESS; 1666c2c66affSColin Finck 1667c2c66affSColin Finck /* Make absolutely sure this is a device object */ 1668c2c66affSColin Finck if (!(FileObject) || !(FileObject->Flags & FO_STREAM_FILE)) 1669c2c66affSColin Finck { 1670c2c66affSColin Finck PSECURITY_DESCRIPTOR CachedSecurityDescriptor; 1671c2c66affSColin Finck 1672c2c66affSColin Finck /* Add the security descriptor in cache */ 1673c2c66affSColin Finck Status = ObLogSecurityDescriptor(SecurityDescriptor, &CachedSecurityDescriptor, 1); 1674c2c66affSColin Finck if (NT_SUCCESS(Status)) 1675c2c66affSColin Finck { 1676c2c66affSColin Finck KeEnterCriticalRegion(); 1677c2c66affSColin Finck ExAcquireResourceExclusiveLite(&IopSecurityResource, TRUE); 1678c2c66affSColin Finck 1679c2c66affSColin Finck /* Assign the Security Descriptor */ 1680c2c66affSColin Finck DeviceObject->SecurityDescriptor = CachedSecurityDescriptor; 1681c2c66affSColin Finck 1682c2c66affSColin Finck ExReleaseResourceLite(&IopSecurityResource); 1683c2c66affSColin Finck KeLeaveCriticalRegion(); 1684c2c66affSColin Finck } 1685c2c66affSColin Finck } 1686c2c66affSColin Finck 1687c2c66affSColin Finck /* Return status */ 1688c2c66affSColin Finck return Status; 1689c2c66affSColin Finck } 1690c2c66affSColin Finck else if (OperationCode == SetSecurityDescriptor) 1691c2c66affSColin Finck { 1692c2c66affSColin Finck /* Get the Physical Device Object if any */ 1693c2c66affSColin Finck PDEVICE_OBJECT PDO = IopGetDevicePDO(DeviceObject); 1694c2c66affSColin Finck 1695c2c66affSColin Finck if (PDO != NULL) 1696c2c66affSColin Finck { 1697c2c66affSColin Finck /* Apply the new SD to any DO in the path from PDO to current DO */ 1698c2c66affSColin Finck Status = IopSetDeviceSecurityDescriptors(DeviceObject, PDO, 1699c2c66affSColin Finck SecurityInformation, 1700c2c66affSColin Finck SecurityDescriptor, 1701c2c66affSColin Finck PoolType, GenericMapping); 1702c2c66affSColin Finck ObDereferenceObject(PDO); 1703c2c66affSColin Finck } 1704c2c66affSColin Finck else 1705c2c66affSColin Finck { 1706c2c66affSColin Finck /* Otherwise, just set for ourselves */ 1707c2c66affSColin Finck Status = IopSetDeviceSecurityDescriptor(DeviceObject, 1708c2c66affSColin Finck SecurityInformation, 1709c2c66affSColin Finck SecurityDescriptor, 1710c2c66affSColin Finck PoolType, GenericMapping); 1711c2c66affSColin Finck } 1712c2c66affSColin Finck 1713c2c66affSColin Finck return STATUS_SUCCESS; 1714c2c66affSColin Finck } 1715c2c66affSColin Finck 1716c2c66affSColin Finck /* Shouldn't happen */ 1717c2c66affSColin Finck return STATUS_SUCCESS; 1718c2c66affSColin Finck } 1719c2c66affSColin Finck else if (OperationCode == DeleteSecurityDescriptor) 1720c2c66affSColin Finck { 1721c2c66affSColin Finck /* Same as for devices, do nothing */ 1722c2c66affSColin Finck return STATUS_SUCCESS; 1723c2c66affSColin Finck } 1724c2c66affSColin Finck 1725c2c66affSColin Finck /* At this point, we know we're a file. Reference it */ 1726c2c66affSColin Finck ObReferenceObject(FileObject); 1727c2c66affSColin Finck 1728c2c66affSColin Finck /* Check if we should use Sync IO or not */ 1729c2c66affSColin Finck if (FileObject->Flags & FO_SYNCHRONOUS_IO) 1730c2c66affSColin Finck { 1731c2c66affSColin Finck /* Lock the file object */ 17328fbc4880SThomas Faber Status = IopLockFileObject(FileObject, ExGetPreviousMode()); 17338fbc4880SThomas Faber if (Status != STATUS_SUCCESS) 17348fbc4880SThomas Faber { 17358fbc4880SThomas Faber ObDereferenceObject(FileObject); 17368fbc4880SThomas Faber return Status; 17378fbc4880SThomas Faber } 1738c2c66affSColin Finck } 1739c2c66affSColin Finck else 1740c2c66affSColin Finck { 1741c2c66affSColin Finck /* Use local event */ 1742c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 1743c2c66affSColin Finck LocalEvent = TRUE; 1744c2c66affSColin Finck } 1745c2c66affSColin Finck 1746c2c66affSColin Finck /* Clear the File Object event */ 1747c2c66affSColin Finck KeClearEvent(&FileObject->Event); 1748c2c66affSColin Finck 1749c2c66affSColin Finck /* Get the device object */ 1750c2c66affSColin Finck DeviceObject = IoGetRelatedDeviceObject(FileObject); 1751c2c66affSColin Finck 1752c2c66affSColin Finck /* Allocate the IRP */ 1753c2c66affSColin Finck Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 1754c2c66affSColin Finck if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 1755c2c66affSColin Finck 1756c2c66affSColin Finck /* Set the IRP */ 1757c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 1758c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 1759c2c66affSColin Finck Irp->RequestorMode = ExGetPreviousMode(); 1760c2c66affSColin Finck Irp->UserIosb = &IoStatusBlock; 1761c2c66affSColin Finck Irp->UserEvent = (LocalEvent) ? &Event : NULL; 1762c2c66affSColin Finck Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 1763c2c66affSColin Finck Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 1764c2c66affSColin Finck 1765c2c66affSColin Finck /* Set Stack Parameters */ 1766c2c66affSColin Finck StackPtr = IoGetNextIrpStackLocation(Irp); 1767c2c66affSColin Finck StackPtr->FileObject = FileObject; 1768c2c66affSColin Finck 1769c2c66affSColin Finck /* Check if this is a query or set */ 1770c2c66affSColin Finck if (OperationCode == QuerySecurityDescriptor) 1771c2c66affSColin Finck { 1772c2c66affSColin Finck /* Set the major function and parameters */ 1773c2c66affSColin Finck StackPtr->MajorFunction = IRP_MJ_QUERY_SECURITY; 1774c2c66affSColin Finck StackPtr->Parameters.QuerySecurity.SecurityInformation = 1775c2c66affSColin Finck *SecurityInformation; 1776c2c66affSColin Finck StackPtr->Parameters.QuerySecurity.Length = *BufferLength; 1777c2c66affSColin Finck Irp->UserBuffer = SecurityDescriptor; 1778c2c66affSColin Finck } 1779c2c66affSColin Finck else 1780c2c66affSColin Finck { 1781c2c66affSColin Finck /* Set the major function and parameters for a set */ 1782c2c66affSColin Finck StackPtr->MajorFunction = IRP_MJ_SET_SECURITY; 1783c2c66affSColin Finck StackPtr->Parameters.SetSecurity.SecurityInformation = 1784c2c66affSColin Finck *SecurityInformation; 1785c2c66affSColin Finck StackPtr->Parameters.SetSecurity.SecurityDescriptor = 1786c2c66affSColin Finck SecurityDescriptor; 1787c2c66affSColin Finck } 1788c2c66affSColin Finck 1789c2c66affSColin Finck /* Queue the IRP */ 1790c2c66affSColin Finck IopQueueIrpToThread(Irp); 1791c2c66affSColin Finck 1792c2c66affSColin Finck /* Update operation counts */ 1793c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 1794c2c66affSColin Finck 1795c2c66affSColin Finck /* Call the Driver */ 1796c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1797c2c66affSColin Finck 1798c2c66affSColin Finck /* Check if this was async I/O */ 1799c2c66affSColin Finck if (LocalEvent) 1800c2c66affSColin Finck { 1801c2c66affSColin Finck /* Check if the IRP is pending completion */ 1802c2c66affSColin Finck if (Status == STATUS_PENDING) 1803c2c66affSColin Finck { 1804c2c66affSColin Finck /* Wait on the local event */ 1805c2c66affSColin Finck KeWaitForSingleObject(&Event, 1806c2c66affSColin Finck Executive, 1807c2c66affSColin Finck KernelMode, 1808c2c66affSColin Finck FALSE, 1809c2c66affSColin Finck NULL); 1810c2c66affSColin Finck Status = IoStatusBlock.Status; 1811c2c66affSColin Finck } 1812c2c66affSColin Finck } 1813c2c66affSColin Finck else 1814c2c66affSColin Finck { 1815c2c66affSColin Finck /* Check if the IRP is pending completion */ 1816c2c66affSColin Finck if (Status == STATUS_PENDING) 1817c2c66affSColin Finck { 1818c2c66affSColin Finck /* Wait on the file object */ 1819c2c66affSColin Finck KeWaitForSingleObject(&FileObject->Event, 1820c2c66affSColin Finck Executive, 1821c2c66affSColin Finck KernelMode, 1822c2c66affSColin Finck FALSE, 1823c2c66affSColin Finck NULL); 1824c2c66affSColin Finck Status = FileObject->FinalStatus; 1825c2c66affSColin Finck } 1826c2c66affSColin Finck 1827c2c66affSColin Finck /* Release the lock */ 1828c2c66affSColin Finck IopUnlockFileObject(FileObject); 1829c2c66affSColin Finck } 1830c2c66affSColin Finck 1831c2c66affSColin Finck /* This Driver doesn't implement Security, so try to give it a default */ 1832c2c66affSColin Finck if (Status == STATUS_INVALID_DEVICE_REQUEST) 1833c2c66affSColin Finck { 1834c2c66affSColin Finck /* Was this a query? */ 1835c2c66affSColin Finck if (OperationCode == QuerySecurityDescriptor) 1836c2c66affSColin Finck { 1837c2c66affSColin Finck /* Set a World Security Descriptor */ 1838c2c66affSColin Finck Status = SeSetWorldSecurityDescriptor(*SecurityInformation, 1839c2c66affSColin Finck SecurityDescriptor, 1840c2c66affSColin Finck BufferLength); 1841c2c66affSColin Finck } 1842c2c66affSColin Finck else 1843c2c66affSColin Finck { 1844c2c66affSColin Finck /* It wasn't a query, so just fake success */ 1845c2c66affSColin Finck Status = STATUS_SUCCESS; 1846c2c66affSColin Finck } 1847c2c66affSColin Finck } 1848c2c66affSColin Finck else if (OperationCode == QuerySecurityDescriptor) 1849c2c66affSColin Finck { 1850c2c66affSColin Finck /* Callers usually expect the normalized form */ 1851c2c66affSColin Finck if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_BUFFER_TOO_SMALL; 1852c2c66affSColin Finck 1853c2c66affSColin Finck _SEH2_TRY 1854c2c66affSColin Finck { 1855c2c66affSColin Finck /* Return length */ 1856c2c66affSColin Finck *BufferLength = (ULONG)IoStatusBlock.Information; 1857c2c66affSColin Finck } 1858c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1859c2c66affSColin Finck { 1860c2c66affSColin Finck /* Get the exception code */ 1861c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 1862c2c66affSColin Finck } 1863c2c66affSColin Finck _SEH2_END; 1864c2c66affSColin Finck } 1865c2c66affSColin Finck 1866c2c66affSColin Finck /* Return Status */ 1867c2c66affSColin Finck return Status; 1868c2c66affSColin Finck } 1869c2c66affSColin Finck 1870c2c66affSColin Finck NTSTATUS 1871c2c66affSColin Finck NTAPI 18721348f62fSPierre Schweitzer IopQueryNameInternal(IN PVOID ObjectBody, 1873c2c66affSColin Finck IN BOOLEAN HasName, 1874c2c66affSColin Finck OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 1875c2c66affSColin Finck IN ULONG Length, 1876c2c66affSColin Finck OUT PULONG ReturnLength, 1877c2c66affSColin Finck IN KPROCESSOR_MODE PreviousMode) 1878c2c66affSColin Finck { 1879c2c66affSColin Finck POBJECT_NAME_INFORMATION LocalInfo; 1880c2c66affSColin Finck PFILE_NAME_INFORMATION LocalFileInfo; 1881c2c66affSColin Finck PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 1882c2c66affSColin Finck ULONG LocalReturnLength, FileLength; 1883c2c66affSColin Finck BOOLEAN LengthMismatch = FALSE; 1884c2c66affSColin Finck NTSTATUS Status; 1885c2c66affSColin Finck PWCHAR p; 1886c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 1887c2c66affSColin Finck 1888c2c66affSColin Finck /* Validate length */ 1889c2c66affSColin Finck if (Length < sizeof(OBJECT_NAME_INFORMATION)) 1890c2c66affSColin Finck { 1891c2c66affSColin Finck /* Wrong length, fail */ 1892c2c66affSColin Finck *ReturnLength = sizeof(OBJECT_NAME_INFORMATION); 1893c2c66affSColin Finck return STATUS_INFO_LENGTH_MISMATCH; 1894c2c66affSColin Finck } 1895c2c66affSColin Finck 1896c2c66affSColin Finck /* Allocate Buffer */ 1897c2c66affSColin Finck LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO); 1898c2c66affSColin Finck if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES; 1899c2c66affSColin Finck 1900c2c66affSColin Finck /* Query the name */ 1901c2c66affSColin Finck Status = ObQueryNameString(FileObject->DeviceObject, 1902c2c66affSColin Finck LocalInfo, 1903c2c66affSColin Finck Length, 1904c2c66affSColin Finck &LocalReturnLength); 1905c2c66affSColin Finck if (!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) 1906c2c66affSColin Finck { 1907c2c66affSColin Finck /* Free the buffer and fail */ 1908c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 1909c2c66affSColin Finck return Status; 1910c2c66affSColin Finck } 1911c2c66affSColin Finck 1912c2c66affSColin Finck /* Copy the information */ 1913c2c66affSColin Finck RtlCopyMemory(ObjectNameInfo, 1914c2c66affSColin Finck LocalInfo, 1915c2c66affSColin Finck (LocalReturnLength > Length) ? 1916c2c66affSColin Finck Length : LocalReturnLength); 1917c2c66affSColin Finck 1918c2c66affSColin Finck /* Set buffer pointer */ 1919c2c66affSColin Finck p = (PWCHAR)(ObjectNameInfo + 1); 1920c2c66affSColin Finck ObjectNameInfo->Name.Buffer = p; 1921c2c66affSColin Finck 1922c2c66affSColin Finck /* Advance in buffer */ 1923c2c66affSColin Finck p += (LocalInfo->Name.Length / sizeof(WCHAR)); 1924c2c66affSColin Finck 1925c2c66affSColin Finck /* Check if this already filled our buffer */ 1926c2c66affSColin Finck if (LocalReturnLength > Length) 1927c2c66affSColin Finck { 1928c2c66affSColin Finck /* Set the length mismatch to true, so that we can return 1929c2c66affSColin Finck * the proper buffer size to the caller later 1930c2c66affSColin Finck */ 1931c2c66affSColin Finck LengthMismatch = TRUE; 1932c2c66affSColin Finck 1933c2c66affSColin Finck /* Save the initial buffer length value */ 1934c2c66affSColin Finck *ReturnLength = LocalReturnLength; 1935c2c66affSColin Finck } 1936c2c66affSColin Finck 1937c2c66affSColin Finck /* Now get the file name buffer and check the length needed */ 1938c2c66affSColin Finck LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo; 1939c2c66affSColin Finck FileLength = Length - 1940c2c66affSColin Finck LocalReturnLength + 1941c2c66affSColin Finck FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 1942c2c66affSColin Finck 1943c2c66affSColin Finck /* Query the File name */ 1944*a1401a75SPierre Schweitzer if (PreviousMode == KernelMode && 1945*a1401a75SPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 1946*a1401a75SPierre Schweitzer { 1947*a1401a75SPierre Schweitzer Status = IopGetFileInformation(FileObject, 1948*a1401a75SPierre Schweitzer LengthMismatch ? Length : FileLength, 1949*a1401a75SPierre Schweitzer FileNameInformation, 1950*a1401a75SPierre Schweitzer LocalFileInfo, 1951*a1401a75SPierre Schweitzer &LocalReturnLength); 1952*a1401a75SPierre Schweitzer } 1953*a1401a75SPierre Schweitzer else 1954*a1401a75SPierre Schweitzer { 1955c2c66affSColin Finck Status = IoQueryFileInformation(FileObject, 1956c2c66affSColin Finck FileNameInformation, 1957c2c66affSColin Finck LengthMismatch ? Length : FileLength, 1958c2c66affSColin Finck LocalFileInfo, 1959c2c66affSColin Finck &LocalReturnLength); 1960*a1401a75SPierre Schweitzer } 1961c2c66affSColin Finck if (NT_ERROR(Status)) 1962c2c66affSColin Finck { 1963c2c66affSColin Finck /* Fail on errors only, allow warnings */ 1964c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 1965c2c66affSColin Finck return Status; 1966c2c66affSColin Finck } 1967c2c66affSColin Finck 1968c2c66affSColin Finck /* If the provided buffer is too small, return the required size */ 1969c2c66affSColin Finck if (LengthMismatch) 1970c2c66affSColin Finck { 1971c2c66affSColin Finck /* Add the required length */ 1972c2c66affSColin Finck *ReturnLength += LocalFileInfo->FileNameLength; 1973c2c66affSColin Finck 1974c2c66affSColin Finck /* Free the allocated buffer and return failure */ 1975c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 1976c2c66affSColin Finck return STATUS_BUFFER_OVERFLOW; 1977c2c66affSColin Finck } 1978c2c66affSColin Finck 1979c2c66affSColin Finck /* Now calculate the new lengths left */ 1980c2c66affSColin Finck FileLength = LocalReturnLength - 1981c2c66affSColin Finck FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 1982c2c66affSColin Finck LocalReturnLength = (ULONG)((ULONG_PTR)p - 1983c2c66affSColin Finck (ULONG_PTR)ObjectNameInfo + 1984c2c66affSColin Finck LocalFileInfo->FileNameLength); 1985c2c66affSColin Finck 1986c2c66affSColin Finck /* Write the Name and null-terminate it */ 1987c2c66affSColin Finck RtlCopyMemory(p, LocalFileInfo->FileName, FileLength); 1988c2c66affSColin Finck p += (FileLength / sizeof(WCHAR)); 1989c2c66affSColin Finck *p = UNICODE_NULL; 1990c2c66affSColin Finck LocalReturnLength += sizeof(UNICODE_NULL); 1991c2c66affSColin Finck 1992c2c66affSColin Finck /* Return the length needed */ 1993c2c66affSColin Finck *ReturnLength = LocalReturnLength; 1994c2c66affSColin Finck 1995c2c66affSColin Finck /* Setup the length and maximum length */ 1996c2c66affSColin Finck FileLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo); 1997c2c66affSColin Finck ObjectNameInfo->Name.Length = (USHORT)FileLength - 1998c2c66affSColin Finck sizeof(OBJECT_NAME_INFORMATION); 1999c2c66affSColin Finck ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length + 2000c2c66affSColin Finck sizeof(UNICODE_NULL); 2001c2c66affSColin Finck 2002c2c66affSColin Finck /* Free buffer and return */ 2003c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 2004c2c66affSColin Finck return Status; 2005c2c66affSColin Finck } 2006c2c66affSColin Finck 2007c2c66affSColin Finck VOID 2008c2c66affSColin Finck NTAPI 2009c2c66affSColin Finck IopCloseFile(IN PEPROCESS Process OPTIONAL, 2010c2c66affSColin Finck IN PVOID ObjectBody, 2011c2c66affSColin Finck IN ACCESS_MASK GrantedAccess, 2012c2c66affSColin Finck IN ULONG HandleCount, 2013c2c66affSColin Finck IN ULONG SystemHandleCount) 2014c2c66affSColin Finck { 2015c2c66affSColin Finck PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 2016c2c66affSColin Finck KEVENT Event; 2017c2c66affSColin Finck PIRP Irp; 2018c2c66affSColin Finck PIO_STACK_LOCATION StackPtr; 2019c2c66affSColin Finck NTSTATUS Status; 2020c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 2021c2c66affSColin Finck KIRQL OldIrql; 20225472c1dbSPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock; 2023c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 2024c2c66affSColin Finck 2025c2c66affSColin Finck /* If this isn't the last handle for the current process, quit */ 2026c2c66affSColin Finck if (HandleCount != 1) return; 2027c2c66affSColin Finck 2028c2c66affSColin Finck /* Check if the file is locked and has more then one handle opened */ 2029c2c66affSColin Finck if ((FileObject->LockOperation) && (SystemHandleCount != 1)) 2030c2c66affSColin Finck { 20315472c1dbSPierre Schweitzer /* Check if this is a direct open or not */ 20325472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN)) 20335472c1dbSPierre Schweitzer { 20345472c1dbSPierre Schweitzer /* Get the attached device */ 20355472c1dbSPierre Schweitzer DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 20365472c1dbSPierre Schweitzer } 20375472c1dbSPierre Schweitzer else 20385472c1dbSPierre Schweitzer { 20395472c1dbSPierre Schweitzer /* Get the FO's device */ 20405472c1dbSPierre Schweitzer DeviceObject = IoGetRelatedDeviceObject(FileObject); 20415472c1dbSPierre Schweitzer } 20425472c1dbSPierre Schweitzer 20435472c1dbSPierre Schweitzer /* Check if this is a sync FO and lock it */ 20445472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 20455472c1dbSPierre Schweitzer { 20468fbc4880SThomas Faber (VOID)IopLockFileObject(FileObject, KernelMode); 20475472c1dbSPierre Schweitzer } 20485472c1dbSPierre Schweitzer 20495472c1dbSPierre Schweitzer /* Go the FastIO path if possible, otherwise fall back to IRP */ 20505472c1dbSPierre Schweitzer if (DeviceObject->DriverObject->FastIoDispatch == NULL || 20515472c1dbSPierre Schweitzer DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL || 20525472c1dbSPierre Schweitzer !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject)) 20535472c1dbSPierre Schweitzer { 20545472c1dbSPierre Schweitzer /* Clear and set up Events */ 20555472c1dbSPierre Schweitzer KeClearEvent(&FileObject->Event); 20565472c1dbSPierre Schweitzer KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 20575472c1dbSPierre Schweitzer 20585472c1dbSPierre Schweitzer /* Allocate an IRP */ 20595472c1dbSPierre Schweitzer Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 20605472c1dbSPierre Schweitzer 20615472c1dbSPierre Schweitzer /* Set it up */ 20625472c1dbSPierre Schweitzer Irp->UserEvent = &Event; 20635472c1dbSPierre Schweitzer Irp->UserIosb = &Irp->IoStatus; 20645472c1dbSPierre Schweitzer Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 20655472c1dbSPierre Schweitzer Irp->Tail.Overlay.OriginalFileObject = FileObject; 20665472c1dbSPierre Schweitzer Irp->RequestorMode = KernelMode; 20675472c1dbSPierre Schweitzer Irp->Flags = IRP_SYNCHRONOUS_API; 20685472c1dbSPierre Schweitzer Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 2069207ff944SPierre Schweitzer ObReferenceObject(FileObject); 20705472c1dbSPierre Schweitzer 20715472c1dbSPierre Schweitzer /* Set up Stack Pointer Data */ 20725472c1dbSPierre Schweitzer StackPtr = IoGetNextIrpStackLocation(Irp); 20735472c1dbSPierre Schweitzer StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; 20745472c1dbSPierre Schweitzer StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL; 20755472c1dbSPierre Schweitzer StackPtr->FileObject = FileObject; 20765472c1dbSPierre Schweitzer 20775472c1dbSPierre Schweitzer /* Queue the IRP */ 20785472c1dbSPierre Schweitzer IopQueueIrpToThread(Irp); 20795472c1dbSPierre Schweitzer 20805472c1dbSPierre Schweitzer /* Call the FS Driver */ 20815472c1dbSPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp); 20825472c1dbSPierre Schweitzer if (Status == STATUS_PENDING) 20835472c1dbSPierre Schweitzer { 20845472c1dbSPierre Schweitzer /* Wait for completion */ 20855472c1dbSPierre Schweitzer KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); 20865472c1dbSPierre Schweitzer } 20875472c1dbSPierre Schweitzer 20885472c1dbSPierre Schweitzer /* IO will unqueue & free for us */ 20895472c1dbSPierre Schweitzer } 20905472c1dbSPierre Schweitzer 20915472c1dbSPierre Schweitzer /* Release the lock if we were holding it */ 20925472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 20935472c1dbSPierre Schweitzer { 20945472c1dbSPierre Schweitzer IopUnlockFileObject(FileObject); 20955472c1dbSPierre Schweitzer } 2096c2c66affSColin Finck } 2097c2c66affSColin Finck 2098c2c66affSColin Finck /* Make sure this is the last handle */ 2099c2c66affSColin Finck if (SystemHandleCount != 1) return; 2100c2c66affSColin Finck 2101c2c66affSColin Finck /* Check if this is a direct open or not */ 2102c2c66affSColin Finck if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 2103c2c66affSColin Finck { 2104c2c66affSColin Finck /* Get the attached device */ 2105c2c66affSColin Finck DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 2106c2c66affSColin Finck } 2107c2c66affSColin Finck else 2108c2c66affSColin Finck { 2109c2c66affSColin Finck /* Get the FO's device */ 2110c2c66affSColin Finck DeviceObject = IoGetRelatedDeviceObject(FileObject); 2111c2c66affSColin Finck } 2112c2c66affSColin Finck 2113c2c66affSColin Finck /* Set the handle created flag */ 2114c2c66affSColin Finck FileObject->Flags |= FO_HANDLE_CREATED; 2115c2c66affSColin Finck 2116c2c66affSColin Finck /* Check if this is a sync FO and lock it */ 2117cf25432eSPierre Schweitzer if (Process != NULL && 2118cf25432eSPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 2119cf25432eSPierre Schweitzer { 21208fbc4880SThomas Faber (VOID)IopLockFileObject(FileObject, KernelMode); 2121cf25432eSPierre Schweitzer } 2122c2c66affSColin Finck 2123c2c66affSColin Finck /* Clear and set up Events */ 2124c2c66affSColin Finck KeClearEvent(&FileObject->Event); 2125c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 2126c2c66affSColin Finck 2127c2c66affSColin Finck /* Allocate an IRP */ 2128c2c66affSColin Finck Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 2129c2c66affSColin Finck 2130c2c66affSColin Finck /* Set it up */ 2131c2c66affSColin Finck Irp->UserEvent = &Event; 2132c2c66affSColin Finck Irp->UserIosb = &Irp->IoStatus; 2133c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 2134c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 2135c2c66affSColin Finck Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 2136c2c66affSColin Finck Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 2137c2c66affSColin Finck 2138c2c66affSColin Finck /* Set up Stack Pointer Data */ 2139c2c66affSColin Finck StackPtr = IoGetNextIrpStackLocation(Irp); 2140c2c66affSColin Finck StackPtr->MajorFunction = IRP_MJ_CLEANUP; 2141c2c66affSColin Finck StackPtr->FileObject = FileObject; 2142c2c66affSColin Finck 2143c2c66affSColin Finck /* Queue the IRP */ 2144c2c66affSColin Finck IopQueueIrpToThread(Irp); 2145c2c66affSColin Finck 2146c2c66affSColin Finck /* Update operation counts */ 2147c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2148c2c66affSColin Finck 2149c2c66affSColin Finck /* Call the FS Driver */ 2150c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 2151c2c66affSColin Finck if (Status == STATUS_PENDING) 2152c2c66affSColin Finck { 2153c2c66affSColin Finck /* Wait for completion */ 2154c2c66affSColin Finck KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); 2155c2c66affSColin Finck } 2156c2c66affSColin Finck 2157c2c66affSColin Finck /* Unqueue the IRP */ 2158c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 2159c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 2160c2c66affSColin Finck KeLowerIrql(OldIrql); 2161c2c66affSColin Finck 2162c2c66affSColin Finck /* Free the IRP */ 2163c2c66affSColin Finck IoFreeIrp(Irp); 2164c2c66affSColin Finck 2165c2c66affSColin Finck /* Release the lock if we were holding it */ 2166cf25432eSPierre Schweitzer if (Process != NULL && 2167cf25432eSPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 2168cf25432eSPierre Schweitzer { 2169cf25432eSPierre Schweitzer IopUnlockFileObject(FileObject); 2170cf25432eSPierre Schweitzer } 2171c2c66affSColin Finck } 2172c2c66affSColin Finck 2173c2c66affSColin Finck NTSTATUS 2174c2c66affSColin Finck NTAPI 2175c2c66affSColin Finck IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 2176c2c66affSColin Finck IN FILE_INFORMATION_CLASS FileInformationClass, 2177c2c66affSColin Finck IN ULONG FileInformationSize, 2178c2c66affSColin Finck OUT PVOID FileInformation) 2179c2c66affSColin Finck { 2180c2c66affSColin Finck NTSTATUS Status; 2181c2c66affSColin Finck KPROCESSOR_MODE AccessMode = ExGetPreviousMode(); 2182c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 2183c2c66affSColin Finck FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo; 2184c2c66affSColin Finck HANDLE Handle; 2185c2c66affSColin Finck OPEN_PACKET OpenPacket; 2186c2c66affSColin Finck BOOLEAN IsBasic; 2187c2c66affSColin Finck PAGED_CODE(); 2188c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass); 2189c2c66affSColin Finck 2190c2c66affSColin Finck /* Check if the caller was user mode */ 2191c2c66affSColin Finck if (AccessMode != KernelMode) 2192c2c66affSColin Finck { 2193c2c66affSColin Finck /* Protect probe in SEH */ 2194c2c66affSColin Finck _SEH2_TRY 2195c2c66affSColin Finck { 2196c2c66affSColin Finck /* Probe the buffer */ 2197c2c66affSColin Finck ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG)); 2198c2c66affSColin Finck } 2199c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2200c2c66affSColin Finck { 2201c2c66affSColin Finck /* Return the exception code */ 2202c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 2203c2c66affSColin Finck } 2204c2c66affSColin Finck _SEH2_END; 2205c2c66affSColin Finck } 2206c2c66affSColin Finck 2207c2c66affSColin Finck /* Check if this is a basic or full request */ 2208c2c66affSColin Finck IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION)); 2209c2c66affSColin Finck 2210c2c66affSColin Finck /* Setup the Open Packet */ 2211c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 2212c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 2213c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 2214c2c66affSColin Finck OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; 2215c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 2216c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 2217c2c66affSColin Finck OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL; 2218c2c66affSColin Finck OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo : 2219c2c66affSColin Finck (AccessMode != KernelMode) ? 2220c2c66affSColin Finck &NetworkOpenInfo : FileInformation; 2221c2c66affSColin Finck OpenPacket.QueryOnly = TRUE; 2222c2c66affSColin Finck OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE; 2223c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 2224c2c66affSColin Finck 2225c2c66affSColin Finck /* Update the operation count */ 2226c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2227c2c66affSColin Finck 2228c2c66affSColin Finck /* 2229c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 2230c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 2231c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 2232c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 2233c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 2234c2c66affSColin Finck * by the Parse Check member. 2235c2c66affSColin Finck */ 2236c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 2237c2c66affSColin Finck NULL, 2238c2c66affSColin Finck AccessMode, 2239c2c66affSColin Finck NULL, 2240c2c66affSColin Finck FILE_READ_ATTRIBUTES, 2241c2c66affSColin Finck &OpenPacket, 2242c2c66affSColin Finck &Handle); 2243c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) 2244c2c66affSColin Finck { 2245c2c66affSColin Finck /* Parse failed */ 2246c2c66affSColin Finck DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n", 2247c2c66affSColin Finck ObjectAttributes->ObjectName, Status); 2248c2c66affSColin Finck return Status; 2249c2c66affSColin Finck } 2250c2c66affSColin Finck else 2251c2c66affSColin Finck { 2252c2c66affSColin Finck /* Use the Io status */ 2253c2c66affSColin Finck Status = OpenPacket.FinalStatus; 2254c2c66affSColin Finck } 2255c2c66affSColin Finck 2256c2c66affSColin Finck /* Check if we were succesful and this was user mode and a full query */ 2257c2c66affSColin Finck if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic)) 2258c2c66affSColin Finck { 2259c2c66affSColin Finck /* Enter SEH for copy */ 2260c2c66affSColin Finck _SEH2_TRY 2261c2c66affSColin Finck { 2262c2c66affSColin Finck /* Copy the buffer back */ 2263c2c66affSColin Finck RtlCopyMemory(FileInformation, 2264c2c66affSColin Finck &NetworkOpenInfo, 2265c2c66affSColin Finck FileInformationSize); 2266c2c66affSColin Finck } 2267c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2268c2c66affSColin Finck { 2269c2c66affSColin Finck /* Get exception code */ 2270c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2271c2c66affSColin Finck } 2272c2c66affSColin Finck _SEH2_END; 2273c2c66affSColin Finck } 2274c2c66affSColin Finck 2275c2c66affSColin Finck /* Return status */ 2276c2c66affSColin Finck return Status; 2277c2c66affSColin Finck } 2278c2c66affSColin Finck 22798fbc4880SThomas Faber NTSTATUS 22808fbc4880SThomas Faber NTAPI 22818fbc4880SThomas Faber IopAcquireFileObjectLock( 22828fbc4880SThomas Faber _In_ PFILE_OBJECT FileObject, 22838fbc4880SThomas Faber _In_ KPROCESSOR_MODE WaitMode, 22848fbc4880SThomas Faber _In_ BOOLEAN Alertable, 22858fbc4880SThomas Faber _Out_ PBOOLEAN LockFailed) 22868fbc4880SThomas Faber { 22878fbc4880SThomas Faber NTSTATUS Status; 22888fbc4880SThomas Faber 22898fbc4880SThomas Faber PAGED_CODE(); 22908fbc4880SThomas Faber 22918fbc4880SThomas Faber InterlockedIncrement((PLONG)&FileObject->Waiters); 22928fbc4880SThomas Faber 22938fbc4880SThomas Faber Status = STATUS_SUCCESS; 22948fbc4880SThomas Faber do 22958fbc4880SThomas Faber { 22968fbc4880SThomas Faber if (!InterlockedExchange((PLONG)&FileObject->Busy, TRUE)) 22978fbc4880SThomas Faber { 22988fbc4880SThomas Faber break; 22998fbc4880SThomas Faber } 23008fbc4880SThomas Faber Status = KeWaitForSingleObject(&FileObject->Lock, 23018fbc4880SThomas Faber Executive, 23028fbc4880SThomas Faber WaitMode, 23038fbc4880SThomas Faber Alertable, 23048fbc4880SThomas Faber NULL); 23058fbc4880SThomas Faber } while (Status == STATUS_SUCCESS); 23068fbc4880SThomas Faber 23078fbc4880SThomas Faber InterlockedDecrement((PLONG)&FileObject->Waiters); 23088fbc4880SThomas Faber if (Status == STATUS_SUCCESS) 23098fbc4880SThomas Faber { 23108fbc4880SThomas Faber ObReferenceObject(FileObject); 23118fbc4880SThomas Faber *LockFailed = FALSE; 23128fbc4880SThomas Faber } 23138fbc4880SThomas Faber else 23148fbc4880SThomas Faber { 23158fbc4880SThomas Faber if (!FileObject->Busy && FileObject->Waiters) 23168fbc4880SThomas Faber { 23178fbc4880SThomas Faber KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE); 23188fbc4880SThomas Faber } 23198fbc4880SThomas Faber *LockFailed = TRUE; 23208fbc4880SThomas Faber } 23218fbc4880SThomas Faber 23228fbc4880SThomas Faber return Status; 23238fbc4880SThomas Faber } 23248fbc4880SThomas Faber 2325c2c66affSColin Finck PVOID 2326c2c66affSColin Finck NTAPI 2327c2c66affSColin Finck IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject) 2328c2c66affSColin Finck { 2329c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 2330c2c66affSColin Finck { 2331c2c66affSColin Finck UNIMPLEMENTED; 2332c2c66affSColin Finck /* FIXME: return NULL for the moment ~ */ 2333c2c66affSColin Finck return NULL; 2334c2c66affSColin Finck } 2335c2c66affSColin Finck 2336c2c66affSColin Finck return NULL; 2337c2c66affSColin Finck } 2338c2c66affSColin Finck 2339c2c66affSColin Finck NTSTATUS 2340c2c66affSColin Finck NTAPI 2341c2c66affSColin Finck IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, 2342c2c66affSColin Finck IN PVOID FilterContext, 2343c2c66affSColin Finck IN BOOLEAN Define) 2344c2c66affSColin Finck { 2345c2c66affSColin Finck if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) 2346c2c66affSColin Finck { 2347c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2348c2c66affSColin Finck } 2349c2c66affSColin Finck 2350c2c66affSColin Finck UNIMPLEMENTED; 2351c2c66affSColin Finck 2352c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2353c2c66affSColin Finck } 2354c2c66affSColin Finck 2355c2c66affSColin Finck NTSTATUS 2356c2c66affSColin Finck NTAPI 2357c2c66affSColin Finck IopCreateFile(OUT PHANDLE FileHandle, 2358c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2359c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2360c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2361c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2362c2c66affSColin Finck IN ULONG FileAttributes, 2363c2c66affSColin Finck IN ULONG ShareAccess, 2364c2c66affSColin Finck IN ULONG Disposition, 2365c2c66affSColin Finck IN ULONG CreateOptions, 2366c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2367c2c66affSColin Finck IN ULONG EaLength, 2368c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2369c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2370c2c66affSColin Finck IN ULONG Options, 2371c2c66affSColin Finck IN ULONG Flags, 2372c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL) 2373c2c66affSColin Finck { 2374c2c66affSColin Finck KPROCESSOR_MODE AccessMode; 2375c2c66affSColin Finck HANDLE LocalHandle = 0; 2376c2c66affSColin Finck LARGE_INTEGER SafeAllocationSize; 2377c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 2378c2c66affSColin Finck PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters; 2379c2c66affSColin Finck POPEN_PACKET OpenPacket; 2380c2c66affSColin Finck ULONG EaErrorOffset; 2381c2c66affSColin Finck PAGED_CODE(); 2382c2c66affSColin Finck 2383c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 2384c2c66affSColin Finck 2385c2c66affSColin Finck 2386c2c66affSColin Finck /* Check if we have no parameter checking to do */ 2387c2c66affSColin Finck if (Options & IO_NO_PARAMETER_CHECKING) 2388c2c66affSColin Finck { 2389c2c66affSColin Finck /* Then force kernel-mode access to avoid checks */ 2390c2c66affSColin Finck AccessMode = KernelMode; 2391c2c66affSColin Finck } 2392c2c66affSColin Finck else 2393c2c66affSColin Finck { 2394c2c66affSColin Finck /* Otherwise, use the actual mode */ 2395c2c66affSColin Finck AccessMode = ExGetPreviousMode(); 2396c2c66affSColin Finck } 2397c2c66affSColin Finck 2398c2c66affSColin Finck /* Check if we need to do parameter checking */ 2399c2c66affSColin Finck if ((AccessMode != KernelMode) || (Options & IO_CHECK_CREATE_PARAMETERS)) 2400c2c66affSColin Finck { 2401c2c66affSColin Finck /* Validate parameters */ 2402c2c66affSColin Finck if (FileAttributes & ~FILE_ATTRIBUTE_VALID_FLAGS) 2403c2c66affSColin Finck { 2404c2c66affSColin Finck DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n"); 2405c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2406c2c66affSColin Finck } 2407c2c66affSColin Finck 2408c2c66affSColin Finck if (ShareAccess & ~FILE_SHARE_VALID_FLAGS) 2409c2c66affSColin Finck { 2410c2c66affSColin Finck DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n"); 2411c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2412c2c66affSColin Finck } 2413c2c66affSColin Finck 2414c2c66affSColin Finck if (Disposition > FILE_MAXIMUM_DISPOSITION) 2415c2c66affSColin Finck { 2416c2c66affSColin Finck DPRINT1("File Create 'Disposition' Parameter is out of range!\n"); 2417c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2418c2c66affSColin Finck } 2419c2c66affSColin Finck 2420c2c66affSColin Finck if (CreateOptions & ~FILE_VALID_OPTION_FLAGS) 2421c2c66affSColin Finck { 2422c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n"); 2423c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2424c2c66affSColin Finck } 2425c2c66affSColin Finck 2426c2c66affSColin Finck if ((CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) && 2427c2c66affSColin Finck (!(DesiredAccess & SYNCHRONIZE))) 2428c2c66affSColin Finck { 2429c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n"); 2430c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2431c2c66affSColin Finck } 2432c2c66affSColin Finck 2433c2c66affSColin Finck if ((CreateOptions & FILE_DELETE_ON_CLOSE) && (!(DesiredAccess & DELETE))) 2434c2c66affSColin Finck { 2435c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n"); 2436c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2437c2c66affSColin Finck } 2438c2c66affSColin Finck 2439c2c66affSColin Finck if ((CreateOptions & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)) == 2440c2c66affSColin Finck (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)) 2441c2c66affSColin Finck { 2442c2c66affSColin Finck DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n"); 2443c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2444c2c66affSColin Finck } 2445c2c66affSColin Finck 2446c2c66affSColin Finck if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) && 2447c2c66affSColin Finck (CreateOptions & ~(FILE_DIRECTORY_FILE | 2448c2c66affSColin Finck FILE_SYNCHRONOUS_IO_ALERT | 2449c2c66affSColin Finck FILE_SYNCHRONOUS_IO_NONALERT | 2450c2c66affSColin Finck FILE_WRITE_THROUGH | 2451c2c66affSColin Finck FILE_COMPLETE_IF_OPLOCKED | 2452c2c66affSColin Finck FILE_OPEN_FOR_BACKUP_INTENT | 2453c2c66affSColin Finck FILE_DELETE_ON_CLOSE | 2454c2c66affSColin Finck FILE_OPEN_FOR_FREE_SPACE_QUERY | 2455c2c66affSColin Finck FILE_OPEN_BY_FILE_ID | 2456c2c66affSColin Finck FILE_NO_COMPRESSION | 2457c2c66affSColin Finck FILE_OPEN_REPARSE_POINT))) 2458c2c66affSColin Finck { 2459c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n"); 2460c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2461c2c66affSColin Finck } 2462c2c66affSColin Finck 2463c2c66affSColin Finck if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) && 2464c2c66affSColin Finck (Disposition != FILE_CREATE) && (Disposition != FILE_OPEN) && (Disposition != FILE_OPEN_IF)) 2465c2c66affSColin Finck { 2466c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n"); 2467c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2468c2c66affSColin Finck } 2469c2c66affSColin Finck 2470c2c66affSColin Finck if ((CreateOptions & FILE_COMPLETE_IF_OPLOCKED) && (CreateOptions & FILE_RESERVE_OPFILTER)) 2471c2c66affSColin Finck { 2472c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n"); 2473c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2474c2c66affSColin Finck } 2475c2c66affSColin Finck 2476c2c66affSColin Finck if ((CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) && (DesiredAccess & FILE_APPEND_DATA)) 2477c2c66affSColin Finck { 2478c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n"); 2479c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2480c2c66affSColin Finck } 2481c2c66affSColin Finck 2482c2c66affSColin Finck /* Now check if this is a named pipe */ 2483c2c66affSColin Finck if (CreateFileType == CreateFileTypeNamedPipe) 2484c2c66affSColin Finck { 2485c2c66affSColin Finck /* Make sure we have extra parameters */ 2486c2c66affSColin Finck if (!ExtraCreateParameters) 2487c2c66affSColin Finck { 2488c2c66affSColin Finck DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n"); 2489c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2490c2c66affSColin Finck } 2491c2c66affSColin Finck 2492c2c66affSColin Finck /* Get the parameters and validate them */ 2493c2c66affSColin Finck NamedPipeCreateParameters = ExtraCreateParameters; 2494c2c66affSColin Finck if ((NamedPipeCreateParameters->NamedPipeType > FILE_PIPE_MESSAGE_TYPE) || 2495c2c66affSColin Finck (NamedPipeCreateParameters->ReadMode > FILE_PIPE_MESSAGE_MODE) || 2496c2c66affSColin Finck (NamedPipeCreateParameters->CompletionMode > FILE_PIPE_COMPLETE_OPERATION) || 2497c2c66affSColin Finck (ShareAccess & FILE_SHARE_DELETE) || 2498c2c66affSColin Finck ((Disposition < FILE_OPEN) || (Disposition > FILE_OPEN_IF)) || 2499c2c66affSColin Finck (CreateOptions & ~FILE_VALID_PIPE_OPTION_FLAGS)) 2500c2c66affSColin Finck { 2501c2c66affSColin Finck /* Invalid named pipe create */ 2502c2c66affSColin Finck DPRINT1("Invalid named pipe create\n"); 2503c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2504c2c66affSColin Finck } 2505c2c66affSColin Finck } 2506c2c66affSColin Finck else if (CreateFileType == CreateFileTypeMailslot) 2507c2c66affSColin Finck { 2508c2c66affSColin Finck /* Make sure we have extra parameters */ 2509c2c66affSColin Finck if (!ExtraCreateParameters) 2510c2c66affSColin Finck { 2511c2c66affSColin Finck DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n"); 2512c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2513c2c66affSColin Finck } 2514c2c66affSColin Finck 2515c2c66affSColin Finck /* Get the parameters and validate them */ 2516c2c66affSColin Finck if ((ShareAccess & FILE_SHARE_DELETE) || 2517c2c66affSColin Finck !(ShareAccess & ~FILE_SHARE_WRITE) || 2518c2c66affSColin Finck (Disposition != FILE_CREATE) || 2519c2c66affSColin Finck (CreateOptions & ~FILE_VALID_MAILSLOT_OPTION_FLAGS)) 2520c2c66affSColin Finck { 2521c2c66affSColin Finck /* Invalid mailslot create */ 2522c2c66affSColin Finck DPRINT1("Invalid mailslot create\n"); 2523c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2524c2c66affSColin Finck } 2525c2c66affSColin Finck } 2526c2c66affSColin Finck } 2527c2c66affSColin Finck 2528c2c66affSColin Finck /* Allocate the open packet */ 2529c2c66affSColin Finck OpenPacket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*OpenPacket), 'pOoI'); 2530c2c66affSColin Finck if (!OpenPacket) return STATUS_INSUFFICIENT_RESOURCES; 2531c2c66affSColin Finck RtlZeroMemory(OpenPacket, sizeof(*OpenPacket)); 2532c2c66affSColin Finck 2533c2c66affSColin Finck /* Check if the call came from user mode */ 2534c2c66affSColin Finck if (AccessMode != KernelMode) 2535c2c66affSColin Finck { 2536c2c66affSColin Finck _SEH2_TRY 2537c2c66affSColin Finck { 2538c2c66affSColin Finck /* Probe the output parameters */ 2539c2c66affSColin Finck ProbeForWriteHandle(FileHandle); 2540c2c66affSColin Finck ProbeForWriteIoStatusBlock(IoStatusBlock); 2541c2c66affSColin Finck 2542c2c66affSColin Finck /* Probe the allocation size if one was passed in */ 2543c2c66affSColin Finck if (AllocationSize) 2544c2c66affSColin Finck { 2545c2c66affSColin Finck SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize); 2546c2c66affSColin Finck } 2547c2c66affSColin Finck else 2548c2c66affSColin Finck { 2549c2c66affSColin Finck SafeAllocationSize.QuadPart = 0; 2550c2c66affSColin Finck } 2551c2c66affSColin Finck 2552c2c66affSColin Finck /* Make sure it's valid */ 2553c2c66affSColin Finck if (SafeAllocationSize.QuadPart < 0) 2554c2c66affSColin Finck { 2555c2c66affSColin Finck RtlRaiseStatus(STATUS_INVALID_PARAMETER); 2556c2c66affSColin Finck } 2557c2c66affSColin Finck 2558c2c66affSColin Finck /* Check if EA was passed in */ 2559c2c66affSColin Finck if ((EaBuffer) && (EaLength)) 2560c2c66affSColin Finck { 2561c2c66affSColin Finck /* Probe it */ 2562c2c66affSColin Finck ProbeForRead(EaBuffer, EaLength, sizeof(ULONG)); 2563c2c66affSColin Finck 2564c2c66affSColin Finck /* And marshall it */ 2565c2c66affSColin Finck OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool, 2566c2c66affSColin Finck EaLength, 2567c2c66affSColin Finck TAG_EA); 2568c2c66affSColin Finck OpenPacket->EaLength = EaLength; 2569c2c66affSColin Finck RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength); 2570c2c66affSColin Finck 2571c2c66affSColin Finck /* Validate the buffer */ 2572c2c66affSColin Finck Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer, 2573c2c66affSColin Finck EaLength, 2574c2c66affSColin Finck &EaErrorOffset); 2575c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2576c2c66affSColin Finck { 2577c2c66affSColin Finck /* Undo everything if it's invalid */ 2578c2c66affSColin Finck DPRINT1("Invalid EA buffer\n"); 2579c2c66affSColin Finck IoStatusBlock->Status = Status; 2580c2c66affSColin Finck IoStatusBlock->Information = EaErrorOffset; 2581c2c66affSColin Finck RtlRaiseStatus(Status); 2582c2c66affSColin Finck } 2583c2c66affSColin Finck } 2584c2c66affSColin Finck } 2585c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2586c2c66affSColin Finck { 2587c2c66affSColin Finck /* Return the exception code */ 2588c2c66affSColin Finck if (OpenPacket->EaBuffer != NULL) ExFreePool(OpenPacket->EaBuffer); 2589c2c66affSColin Finck ExFreePool(OpenPacket); 2590c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 2591c2c66affSColin Finck } 2592c2c66affSColin Finck _SEH2_END; 2593c2c66affSColin Finck } 2594c2c66affSColin Finck else 2595c2c66affSColin Finck { 2596c2c66affSColin Finck /* Check if this is a device attach */ 2597c2c66affSColin Finck if (CreateOptions & IO_ATTACH_DEVICE_API) 2598c2c66affSColin Finck { 2599c2c66affSColin Finck /* Set the flag properly */ 2600c2c66affSColin Finck Options |= IO_ATTACH_DEVICE; 2601c2c66affSColin Finck CreateOptions &= ~IO_ATTACH_DEVICE_API; 2602c2c66affSColin Finck } 2603c2c66affSColin Finck 2604c2c66affSColin Finck /* Check if we have allocation size */ 2605c2c66affSColin Finck if (AllocationSize) 2606c2c66affSColin Finck { 2607c2c66affSColin Finck /* Capture it */ 2608c2c66affSColin Finck SafeAllocationSize = *AllocationSize; 2609c2c66affSColin Finck } 2610c2c66affSColin Finck else 2611c2c66affSColin Finck { 2612c2c66affSColin Finck /* Otherwise, no size */ 2613c2c66affSColin Finck SafeAllocationSize.QuadPart = 0; 2614c2c66affSColin Finck } 2615c2c66affSColin Finck 2616c2c66affSColin Finck /* Check if we have an EA packet */ 2617c2c66affSColin Finck if ((EaBuffer) && (EaLength)) 2618c2c66affSColin Finck { 2619c2c66affSColin Finck /* Allocate the kernel copy */ 2620c2c66affSColin Finck OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool, 2621c2c66affSColin Finck EaLength, 2622c2c66affSColin Finck TAG_EA); 2623c2c66affSColin Finck if (!OpenPacket->EaBuffer) 2624c2c66affSColin Finck { 2625c2c66affSColin Finck ExFreePool(OpenPacket); 2626c2c66affSColin Finck DPRINT1("Failed to allocate open packet EA buffer\n"); 2627c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 2628c2c66affSColin Finck } 2629c2c66affSColin Finck 2630c2c66affSColin Finck /* Copy the data */ 2631c2c66affSColin Finck OpenPacket->EaLength = EaLength; 2632c2c66affSColin Finck RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength); 2633c2c66affSColin Finck 2634c2c66affSColin Finck /* Validate the buffer */ 2635c2c66affSColin Finck Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer, 2636c2c66affSColin Finck EaLength, 2637c2c66affSColin Finck &EaErrorOffset); 2638c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2639c2c66affSColin Finck { 2640c2c66affSColin Finck /* Undo everything if it's invalid */ 2641c2c66affSColin Finck DPRINT1("Invalid EA buffer\n"); 2642c2c66affSColin Finck ExFreePool(OpenPacket->EaBuffer); 2643c2c66affSColin Finck IoStatusBlock->Status = Status; 2644c2c66affSColin Finck IoStatusBlock->Information = EaErrorOffset; 2645c2c66affSColin Finck ExFreePool(OpenPacket); 2646c2c66affSColin Finck return Status; 2647c2c66affSColin Finck } 2648c2c66affSColin Finck } 2649c2c66affSColin Finck } 2650c2c66affSColin Finck 2651c2c66affSColin Finck /* Setup the Open Packet */ 2652c2c66affSColin Finck OpenPacket->Type = IO_TYPE_OPEN_PACKET; 2653c2c66affSColin Finck OpenPacket->Size = sizeof(*OpenPacket); 2654c2c66affSColin Finck OpenPacket->AllocationSize = SafeAllocationSize; 2655c2c66affSColin Finck OpenPacket->CreateOptions = CreateOptions; 2656c2c66affSColin Finck OpenPacket->FileAttributes = (USHORT)FileAttributes; 2657c2c66affSColin Finck OpenPacket->ShareAccess = (USHORT)ShareAccess; 2658c2c66affSColin Finck OpenPacket->Options = Options; 2659c2c66affSColin Finck OpenPacket->Disposition = Disposition; 2660c2c66affSColin Finck OpenPacket->CreateFileType = CreateFileType; 2661c2c66affSColin Finck OpenPacket->ExtraCreateParameters = ExtraCreateParameters; 2662c2c66affSColin Finck OpenPacket->InternalFlags = Flags; 2663c2c66affSColin Finck OpenPacket->TopDeviceObjectHint = DeviceObject; 2664c2c66affSColin Finck 2665c2c66affSColin Finck /* Update the operation count */ 2666c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2667c2c66affSColin Finck 2668c2c66affSColin Finck /* 2669c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 2670c2c66affSColin Finck * the File Object (IopParseDevice) which will create the object and 2671c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 2672c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 2673c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 2674c2c66affSColin Finck * by the Parse Check member. 2675c2c66affSColin Finck */ 2676c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 2677c2c66affSColin Finck NULL, 2678c2c66affSColin Finck AccessMode, 2679c2c66affSColin Finck NULL, 2680c2c66affSColin Finck DesiredAccess, 2681c2c66affSColin Finck OpenPacket, 2682c2c66affSColin Finck &LocalHandle); 2683c2c66affSColin Finck 2684c2c66affSColin Finck /* Free the EA Buffer */ 2685c2c66affSColin Finck if (OpenPacket->EaBuffer) ExFreePool(OpenPacket->EaBuffer); 2686c2c66affSColin Finck 2687c2c66affSColin Finck /* Now check for Ob or Io failure */ 2688c2c66affSColin Finck if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck == FALSE)) 2689c2c66affSColin Finck { 2690c2c66affSColin Finck /* Check if Ob thinks well went well */ 2691c2c66affSColin Finck if (NT_SUCCESS(Status)) 2692c2c66affSColin Finck { 2693c2c66affSColin Finck /* 2694c2c66affSColin Finck * Tell it otherwise. Because we didn't use an ObjectType, 2695c2c66affSColin Finck * it incorrectly returned us a handle to God knows what. 2696c2c66affSColin Finck */ 2697c2c66affSColin Finck ZwClose(LocalHandle); 2698c2c66affSColin Finck Status = STATUS_OBJECT_TYPE_MISMATCH; 2699c2c66affSColin Finck } 2700c2c66affSColin Finck 2701c2c66affSColin Finck /* Now check the Io status */ 2702c2c66affSColin Finck if (!NT_SUCCESS(OpenPacket->FinalStatus)) 2703c2c66affSColin Finck { 2704c2c66affSColin Finck /* Use this status instead of Ob's */ 2705c2c66affSColin Finck Status = OpenPacket->FinalStatus; 2706c2c66affSColin Finck 2707c2c66affSColin Finck /* Check if it was only a warning */ 2708c2c66affSColin Finck if (NT_WARNING(Status)) 2709c2c66affSColin Finck { 2710c2c66affSColin Finck /* Protect write with SEH */ 2711c2c66affSColin Finck _SEH2_TRY 2712c2c66affSColin Finck { 2713c2c66affSColin Finck /* In this case, we copy the I/O Status back */ 2714c2c66affSColin Finck IoStatusBlock->Information = OpenPacket->Information; 2715c2c66affSColin Finck IoStatusBlock->Status = OpenPacket->FinalStatus; 2716c2c66affSColin Finck } 2717c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2718c2c66affSColin Finck { 2719c2c66affSColin Finck /* Get exception code */ 2720c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2721c2c66affSColin Finck } 2722c2c66affSColin Finck _SEH2_END; 2723c2c66affSColin Finck } 2724c2c66affSColin Finck } 2725c2c66affSColin Finck else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck == FALSE)) 2726c2c66affSColin Finck { 2727c2c66affSColin Finck /* 2728c2c66affSColin Finck * This can happen in the very bizarre case where the parse routine 2729c2c66affSColin Finck * actually executed more then once (due to a reparse) and ended 2730c2c66affSColin Finck * up failing after already having created the File Object. 2731c2c66affSColin Finck */ 2732c2c66affSColin Finck if (OpenPacket->FileObject->FileName.Length) 2733c2c66affSColin Finck { 2734c2c66affSColin Finck /* It had a name, free it */ 2735c2c66affSColin Finck ExFreePoolWithTag(OpenPacket->FileObject->FileName.Buffer, TAG_IO_NAME); 2736c2c66affSColin Finck } 2737c2c66affSColin Finck 2738c2c66affSColin Finck /* Clear the device object to invalidate the FO, and dereference */ 2739c2c66affSColin Finck OpenPacket->FileObject->DeviceObject = NULL; 2740c2c66affSColin Finck ObDereferenceObject(OpenPacket->FileObject); 2741c2c66affSColin Finck } 2742c2c66affSColin Finck } 2743c2c66affSColin Finck else 2744c2c66affSColin Finck { 2745c2c66affSColin Finck /* We reached success and have a valid file handle */ 2746c2c66affSColin Finck OpenPacket->FileObject->Flags |= FO_HANDLE_CREATED; 2747c2c66affSColin Finck ASSERT(OpenPacket->FileObject->Type == IO_TYPE_FILE); 2748c2c66affSColin Finck 2749c2c66affSColin Finck /* Enter SEH for write back */ 2750c2c66affSColin Finck _SEH2_TRY 2751c2c66affSColin Finck { 2752c2c66affSColin Finck /* Write back the handle and I/O Status */ 2753c2c66affSColin Finck *FileHandle = LocalHandle; 2754c2c66affSColin Finck IoStatusBlock->Information = OpenPacket->Information; 2755c2c66affSColin Finck IoStatusBlock->Status = OpenPacket->FinalStatus; 2756c2c66affSColin Finck 2757c2c66affSColin Finck /* Get the Io status */ 2758c2c66affSColin Finck Status = OpenPacket->FinalStatus; 2759c2c66affSColin Finck } 2760c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2761c2c66affSColin Finck { 2762c2c66affSColin Finck /* Get the exception status */ 2763c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2764c2c66affSColin Finck } 2765c2c66affSColin Finck _SEH2_END; 2766c2c66affSColin Finck } 2767c2c66affSColin Finck 2768c2c66affSColin Finck /* Check if we were 100% successful */ 2769c2c66affSColin Finck if ((OpenPacket->ParseCheck != FALSE) && (OpenPacket->FileObject)) 2770c2c66affSColin Finck { 2771c2c66affSColin Finck /* Dereference the File Object */ 2772c2c66affSColin Finck ObDereferenceObject(OpenPacket->FileObject); 2773c2c66affSColin Finck } 2774c2c66affSColin Finck 2775c2c66affSColin Finck /* Return status */ 2776c2c66affSColin Finck ExFreePool(OpenPacket); 2777c2c66affSColin Finck return Status; 2778c2c66affSColin Finck } 2779c2c66affSColin Finck 2780c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 2781c2c66affSColin Finck 2782c2c66affSColin Finck /* 2783c2c66affSColin Finck * @unimplemented 2784c2c66affSColin Finck */ 2785c2c66affSColin Finck NTSTATUS 2786c2c66affSColin Finck NTAPI 2787c2c66affSColin Finck IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass, 2788c2c66affSColin Finck IN ULONG Length, 2789c2c66affSColin Finck IN BOOLEAN SetOperation) 2790c2c66affSColin Finck { 2791c2c66affSColin Finck UNIMPLEMENTED; 2792c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2793c2c66affSColin Finck } 2794c2c66affSColin Finck 2795c2c66affSColin Finck /* 2796c2c66affSColin Finck * @unimplemented 2797c2c66affSColin Finck */ 2798c2c66affSColin Finck NTSTATUS 2799c2c66affSColin Finck NTAPI 2800c2c66affSColin Finck IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer, 2801c2c66affSColin Finck IN ULONG QuotaLength, 2802c2c66affSColin Finck OUT PULONG ErrorOffset) 2803c2c66affSColin Finck { 2804c2c66affSColin Finck UNIMPLEMENTED; 2805c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2806c2c66affSColin Finck } 2807c2c66affSColin Finck 2808c2c66affSColin Finck /* 2809c2c66affSColin Finck * @implemented 2810c2c66affSColin Finck */ 2811c2c66affSColin Finck NTSTATUS 2812c2c66affSColin Finck NTAPI 2813c2c66affSColin Finck IoCreateFile(OUT PHANDLE FileHandle, 2814c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2815c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2816c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2817c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2818c2c66affSColin Finck IN ULONG FileAttributes, 2819c2c66affSColin Finck IN ULONG ShareAccess, 2820c2c66affSColin Finck IN ULONG Disposition, 2821c2c66affSColin Finck IN ULONG CreateOptions, 2822c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2823c2c66affSColin Finck IN ULONG EaLength, 2824c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2825c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2826c2c66affSColin Finck IN ULONG Options) 2827c2c66affSColin Finck { 2828c2c66affSColin Finck PAGED_CODE(); 2829c2c66affSColin Finck 2830c2c66affSColin Finck return IopCreateFile(FileHandle, 2831c2c66affSColin Finck DesiredAccess, 2832c2c66affSColin Finck ObjectAttributes, 2833c2c66affSColin Finck IoStatusBlock, 2834c2c66affSColin Finck AllocationSize, 2835c2c66affSColin Finck FileAttributes, 2836c2c66affSColin Finck ShareAccess, 2837c2c66affSColin Finck Disposition, 2838c2c66affSColin Finck CreateOptions, 2839c2c66affSColin Finck EaBuffer, 2840c2c66affSColin Finck EaLength, 2841c2c66affSColin Finck CreateFileType, 2842c2c66affSColin Finck ExtraCreateParameters, 2843c2c66affSColin Finck Options, 2844c2c66affSColin Finck 0, 2845c2c66affSColin Finck NULL); 2846c2c66affSColin Finck } 2847c2c66affSColin Finck 2848c2c66affSColin Finck /* 2849c2c66affSColin Finck * @unimplemented 2850c2c66affSColin Finck */ 2851c2c66affSColin Finck NTSTATUS 2852c2c66affSColin Finck NTAPI 2853c2c66affSColin Finck IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle, 2854c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2855c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2856c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2857c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2858c2c66affSColin Finck IN ULONG FileAttributes, 2859c2c66affSColin Finck IN ULONG ShareAccess, 2860c2c66affSColin Finck IN ULONG Disposition, 2861c2c66affSColin Finck IN ULONG CreateOptions, 2862c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2863c2c66affSColin Finck IN ULONG EaLength, 2864c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2865c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2866c2c66affSColin Finck IN ULONG Options, 2867c2c66affSColin Finck IN PVOID DeviceObject) 2868c2c66affSColin Finck { 2869c2c66affSColin Finck ULONG Flags = 0; 2870c2c66affSColin Finck 2871c2c66affSColin Finck PAGED_CODE(); 2872c2c66affSColin Finck 2873c2c66affSColin Finck /* Check if we were passed a device to send the create request to*/ 2874c2c66affSColin Finck if (DeviceObject) 2875c2c66affSColin Finck { 2876c2c66affSColin Finck /* We'll tag this request into a file object extension */ 2877c2c66affSColin Finck Flags = (IOP_CREATE_FILE_OBJECT_EXTENSION | IOP_USE_TOP_LEVEL_DEVICE_HINT); 2878c2c66affSColin Finck } 2879c2c66affSColin Finck 2880c2c66affSColin Finck return IopCreateFile(FileHandle, 2881c2c66affSColin Finck DesiredAccess, 2882c2c66affSColin Finck ObjectAttributes, 2883c2c66affSColin Finck IoStatusBlock, 2884c2c66affSColin Finck AllocationSize, 2885c2c66affSColin Finck FileAttributes, 2886c2c66affSColin Finck ShareAccess, 2887c2c66affSColin Finck Disposition, 2888c2c66affSColin Finck CreateOptions, 2889c2c66affSColin Finck EaBuffer, 2890c2c66affSColin Finck EaLength, 2891c2c66affSColin Finck CreateFileType, 2892c2c66affSColin Finck ExtraCreateParameters, 2893c2c66affSColin Finck Options | IO_NO_PARAMETER_CHECKING, 2894c2c66affSColin Finck Flags, 2895c2c66affSColin Finck DeviceObject); 2896c2c66affSColin Finck } 2897c2c66affSColin Finck 2898c2c66affSColin Finck /* 2899c2c66affSColin Finck * @implemented 2900c2c66affSColin Finck */ 2901c2c66affSColin Finck PFILE_OBJECT 2902c2c66affSColin Finck NTAPI 2903c2c66affSColin Finck IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL, 2904c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL, 2905c2c66affSColin Finck OUT PHANDLE FileObjectHandle OPTIONAL) 2906c2c66affSColin Finck { 2907c2c66affSColin Finck PFILE_OBJECT CreatedFileObject; 2908c2c66affSColin Finck NTSTATUS Status; 2909c2c66affSColin Finck HANDLE FileHandle; 2910c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 2911c2c66affSColin Finck PAGED_CODE(); 2912c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 2913c2c66affSColin Finck 2914c2c66affSColin Finck /* Choose Device Object */ 2915c2c66affSColin Finck if (FileObject) DeviceObject = FileObject->DeviceObject; 2916c2c66affSColin Finck 2917c2c66affSColin Finck /* Reference the device object and initialize attributes */ 2918c2c66affSColin Finck InterlockedIncrement(&DeviceObject->ReferenceCount); 2919c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 2920c2c66affSColin Finck 2921c2c66affSColin Finck /* Create the File Object */ 2922c2c66affSColin Finck Status = ObCreateObject(KernelMode, 2923c2c66affSColin Finck IoFileObjectType, 2924c2c66affSColin Finck &ObjectAttributes, 2925c2c66affSColin Finck KernelMode, 2926c2c66affSColin Finck NULL, 2927c2c66affSColin Finck sizeof(FILE_OBJECT), 2928c2c66affSColin Finck sizeof(FILE_OBJECT), 2929c2c66affSColin Finck 0, 2930c2c66affSColin Finck (PVOID*)&CreatedFileObject); 2931c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2932c2c66affSColin Finck { 2933c2c66affSColin Finck /* Fail */ 2934c2c66affSColin Finck IopDereferenceDeviceObject(DeviceObject, FALSE); 2935c2c66affSColin Finck ExRaiseStatus(Status); 2936c2c66affSColin Finck } 2937c2c66affSColin Finck 2938c2c66affSColin Finck /* Set File Object Data */ 2939c2c66affSColin Finck RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 2940c2c66affSColin Finck CreatedFileObject->DeviceObject = DeviceObject; 2941c2c66affSColin Finck CreatedFileObject->Type = IO_TYPE_FILE; 2942c2c66affSColin Finck CreatedFileObject->Size = sizeof(FILE_OBJECT); 2943c2c66affSColin Finck CreatedFileObject->Flags = FO_STREAM_FILE; 2944c2c66affSColin Finck 2945c2c66affSColin Finck /* Initialize the wait event */ 2946c2c66affSColin Finck KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 2947c2c66affSColin Finck 2948c2c66affSColin Finck /* Insert it to create a handle for it */ 2949c2c66affSColin Finck Status = ObInsertObject(CreatedFileObject, 2950c2c66affSColin Finck NULL, 2951c2c66affSColin Finck FILE_READ_DATA, 2952c2c66affSColin Finck 1, 2953c2c66affSColin Finck (PVOID*)&CreatedFileObject, 2954c2c66affSColin Finck &FileHandle); 2955c2c66affSColin Finck if (!NT_SUCCESS(Status)) ExRaiseStatus(Status); 2956c2c66affSColin Finck 2957c2c66affSColin Finck /* Set the handle created flag */ 2958c2c66affSColin Finck CreatedFileObject->Flags |= FO_HANDLE_CREATED; 2959c2c66affSColin Finck ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 2960c2c66affSColin Finck 2961c2c66affSColin Finck /* Check if we have a VPB */ 2962c2c66affSColin Finck if (DeviceObject->Vpb) 2963c2c66affSColin Finck { 2964c2c66affSColin Finck /* Reference it */ 2965c2c66affSColin Finck InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 2966c2c66affSColin Finck } 2967c2c66affSColin Finck 2968c2c66affSColin Finck /* Check if the caller wants the handle */ 2969c2c66affSColin Finck if (FileObjectHandle) 2970c2c66affSColin Finck { 2971c2c66affSColin Finck /* Return it */ 2972c2c66affSColin Finck *FileObjectHandle = FileHandle; 2973c2c66affSColin Finck ObDereferenceObject(CreatedFileObject); 2974c2c66affSColin Finck } 2975c2c66affSColin Finck else 2976c2c66affSColin Finck { 2977c2c66affSColin Finck /* Otherwise, close it */ 2978c2c66affSColin Finck ObCloseHandle(FileHandle, KernelMode); 2979c2c66affSColin Finck } 2980c2c66affSColin Finck 2981c2c66affSColin Finck /* Return the file object */ 2982c2c66affSColin Finck return CreatedFileObject; 2983c2c66affSColin Finck } 2984c2c66affSColin Finck 2985c2c66affSColin Finck /* 2986c2c66affSColin Finck * @implemented 2987c2c66affSColin Finck */ 2988c2c66affSColin Finck PFILE_OBJECT 2989c2c66affSColin Finck NTAPI 2990c2c66affSColin Finck IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, 2991c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject) 2992c2c66affSColin Finck { 2993c2c66affSColin Finck /* Call the newer function */ 2994c2c66affSColin Finck return IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL); 2995c2c66affSColin Finck } 2996c2c66affSColin Finck 2997c2c66affSColin Finck /* 2998c2c66affSColin Finck * @implemented 2999c2c66affSColin Finck */ 3000c2c66affSColin Finck PFILE_OBJECT 3001c2c66affSColin Finck NTAPI 3002c2c66affSColin Finck IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL, 3003c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL) 3004c2c66affSColin Finck { 3005c2c66affSColin Finck PFILE_OBJECT CreatedFileObject; 3006c2c66affSColin Finck NTSTATUS Status; 3007c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 3008c2c66affSColin Finck PAGED_CODE(); 3009c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 3010c2c66affSColin Finck 3011c2c66affSColin Finck /* Choose Device Object */ 3012c2c66affSColin Finck if (FileObject) DeviceObject = FileObject->DeviceObject; 3013c2c66affSColin Finck 3014c2c66affSColin Finck /* Reference the device object and initialize attributes */ 3015c2c66affSColin Finck InterlockedIncrement(&DeviceObject->ReferenceCount); 3016c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 3017c2c66affSColin Finck 3018c2c66affSColin Finck /* Create the File Object */ 3019c2c66affSColin Finck Status = ObCreateObject(KernelMode, 3020c2c66affSColin Finck IoFileObjectType, 3021c2c66affSColin Finck &ObjectAttributes, 3022c2c66affSColin Finck KernelMode, 3023c2c66affSColin Finck NULL, 3024c2c66affSColin Finck sizeof(FILE_OBJECT), 3025c2c66affSColin Finck sizeof(FILE_OBJECT), 3026c2c66affSColin Finck 0, 3027c2c66affSColin Finck (PVOID*)&CreatedFileObject); 3028c2c66affSColin Finck if (!NT_SUCCESS(Status)) 3029c2c66affSColin Finck { 3030c2c66affSColin Finck /* Fail */ 3031c2c66affSColin Finck IopDereferenceDeviceObject(DeviceObject, FALSE); 3032c2c66affSColin Finck ExRaiseStatus(Status); 3033c2c66affSColin Finck } 3034c2c66affSColin Finck 3035c2c66affSColin Finck /* Set File Object Data */ 3036c2c66affSColin Finck RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 3037c2c66affSColin Finck CreatedFileObject->DeviceObject = DeviceObject; 3038c2c66affSColin Finck CreatedFileObject->Type = IO_TYPE_FILE; 3039c2c66affSColin Finck CreatedFileObject->Size = sizeof(FILE_OBJECT); 3040c2c66affSColin Finck CreatedFileObject->Flags = FO_STREAM_FILE; 3041c2c66affSColin Finck 3042c2c66affSColin Finck /* Initialize the wait event */ 3043c2c66affSColin Finck KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 3044c2c66affSColin Finck 3045c2c66affSColin Finck /* Destroy create information */ 3046c2c66affSColin Finck ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject)-> 3047c2c66affSColin Finck ObjectCreateInfo); 3048c2c66affSColin Finck OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL; 3049c2c66affSColin Finck 3050c2c66affSColin Finck /* Set the handle created flag */ 3051c2c66affSColin Finck CreatedFileObject->Flags |= FO_HANDLE_CREATED; 3052c2c66affSColin Finck ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 3053c2c66affSColin Finck 3054c2c66affSColin Finck /* Check if we have a VPB */ 3055c2c66affSColin Finck if (DeviceObject->Vpb) 3056c2c66affSColin Finck { 3057c2c66affSColin Finck /* Reference it */ 3058c2c66affSColin Finck InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 3059c2c66affSColin Finck } 3060c2c66affSColin Finck 3061c2c66affSColin Finck /* Return the file object */ 3062c2c66affSColin Finck return CreatedFileObject; 3063c2c66affSColin Finck } 3064c2c66affSColin Finck 3065c2c66affSColin Finck /* 3066c2c66affSColin Finck * @implemented 3067c2c66affSColin Finck */ 3068c2c66affSColin Finck PGENERIC_MAPPING 3069c2c66affSColin Finck NTAPI 3070c2c66affSColin Finck IoGetFileObjectGenericMapping(VOID) 3071c2c66affSColin Finck { 3072c2c66affSColin Finck /* Return the mapping */ 3073c2c66affSColin Finck return &IopFileMapping; 3074c2c66affSColin Finck } 3075c2c66affSColin Finck 3076c2c66affSColin Finck /* 3077c2c66affSColin Finck * @implemented 3078c2c66affSColin Finck */ 3079c2c66affSColin Finck BOOLEAN 3080c2c66affSColin Finck NTAPI 3081c2c66affSColin Finck IoIsFileOriginRemote(IN PFILE_OBJECT FileObject) 3082c2c66affSColin Finck { 3083c2c66affSColin Finck /* Return the flag status */ 3084c2c66affSColin Finck return FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 3085c2c66affSColin Finck } 3086c2c66affSColin Finck 3087c2c66affSColin Finck /* 3088c2c66affSColin Finck * @implemented 3089c2c66affSColin Finck */ 3090c2c66affSColin Finck BOOLEAN 3091c2c66affSColin Finck NTAPI 3092c2c66affSColin Finck IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, 3093c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3094c2c66affSColin Finck IN ULONG OpenOptions, 3095c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatus, 3096c2c66affSColin Finck OUT PFILE_NETWORK_OPEN_INFORMATION Buffer) 3097c2c66affSColin Finck { 3098c2c66affSColin Finck NTSTATUS Status; 3099c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 3100c2c66affSColin Finck HANDLE Handle; 3101c2c66affSColin Finck OPEN_PACKET OpenPacket; 3102c2c66affSColin Finck PAGED_CODE(); 3103c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 3104c2c66affSColin Finck 3105c2c66affSColin Finck /* Setup the Open Packet */ 3106c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 3107c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 3108c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 3109c2c66affSColin Finck OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT; 3110c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 3111c2c66affSColin Finck OpenPacket.Options = IO_FORCE_ACCESS_CHECK; 3112c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 3113c2c66affSColin Finck OpenPacket.NetworkInformation = Buffer; 3114c2c66affSColin Finck OpenPacket.QueryOnly = TRUE; 3115c2c66affSColin Finck OpenPacket.FullAttributes = TRUE; 3116c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 3117c2c66affSColin Finck 3118c2c66affSColin Finck /* 3119c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 3120c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 3121c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 3122c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 3123c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 3124c2c66affSColin Finck * by the Parse Check member. 3125c2c66affSColin Finck */ 3126c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 3127c2c66affSColin Finck NULL, 3128c2c66affSColin Finck KernelMode, 3129c2c66affSColin Finck NULL, 3130c2c66affSColin Finck DesiredAccess, 3131c2c66affSColin Finck &OpenPacket, 3132c2c66affSColin Finck &Handle); 3133c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) 3134c2c66affSColin Finck { 3135c2c66affSColin Finck /* Parse failed */ 3136c2c66affSColin Finck IoStatus->Status = Status; 3137c2c66affSColin Finck } 3138c2c66affSColin Finck else 3139c2c66affSColin Finck { 3140c2c66affSColin Finck /* Use the Io status */ 3141c2c66affSColin Finck IoStatus->Status = OpenPacket.FinalStatus; 3142c2c66affSColin Finck IoStatus->Information = OpenPacket.Information; 3143c2c66affSColin Finck } 3144c2c66affSColin Finck 3145c2c66affSColin Finck /* Return success */ 3146c2c66affSColin Finck return TRUE; 3147c2c66affSColin Finck } 3148c2c66affSColin Finck 3149c2c66affSColin Finck /* 3150c2c66affSColin Finck * @implemented 3151c2c66affSColin Finck */ 3152c2c66affSColin Finck VOID 3153c2c66affSColin Finck NTAPI 3154c2c66affSColin Finck IoUpdateShareAccess(IN PFILE_OBJECT FileObject, 3155c2c66affSColin Finck OUT PSHARE_ACCESS ShareAccess) 3156c2c66affSColin Finck { 3157c2c66affSColin Finck PAGED_CODE(); 3158c2c66affSColin Finck 3159c2c66affSColin Finck /* Check if the file has an extension */ 3160c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3161c2c66affSColin Finck { 3162c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3163c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3164c2c66affSColin Finck { 3165c2c66affSColin Finck /* Don't update share access */ 3166c2c66affSColin Finck return; 3167c2c66affSColin Finck } 3168c2c66affSColin Finck } 3169c2c66affSColin Finck 3170c2c66affSColin Finck /* Otherwise, check if there's any access present */ 3171c2c66affSColin Finck if ((FileObject->ReadAccess) || 3172c2c66affSColin Finck (FileObject->WriteAccess) || 3173c2c66affSColin Finck (FileObject->DeleteAccess)) 3174c2c66affSColin Finck { 3175c2c66affSColin Finck /* Increase the open count */ 3176c2c66affSColin Finck ShareAccess->OpenCount++; 3177c2c66affSColin Finck 3178c2c66affSColin Finck /* Add new share access */ 3179c2c66affSColin Finck ShareAccess->Readers += FileObject->ReadAccess; 3180c2c66affSColin Finck ShareAccess->Writers += FileObject->WriteAccess; 3181c2c66affSColin Finck ShareAccess->Deleters += FileObject->DeleteAccess; 3182c2c66affSColin Finck ShareAccess->SharedRead += FileObject->SharedRead; 3183c2c66affSColin Finck ShareAccess->SharedWrite += FileObject->SharedWrite; 3184c2c66affSColin Finck ShareAccess->SharedDelete += FileObject->SharedDelete; 3185c2c66affSColin Finck } 3186c2c66affSColin Finck } 3187c2c66affSColin Finck 3188c2c66affSColin Finck /* 3189c2c66affSColin Finck * @implemented 3190c2c66affSColin Finck */ 3191c2c66affSColin Finck NTSTATUS 3192c2c66affSColin Finck NTAPI 3193c2c66affSColin Finck IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, 3194c2c66affSColin Finck IN ULONG DesiredShareAccess, 3195c2c66affSColin Finck IN PFILE_OBJECT FileObject, 3196c2c66affSColin Finck IN PSHARE_ACCESS ShareAccess, 3197c2c66affSColin Finck IN BOOLEAN Update) 3198c2c66affSColin Finck { 3199c2c66affSColin Finck BOOLEAN ReadAccess; 3200c2c66affSColin Finck BOOLEAN WriteAccess; 3201c2c66affSColin Finck BOOLEAN DeleteAccess; 3202c2c66affSColin Finck BOOLEAN SharedRead; 3203c2c66affSColin Finck BOOLEAN SharedWrite; 3204c2c66affSColin Finck BOOLEAN SharedDelete; 3205c2c66affSColin Finck PAGED_CODE(); 3206c2c66affSColin Finck 3207c2c66affSColin Finck /* Get access masks */ 3208c2c66affSColin Finck ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 3209c2c66affSColin Finck WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 3210c2c66affSColin Finck DeleteAccess = (DesiredAccess & DELETE) != 0; 3211c2c66affSColin Finck 3212c2c66affSColin Finck /* Set them in the file object */ 3213c2c66affSColin Finck FileObject->ReadAccess = ReadAccess; 3214c2c66affSColin Finck FileObject->WriteAccess = WriteAccess; 3215c2c66affSColin Finck FileObject->DeleteAccess = DeleteAccess; 3216c2c66affSColin Finck 3217c2c66affSColin Finck /* Check if the file has an extension */ 3218c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3219c2c66affSColin Finck { 3220c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3221c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3222c2c66affSColin Finck { 3223c2c66affSColin Finck /* Don't check share access */ 3224c2c66affSColin Finck return STATUS_SUCCESS; 3225c2c66affSColin Finck } 3226c2c66affSColin Finck } 3227c2c66affSColin Finck 3228c2c66affSColin Finck /* Check if we have any access */ 3229c2c66affSColin Finck if ((ReadAccess) || (WriteAccess) || (DeleteAccess)) 3230c2c66affSColin Finck { 3231c2c66affSColin Finck /* Get shared access masks */ 3232c2c66affSColin Finck SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 3233c2c66affSColin Finck SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 3234c2c66affSColin Finck SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 3235c2c66affSColin Finck 3236c2c66affSColin Finck /* Set them */ 3237c2c66affSColin Finck FileObject->SharedRead = SharedRead; 3238c2c66affSColin Finck FileObject->SharedWrite = SharedWrite; 3239c2c66affSColin Finck FileObject->SharedDelete = SharedDelete; 3240c2c66affSColin Finck 3241c2c66affSColin Finck /* Check if the shared access is violated */ 3242c2c66affSColin Finck if ((ReadAccess && 3243c2c66affSColin Finck (ShareAccess->SharedRead < ShareAccess->OpenCount)) || 3244c2c66affSColin Finck (WriteAccess && 3245c2c66affSColin Finck (ShareAccess->SharedWrite < ShareAccess->OpenCount)) || 3246c2c66affSColin Finck (DeleteAccess && 3247c2c66affSColin Finck (ShareAccess->SharedDelete < ShareAccess->OpenCount)) || 3248c2c66affSColin Finck ((ShareAccess->Readers != 0) && !SharedRead) || 3249c2c66affSColin Finck ((ShareAccess->Writers != 0) && !SharedWrite) || 3250c2c66affSColin Finck ((ShareAccess->Deleters != 0) && !SharedDelete)) 3251c2c66affSColin Finck { 3252c2c66affSColin Finck /* Sharing violation, fail */ 3253c2c66affSColin Finck return STATUS_SHARING_VIOLATION; 3254c2c66affSColin Finck } 3255c2c66affSColin Finck 3256c2c66affSColin Finck /* It's not, check if caller wants us to update it */ 3257c2c66affSColin Finck if (Update) 3258c2c66affSColin Finck { 3259c2c66affSColin Finck /* Increase open count */ 3260c2c66affSColin Finck ShareAccess->OpenCount++; 3261c2c66affSColin Finck 3262c2c66affSColin Finck /* Update shared access */ 3263c2c66affSColin Finck ShareAccess->Readers += ReadAccess; 3264c2c66affSColin Finck ShareAccess->Writers += WriteAccess; 3265c2c66affSColin Finck ShareAccess->Deleters += DeleteAccess; 3266c2c66affSColin Finck ShareAccess->SharedRead += SharedRead; 3267c2c66affSColin Finck ShareAccess->SharedWrite += SharedWrite; 3268c2c66affSColin Finck ShareAccess->SharedDelete += SharedDelete; 3269c2c66affSColin Finck } 3270c2c66affSColin Finck } 3271c2c66affSColin Finck 3272c2c66affSColin Finck /* Validation successful */ 3273c2c66affSColin Finck return STATUS_SUCCESS; 3274c2c66affSColin Finck } 3275c2c66affSColin Finck 3276c2c66affSColin Finck /* 3277c2c66affSColin Finck * @implemented 3278c2c66affSColin Finck */ 3279c2c66affSColin Finck VOID 3280c2c66affSColin Finck NTAPI 3281c2c66affSColin Finck IoRemoveShareAccess(IN PFILE_OBJECT FileObject, 3282c2c66affSColin Finck IN PSHARE_ACCESS ShareAccess) 3283c2c66affSColin Finck { 3284c2c66affSColin Finck PAGED_CODE(); 3285c2c66affSColin Finck 3286c2c66affSColin Finck /* Check if the file has an extension */ 3287c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3288c2c66affSColin Finck { 3289c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3290c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3291c2c66affSColin Finck { 3292c2c66affSColin Finck /* Don't update share access */ 3293c2c66affSColin Finck return; 3294c2c66affSColin Finck } 3295c2c66affSColin Finck } 3296c2c66affSColin Finck 3297c2c66affSColin Finck /* Otherwise, check if there's any access present */ 3298c2c66affSColin Finck if ((FileObject->ReadAccess) || 3299c2c66affSColin Finck (FileObject->WriteAccess) || 3300c2c66affSColin Finck (FileObject->DeleteAccess)) 3301c2c66affSColin Finck { 3302c2c66affSColin Finck /* Decrement the open count */ 3303c2c66affSColin Finck ShareAccess->OpenCount--; 3304c2c66affSColin Finck 3305c2c66affSColin Finck /* Remove share access */ 3306c2c66affSColin Finck ShareAccess->Readers -= FileObject->ReadAccess; 3307c2c66affSColin Finck ShareAccess->Writers -= FileObject->WriteAccess; 3308c2c66affSColin Finck ShareAccess->Deleters -= FileObject->DeleteAccess; 3309c2c66affSColin Finck ShareAccess->SharedRead -= FileObject->SharedRead; 3310c2c66affSColin Finck ShareAccess->SharedWrite -= FileObject->SharedWrite; 3311c2c66affSColin Finck ShareAccess->SharedDelete -= FileObject->SharedDelete; 3312c2c66affSColin Finck } 3313c2c66affSColin Finck } 3314c2c66affSColin Finck 3315c2c66affSColin Finck /* 3316c2c66affSColin Finck * @implemented 3317c2c66affSColin Finck */ 3318c2c66affSColin Finck VOID 3319c2c66affSColin Finck NTAPI 3320c2c66affSColin Finck IoSetShareAccess(IN ACCESS_MASK DesiredAccess, 3321c2c66affSColin Finck IN ULONG DesiredShareAccess, 3322c2c66affSColin Finck IN PFILE_OBJECT FileObject, 3323c2c66affSColin Finck OUT PSHARE_ACCESS ShareAccess) 3324c2c66affSColin Finck { 3325c2c66affSColin Finck BOOLEAN ReadAccess; 3326c2c66affSColin Finck BOOLEAN WriteAccess; 3327c2c66affSColin Finck BOOLEAN DeleteAccess; 3328c2c66affSColin Finck BOOLEAN SharedRead; 3329c2c66affSColin Finck BOOLEAN SharedWrite; 3330c2c66affSColin Finck BOOLEAN SharedDelete; 3331c2c66affSColin Finck BOOLEAN Update = TRUE; 3332c2c66affSColin Finck PAGED_CODE(); 3333c2c66affSColin Finck 3334c2c66affSColin Finck ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 3335c2c66affSColin Finck WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 3336c2c66affSColin Finck DeleteAccess = (DesiredAccess & DELETE) != 0; 3337c2c66affSColin Finck 3338c2c66affSColin Finck /* Check if the file has an extension */ 3339c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3340c2c66affSColin Finck { 3341c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3342c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3343c2c66affSColin Finck { 3344c2c66affSColin Finck /* Don't update share access */ 3345c2c66affSColin Finck Update = FALSE; 3346c2c66affSColin Finck } 3347c2c66affSColin Finck } 3348c2c66affSColin Finck 3349c2c66affSColin Finck /* Update basic access */ 3350c2c66affSColin Finck FileObject->ReadAccess = ReadAccess; 3351c2c66affSColin Finck FileObject->WriteAccess = WriteAccess; 3352c2c66affSColin Finck FileObject->DeleteAccess = DeleteAccess; 3353c2c66affSColin Finck 3354c2c66affSColin Finck /* Check if we have no access as all */ 3355c2c66affSColin Finck if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess)) 3356c2c66affSColin Finck { 3357c2c66affSColin Finck /* Check if we need to update the structure */ 3358c2c66affSColin Finck if (!Update) return; 3359c2c66affSColin Finck 3360c2c66affSColin Finck /* Otherwise, clear data */ 3361c2c66affSColin Finck ShareAccess->OpenCount = 0; 3362c2c66affSColin Finck ShareAccess->Readers = 0; 3363c2c66affSColin Finck ShareAccess->Writers = 0; 3364c2c66affSColin Finck ShareAccess->Deleters = 0; 3365c2c66affSColin Finck ShareAccess->SharedRead = 0; 3366c2c66affSColin Finck ShareAccess->SharedWrite = 0; 3367c2c66affSColin Finck ShareAccess->SharedDelete = 0; 3368c2c66affSColin Finck } 3369c2c66affSColin Finck else 3370c2c66affSColin Finck { 3371c2c66affSColin Finck /* Calculate shared access */ 3372c2c66affSColin Finck SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 3373c2c66affSColin Finck SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 3374c2c66affSColin Finck SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 3375c2c66affSColin Finck 3376c2c66affSColin Finck /* Set it in the FO */ 3377c2c66affSColin Finck FileObject->SharedRead = SharedRead; 3378c2c66affSColin Finck FileObject->SharedWrite = SharedWrite; 3379c2c66affSColin Finck FileObject->SharedDelete = SharedDelete; 3380c2c66affSColin Finck 3381c2c66affSColin Finck /* Check if we need to update the structure */ 3382c2c66affSColin Finck if (!Update) return; 3383c2c66affSColin Finck 3384c2c66affSColin Finck /* Otherwise, set data */ 3385c2c66affSColin Finck ShareAccess->OpenCount = 1; 3386c2c66affSColin Finck ShareAccess->Readers = ReadAccess; 3387c2c66affSColin Finck ShareAccess->Writers = WriteAccess; 3388c2c66affSColin Finck ShareAccess->Deleters = DeleteAccess; 3389c2c66affSColin Finck ShareAccess->SharedRead = SharedRead; 3390c2c66affSColin Finck ShareAccess->SharedWrite = SharedWrite; 3391c2c66affSColin Finck ShareAccess->SharedDelete = SharedDelete; 3392c2c66affSColin Finck } 3393c2c66affSColin Finck } 3394c2c66affSColin Finck 3395c2c66affSColin Finck /* 3396c2c66affSColin Finck * @implemented 3397c2c66affSColin Finck */ 3398c2c66affSColin Finck VOID 3399c2c66affSColin Finck NTAPI 3400c2c66affSColin Finck IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject, 3401c2c66affSColin Finck IN PFILE_OBJECT FileObject) 3402c2c66affSColin Finck { 3403c2c66affSColin Finck PIRP Irp; 3404c2c66affSColin Finck KEVENT Event; 3405c2c66affSColin Finck KIRQL OldIrql; 3406c2c66affSColin Finck NTSTATUS Status; 3407c2c66affSColin Finck PIO_STACK_LOCATION Stack; 3408c2c66affSColin Finck 3409c2c66affSColin Finck /* Check if handles were already created for the 3410c2c66affSColin Finck * open file. If so, that's over. 3411c2c66affSColin Finck */ 3412c2c66affSColin Finck if (FileObject->Flags & FO_HANDLE_CREATED) 3413c2c66affSColin Finck KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN, 3414c2c66affSColin Finck (ULONG_PTR)FileObject, 3415c2c66affSColin Finck (ULONG_PTR)DeviceObject, 0, 0); 3416c2c66affSColin Finck 3417c2c66affSColin Finck /* Reset the events */ 3418c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 3419c2c66affSColin Finck KeClearEvent(&FileObject->Event); 3420c2c66affSColin Finck 3421c2c66affSColin Finck /* Allocate the IRP we'll use */ 3422c2c66affSColin Finck Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 3423c2c66affSColin Finck /* Properly set it */ 3424c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 3425c2c66affSColin Finck Irp->UserEvent = &Event; 3426c2c66affSColin Finck Irp->UserIosb = &Irp->IoStatus; 3427c2c66affSColin Finck Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 3428c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 3429c2c66affSColin Finck Irp->RequestorMode = KernelMode; 3430c2c66affSColin Finck Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 3431c2c66affSColin Finck 3432c2c66affSColin Finck Stack = IoGetNextIrpStackLocation(Irp); 3433c2c66affSColin Finck Stack->MajorFunction = IRP_MJ_CLEANUP; 3434c2c66affSColin Finck Stack->FileObject = FileObject; 3435c2c66affSColin Finck 3436c2c66affSColin Finck /* Put on top of IRPs list of the thread */ 3437c2c66affSColin Finck IopQueueIrpToThread(Irp); 3438c2c66affSColin Finck 3439c2c66affSColin Finck /* Call the driver */ 3440c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 3441c2c66affSColin Finck if (Status == STATUS_PENDING) 3442c2c66affSColin Finck { 3443c2c66affSColin Finck KeWaitForSingleObject(&Event, UserRequest, 3444c2c66affSColin Finck KernelMode, FALSE, NULL); 3445c2c66affSColin Finck } 3446c2c66affSColin Finck 3447c2c66affSColin Finck /* Remove from IRPs list */ 3448c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3449c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 3450c2c66affSColin Finck KeLowerIrql(OldIrql); 3451c2c66affSColin Finck 3452c2c66affSColin Finck /* Free the IRP */ 3453c2c66affSColin Finck IoFreeIrp(Irp); 3454c2c66affSColin Finck 3455c2c66affSColin Finck /* Clear the event */ 3456c2c66affSColin Finck KeClearEvent(&FileObject->Event); 3457c2c66affSColin Finck /* And finally, mark the open operation as canceled */ 3458c2c66affSColin Finck FileObject->Flags |= FO_FILE_OPEN_CANCELLED; 3459c2c66affSColin Finck } 3460c2c66affSColin Finck 3461c2c66affSColin Finck /* 3462c2c66affSColin Finck * @unimplemented 3463c2c66affSColin Finck */ 3464c2c66affSColin Finck NTSTATUS 3465c2c66affSColin Finck NTAPI 3466c2c66affSColin Finck IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject, 3467c2c66affSColin Finck OUT POBJECT_NAME_INFORMATION *ObjectNameInformation) 3468c2c66affSColin Finck { 3469c2c66affSColin Finck UNIMPLEMENTED; 3470c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 3471c2c66affSColin Finck } 3472c2c66affSColin Finck 3473c2c66affSColin Finck /* 3474c2c66affSColin Finck * @implemented 3475c2c66affSColin Finck */ 3476c2c66affSColin Finck NTSTATUS 3477c2c66affSColin Finck NTAPI 3478c2c66affSColin Finck IoSetFileOrigin(IN PFILE_OBJECT FileObject, 3479c2c66affSColin Finck IN BOOLEAN Remote) 3480c2c66affSColin Finck { 3481c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 3482c2c66affSColin Finck BOOLEAN FlagSet; 3483c2c66affSColin Finck 3484c2c66affSColin Finck /* Get the flag status */ 3485c2c66affSColin Finck FlagSet = FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 3486c2c66affSColin Finck 3487c2c66affSColin Finck /* Don't set the flag if it was set already, and don't remove it if it wasn't set */ 3488c2c66affSColin Finck if (Remote && !FlagSet) 3489c2c66affSColin Finck { 3490c2c66affSColin Finck /* Set the flag */ 3491c2c66affSColin Finck FileObject->Flags |= FO_REMOTE_ORIGIN; 3492c2c66affSColin Finck } 3493c2c66affSColin Finck else if (!Remote && FlagSet) 3494c2c66affSColin Finck { 3495c2c66affSColin Finck /* Remove the flag */ 3496c2c66affSColin Finck FileObject->Flags &= ~FO_REMOTE_ORIGIN; 3497c2c66affSColin Finck } 3498c2c66affSColin Finck else 3499c2c66affSColin Finck { 3500c2c66affSColin Finck /* Fail */ 3501c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER_MIX; 3502c2c66affSColin Finck } 3503c2c66affSColin Finck 3504c2c66affSColin Finck /* Return status */ 3505c2c66affSColin Finck return Status; 3506c2c66affSColin Finck } 3507c2c66affSColin Finck 3508c2c66affSColin Finck /* 3509c2c66affSColin Finck * @implemented 3510c2c66affSColin Finck */ 3511c2c66affSColin Finck NTSTATUS 3512c2c66affSColin Finck NTAPI 3513c2c66affSColin Finck NtCreateFile(PHANDLE FileHandle, 3514c2c66affSColin Finck ACCESS_MASK DesiredAccess, 3515c2c66affSColin Finck POBJECT_ATTRIBUTES ObjectAttributes, 3516c2c66affSColin Finck PIO_STATUS_BLOCK IoStatusBlock, 3517c2c66affSColin Finck PLARGE_INTEGER AllocateSize, 3518c2c66affSColin Finck ULONG FileAttributes, 3519c2c66affSColin Finck ULONG ShareAccess, 3520c2c66affSColin Finck ULONG CreateDisposition, 3521c2c66affSColin Finck ULONG CreateOptions, 3522c2c66affSColin Finck PVOID EaBuffer, 3523c2c66affSColin Finck ULONG EaLength) 3524c2c66affSColin Finck { 3525c2c66affSColin Finck /* Call the I/O Function */ 3526c2c66affSColin Finck return IoCreateFile(FileHandle, 3527c2c66affSColin Finck DesiredAccess, 3528c2c66affSColin Finck ObjectAttributes, 3529c2c66affSColin Finck IoStatusBlock, 3530c2c66affSColin Finck AllocateSize, 3531c2c66affSColin Finck FileAttributes, 3532c2c66affSColin Finck ShareAccess, 3533c2c66affSColin Finck CreateDisposition, 3534c2c66affSColin Finck CreateOptions, 3535c2c66affSColin Finck EaBuffer, 3536c2c66affSColin Finck EaLength, 3537c2c66affSColin Finck CreateFileTypeNone, 3538c2c66affSColin Finck NULL, 3539c2c66affSColin Finck 0); 3540c2c66affSColin Finck } 3541c2c66affSColin Finck 3542c2c66affSColin Finck NTSTATUS 3543c2c66affSColin Finck NTAPI 3544c2c66affSColin Finck NtCreateMailslotFile(OUT PHANDLE FileHandle, 3545c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3546c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 3547c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 3548c2c66affSColin Finck IN ULONG CreateOptions, 3549c2c66affSColin Finck IN ULONG MailslotQuota, 3550c2c66affSColin Finck IN ULONG MaxMessageSize, 3551c2c66affSColin Finck IN PLARGE_INTEGER TimeOut) 3552c2c66affSColin Finck { 3553c2c66affSColin Finck MAILSLOT_CREATE_PARAMETERS Buffer; 3554c2c66affSColin Finck PAGED_CODE(); 3555c2c66affSColin Finck 3556c2c66affSColin Finck /* Check for Timeout */ 3557c2c66affSColin Finck if (TimeOut) 3558c2c66affSColin Finck { 3559c2c66affSColin Finck /* check if the call came from user mode */ 3560c2c66affSColin Finck if (KeGetPreviousMode() != KernelMode) 3561c2c66affSColin Finck { 3562c2c66affSColin Finck /* Enter SEH for Probe */ 3563c2c66affSColin Finck _SEH2_TRY 3564c2c66affSColin Finck { 3565c2c66affSColin Finck /* Probe the timeout */ 3566c2c66affSColin Finck Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut); 3567c2c66affSColin Finck } 3568c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3569c2c66affSColin Finck { 3570c2c66affSColin Finck /* Return the exception code */ 3571c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3572c2c66affSColin Finck } 3573c2c66affSColin Finck _SEH2_END; 3574c2c66affSColin Finck } 3575c2c66affSColin Finck else 3576c2c66affSColin Finck { 3577c2c66affSColin Finck /* Otherwise, capture directly */ 3578c2c66affSColin Finck Buffer.ReadTimeout = *TimeOut; 3579c2c66affSColin Finck } 3580c2c66affSColin Finck 3581c2c66affSColin Finck /* Set the correct setting */ 3582c2c66affSColin Finck Buffer.TimeoutSpecified = TRUE; 3583c2c66affSColin Finck } 3584c2c66affSColin Finck else 3585c2c66affSColin Finck { 3586c2c66affSColin Finck /* Tell the FSD we don't have a timeout */ 3587c2c66affSColin Finck Buffer.TimeoutSpecified = FALSE; 3588c2c66affSColin Finck } 3589c2c66affSColin Finck 3590c2c66affSColin Finck /* Set Settings */ 3591c2c66affSColin Finck Buffer.MailslotQuota = MailslotQuota; 3592c2c66affSColin Finck Buffer.MaximumMessageSize = MaxMessageSize; 3593c2c66affSColin Finck 3594c2c66affSColin Finck /* Call I/O */ 3595c2c66affSColin Finck return IoCreateFile(FileHandle, 3596c2c66affSColin Finck DesiredAccess, 3597c2c66affSColin Finck ObjectAttributes, 3598c2c66affSColin Finck IoStatusBlock, 3599c2c66affSColin Finck NULL, 3600c2c66affSColin Finck 0, 3601c2c66affSColin Finck FILE_SHARE_READ | FILE_SHARE_WRITE, 3602c2c66affSColin Finck FILE_CREATE, 3603c2c66affSColin Finck CreateOptions, 3604c2c66affSColin Finck NULL, 3605c2c66affSColin Finck 0, 3606c2c66affSColin Finck CreateFileTypeMailslot, 3607c2c66affSColin Finck (PVOID)&Buffer, 3608c2c66affSColin Finck 0); 3609c2c66affSColin Finck } 3610c2c66affSColin Finck 3611c2c66affSColin Finck NTSTATUS 3612c2c66affSColin Finck NTAPI 3613c2c66affSColin Finck NtCreateNamedPipeFile(OUT PHANDLE FileHandle, 3614c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3615c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 3616c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 3617c2c66affSColin Finck IN ULONG ShareAccess, 3618c2c66affSColin Finck IN ULONG CreateDisposition, 3619c2c66affSColin Finck IN ULONG CreateOptions, 3620c2c66affSColin Finck IN ULONG NamedPipeType, 3621c2c66affSColin Finck IN ULONG ReadMode, 3622c2c66affSColin Finck IN ULONG CompletionMode, 3623c2c66affSColin Finck IN ULONG MaximumInstances, 3624c2c66affSColin Finck IN ULONG InboundQuota, 3625c2c66affSColin Finck IN ULONG OutboundQuota, 3626c2c66affSColin Finck IN PLARGE_INTEGER DefaultTimeout) 3627c2c66affSColin Finck { 3628c2c66affSColin Finck NAMED_PIPE_CREATE_PARAMETERS Buffer; 3629c2c66affSColin Finck PAGED_CODE(); 3630c2c66affSColin Finck 3631c2c66affSColin Finck /* Check for Timeout */ 3632c2c66affSColin Finck if (DefaultTimeout) 3633c2c66affSColin Finck { 3634c2c66affSColin Finck /* check if the call came from user mode */ 3635c2c66affSColin Finck if (KeGetPreviousMode() != KernelMode) 3636c2c66affSColin Finck { 3637c2c66affSColin Finck /* Enter SEH for Probe */ 3638c2c66affSColin Finck _SEH2_TRY 3639c2c66affSColin Finck { 3640c2c66affSColin Finck /* Probe the timeout */ 3641c2c66affSColin Finck Buffer.DefaultTimeout = 3642c2c66affSColin Finck ProbeForReadLargeInteger(DefaultTimeout); 3643c2c66affSColin Finck } 3644c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3645c2c66affSColin Finck { 3646c2c66affSColin Finck /* Return the exception code */ 3647c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3648c2c66affSColin Finck } 3649c2c66affSColin Finck _SEH2_END; 3650c2c66affSColin Finck } 3651c2c66affSColin Finck else 3652c2c66affSColin Finck { 3653c2c66affSColin Finck /* Otherwise, capture directly */ 3654c2c66affSColin Finck Buffer.DefaultTimeout = *DefaultTimeout; 3655c2c66affSColin Finck } 3656c2c66affSColin Finck 3657c2c66affSColin Finck /* Set the correct setting */ 3658c2c66affSColin Finck Buffer.TimeoutSpecified = TRUE; 3659c2c66affSColin Finck } 3660c2c66affSColin Finck else 3661c2c66affSColin Finck { 3662c2c66affSColin Finck /* Tell the FSD we don't have a timeout */ 3663c2c66affSColin Finck Buffer.TimeoutSpecified = FALSE; 3664c2c66affSColin Finck } 3665c2c66affSColin Finck 3666c2c66affSColin Finck /* Set Settings */ 3667c2c66affSColin Finck Buffer.NamedPipeType = NamedPipeType; 3668c2c66affSColin Finck Buffer.ReadMode = ReadMode; 3669c2c66affSColin Finck Buffer.CompletionMode = CompletionMode; 3670c2c66affSColin Finck Buffer.MaximumInstances = MaximumInstances; 3671c2c66affSColin Finck Buffer.InboundQuota = InboundQuota; 3672c2c66affSColin Finck Buffer.OutboundQuota = OutboundQuota; 3673c2c66affSColin Finck 3674c2c66affSColin Finck /* Call I/O */ 3675c2c66affSColin Finck return IoCreateFile(FileHandle, 3676c2c66affSColin Finck DesiredAccess, 3677c2c66affSColin Finck ObjectAttributes, 3678c2c66affSColin Finck IoStatusBlock, 3679c2c66affSColin Finck NULL, 3680c2c66affSColin Finck 0, 3681c2c66affSColin Finck ShareAccess, 3682c2c66affSColin Finck CreateDisposition, 3683c2c66affSColin Finck CreateOptions, 3684c2c66affSColin Finck NULL, 3685c2c66affSColin Finck 0, 3686c2c66affSColin Finck CreateFileTypeNamedPipe, 3687c2c66affSColin Finck (PVOID)&Buffer, 3688c2c66affSColin Finck 0); 3689c2c66affSColin Finck } 3690c2c66affSColin Finck 3691c2c66affSColin Finck NTSTATUS 3692c2c66affSColin Finck NTAPI 3693c2c66affSColin Finck NtFlushWriteBuffer(VOID) 3694c2c66affSColin Finck { 3695c2c66affSColin Finck PAGED_CODE(); 3696c2c66affSColin Finck 3697c2c66affSColin Finck /* Call the kernel */ 3698c2c66affSColin Finck KeFlushWriteBuffer(); 3699c2c66affSColin Finck return STATUS_SUCCESS; 3700c2c66affSColin Finck } 3701c2c66affSColin Finck 3702c2c66affSColin Finck /* 3703c2c66affSColin Finck * @implemented 3704c2c66affSColin Finck */ 3705c2c66affSColin Finck NTSTATUS 3706c2c66affSColin Finck NTAPI 3707c2c66affSColin Finck NtOpenFile(OUT PHANDLE FileHandle, 3708c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3709c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 3710c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 3711c2c66affSColin Finck IN ULONG ShareAccess, 3712c2c66affSColin Finck IN ULONG OpenOptions) 3713c2c66affSColin Finck { 3714c2c66affSColin Finck /* Call the I/O Function */ 3715c2c66affSColin Finck return IoCreateFile(FileHandle, 3716c2c66affSColin Finck DesiredAccess, 3717c2c66affSColin Finck ObjectAttributes, 3718c2c66affSColin Finck IoStatusBlock, 3719c2c66affSColin Finck NULL, 3720c2c66affSColin Finck 0, 3721c2c66affSColin Finck ShareAccess, 3722c2c66affSColin Finck FILE_OPEN, 3723c2c66affSColin Finck OpenOptions, 3724c2c66affSColin Finck NULL, 3725c2c66affSColin Finck 0, 3726c2c66affSColin Finck CreateFileTypeNone, 3727c2c66affSColin Finck NULL, 3728c2c66affSColin Finck 0); 3729c2c66affSColin Finck } 3730c2c66affSColin Finck 3731c2c66affSColin Finck NTSTATUS 3732c2c66affSColin Finck NTAPI 3733c2c66affSColin Finck NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 3734c2c66affSColin Finck OUT PFILE_BASIC_INFORMATION FileInformation) 3735c2c66affSColin Finck { 3736c2c66affSColin Finck /* Call the internal helper API */ 3737c2c66affSColin Finck return IopQueryAttributesFile(ObjectAttributes, 3738c2c66affSColin Finck FileBasicInformation, 3739c2c66affSColin Finck sizeof(FILE_BASIC_INFORMATION), 3740c2c66affSColin Finck FileInformation); 3741c2c66affSColin Finck } 3742c2c66affSColin Finck 3743c2c66affSColin Finck NTSTATUS 3744c2c66affSColin Finck NTAPI 3745c2c66affSColin Finck NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 3746c2c66affSColin Finck OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation) 3747c2c66affSColin Finck { 3748c2c66affSColin Finck /* Call the internal helper API */ 3749c2c66affSColin Finck return IopQueryAttributesFile(ObjectAttributes, 3750c2c66affSColin Finck FileNetworkOpenInformation, 3751c2c66affSColin Finck sizeof(FILE_NETWORK_OPEN_INFORMATION), 3752c2c66affSColin Finck FileInformation); 3753c2c66affSColin Finck } 3754c2c66affSColin Finck 3755c2c66affSColin Finck /** 3756c2c66affSColin Finck * @name NtCancelIoFile 3757c2c66affSColin Finck * 3758c2c66affSColin Finck * Cancel all pending I/O operations in the current thread for specified 3759c2c66affSColin Finck * file object. 3760c2c66affSColin Finck * 3761c2c66affSColin Finck * @param FileHandle 3762c2c66affSColin Finck * Handle to file object to cancel requests for. No specific 3763c2c66affSColin Finck * access rights are needed. 3764c2c66affSColin Finck * @param IoStatusBlock 3765c2c66affSColin Finck * Pointer to status block which is filled with final completition 3766c2c66affSColin Finck * status on successful return. 3767c2c66affSColin Finck * 3768c2c66affSColin Finck * @return Status. 3769c2c66affSColin Finck * 3770c2c66affSColin Finck * @implemented 3771c2c66affSColin Finck */ 3772c2c66affSColin Finck NTSTATUS 3773c2c66affSColin Finck NTAPI 3774c2c66affSColin Finck NtCancelIoFile(IN HANDLE FileHandle, 3775c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock) 3776c2c66affSColin Finck { 3777c2c66affSColin Finck PFILE_OBJECT FileObject; 3778c2c66affSColin Finck PETHREAD Thread; 3779c2c66affSColin Finck PIRP Irp; 3780c2c66affSColin Finck KIRQL OldIrql; 3781c2c66affSColin Finck BOOLEAN OurIrpsInList = FALSE; 3782c2c66affSColin Finck LARGE_INTEGER Interval; 3783c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 3784c2c66affSColin Finck NTSTATUS Status; 3785c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry; 3786c2c66affSColin Finck PAGED_CODE(); 3787c2c66affSColin Finck IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 3788c2c66affSColin Finck 3789c2c66affSColin Finck /* Check the previous mode */ 3790c2c66affSColin Finck if (PreviousMode != KernelMode) 3791c2c66affSColin Finck { 3792c2c66affSColin Finck /* Enter SEH for probing */ 3793c2c66affSColin Finck _SEH2_TRY 3794c2c66affSColin Finck { 3795c2c66affSColin Finck /* Probe the I/O Status Block */ 3796c2c66affSColin Finck ProbeForWriteIoStatusBlock(IoStatusBlock); 3797c2c66affSColin Finck } 3798c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3799c2c66affSColin Finck { 3800c2c66affSColin Finck /* Return the exception code */ 3801c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3802c2c66affSColin Finck } 3803c2c66affSColin Finck _SEH2_END; 3804c2c66affSColin Finck } 3805c2c66affSColin Finck 3806c2c66affSColin Finck /* Reference the file object */ 3807c2c66affSColin Finck Status = ObReferenceObjectByHandle(FileHandle, 3808c2c66affSColin Finck 0, 3809c2c66affSColin Finck IoFileObjectType, 3810c2c66affSColin Finck PreviousMode, 3811c2c66affSColin Finck (PVOID*)&FileObject, 3812c2c66affSColin Finck NULL); 3813c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 3814c2c66affSColin Finck 3815c2c66affSColin Finck /* IRP cancellations are synchronized at APC_LEVEL. */ 3816c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3817c2c66affSColin Finck 3818c2c66affSColin Finck /* Get the current thread */ 3819c2c66affSColin Finck Thread = PsGetCurrentThread(); 3820c2c66affSColin Finck 3821c2c66affSColin Finck /* Update the operation counts */ 3822c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 3823c2c66affSColin Finck 3824c2c66affSColin Finck /* Loop the list */ 3825c2c66affSColin Finck ListHead = &Thread->IrpList; 3826c2c66affSColin Finck NextEntry = ListHead->Flink; 3827c2c66affSColin Finck while (ListHead != NextEntry) 3828c2c66affSColin Finck { 3829c2c66affSColin Finck /* Get the IRP and check if the File Object matches */ 3830c2c66affSColin Finck Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 3831c2c66affSColin Finck if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 3832c2c66affSColin Finck { 3833c2c66affSColin Finck /* Cancel this IRP and keep looping */ 3834c2c66affSColin Finck IoCancelIrp(Irp); 3835c2c66affSColin Finck OurIrpsInList = TRUE; 3836c2c66affSColin Finck } 3837c2c66affSColin Finck 3838c2c66affSColin Finck /* Go to the next entry */ 3839c2c66affSColin Finck NextEntry = NextEntry->Flink; 3840c2c66affSColin Finck } 3841c2c66affSColin Finck 3842c2c66affSColin Finck /* Lower the IRQL */ 3843c2c66affSColin Finck KeLowerIrql(OldIrql); 3844c2c66affSColin Finck 3845c2c66affSColin Finck /* Check if we had found an IRP */ 3846c2c66affSColin Finck if (OurIrpsInList) 3847c2c66affSColin Finck { 3848c2c66affSColin Finck /* Setup a 10ms wait */ 3849c2c66affSColin Finck Interval.QuadPart = -100000; 3850c2c66affSColin Finck 3851c2c66affSColin Finck /* Start looping */ 3852c2c66affSColin Finck while (OurIrpsInList) 3853c2c66affSColin Finck { 3854c2c66affSColin Finck /* Do the wait */ 3855c2c66affSColin Finck KeDelayExecutionThread(KernelMode, FALSE, &Interval); 3856c2c66affSColin Finck OurIrpsInList = FALSE; 3857c2c66affSColin Finck 3858c2c66affSColin Finck /* Raise IRQL */ 3859c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3860c2c66affSColin Finck 3861c2c66affSColin Finck /* Now loop the list again */ 3862c2c66affSColin Finck NextEntry = ListHead->Flink; 3863c2c66affSColin Finck while (NextEntry != ListHead) 3864c2c66affSColin Finck { 3865c2c66affSColin Finck /* Get the IRP and check if the File Object matches */ 3866c2c66affSColin Finck Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 3867c2c66affSColin Finck if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 3868c2c66affSColin Finck { 3869c2c66affSColin Finck /* Keep looping */ 3870c2c66affSColin Finck OurIrpsInList = TRUE; 3871c2c66affSColin Finck break; 3872c2c66affSColin Finck } 3873c2c66affSColin Finck 3874c2c66affSColin Finck /* Go to the next entry */ 3875c2c66affSColin Finck NextEntry = NextEntry->Flink; 3876c2c66affSColin Finck } 3877c2c66affSColin Finck 3878c2c66affSColin Finck /* Lower the IRQL */ 3879c2c66affSColin Finck KeLowerIrql(OldIrql); 3880c2c66affSColin Finck } 3881c2c66affSColin Finck } 3882c2c66affSColin Finck 3883c2c66affSColin Finck /* Enter SEH for writing back the I/O Status */ 3884c2c66affSColin Finck _SEH2_TRY 3885c2c66affSColin Finck { 3886c2c66affSColin Finck /* Write success */ 3887c2c66affSColin Finck IoStatusBlock->Status = STATUS_SUCCESS; 3888c2c66affSColin Finck IoStatusBlock->Information = 0; 3889c2c66affSColin Finck } 3890c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3891c2c66affSColin Finck { 3892c2c66affSColin Finck /* Ignore exception */ 3893c2c66affSColin Finck } 3894c2c66affSColin Finck _SEH2_END; 3895c2c66affSColin Finck 3896c2c66affSColin Finck /* Dereference the file object and return success */ 3897c2c66affSColin Finck ObDereferenceObject(FileObject); 3898c2c66affSColin Finck return STATUS_SUCCESS; 3899c2c66affSColin Finck } 3900c2c66affSColin Finck 3901c2c66affSColin Finck /* 3902c2c66affSColin Finck * @implemented 3903c2c66affSColin Finck */ 3904c2c66affSColin Finck NTSTATUS 3905c2c66affSColin Finck NTAPI 3906c2c66affSColin Finck NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes) 3907c2c66affSColin Finck { 3908c2c66affSColin Finck NTSTATUS Status; 3909c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 3910c2c66affSColin Finck HANDLE Handle; 3911c2c66affSColin Finck KPROCESSOR_MODE AccessMode = KeGetPreviousMode(); 3912c2c66affSColin Finck OPEN_PACKET OpenPacket; 3913c2c66affSColin Finck PAGED_CODE(); 3914c2c66affSColin Finck IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName); 3915c2c66affSColin Finck 3916c2c66affSColin Finck /* Setup the Open Packet */ 3917c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 3918c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 3919c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 3920c2c66affSColin Finck OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE; 3921c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | 3922c2c66affSColin Finck FILE_SHARE_WRITE | 3923c2c66affSColin Finck FILE_SHARE_DELETE; 3924c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 3925c2c66affSColin Finck OpenPacket.DeleteOnly = TRUE; 3926c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 3927c2c66affSColin Finck 3928c2c66affSColin Finck /* Update the operation counts */ 3929c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 3930c2c66affSColin Finck 3931c2c66affSColin Finck /* 3932c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 3933c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 3934c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 3935c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 3936c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 3937c2c66affSColin Finck * by the Parse Check member. 3938c2c66affSColin Finck */ 3939c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 3940c2c66affSColin Finck NULL, 3941c2c66affSColin Finck AccessMode, 3942c2c66affSColin Finck NULL, 3943c2c66affSColin Finck DELETE, 3944c2c66affSColin Finck &OpenPacket, 3945c2c66affSColin Finck &Handle); 3946c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) return Status; 3947c2c66affSColin Finck 3948c2c66affSColin Finck /* Retrn the Io status */ 3949c2c66affSColin Finck return OpenPacket.FinalStatus; 3950c2c66affSColin Finck } 3951c2c66affSColin Finck 3952c2c66affSColin Finck /* EOF */ 3953