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 1872abfddca8SPierre Schweitzer IopQueryName(IN PVOID ObjectBody, 1873abfddca8SPierre Schweitzer IN BOOLEAN HasName, 1874abfddca8SPierre Schweitzer OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 1875abfddca8SPierre Schweitzer IN ULONG Length, 1876abfddca8SPierre Schweitzer OUT PULONG ReturnLength, 1877abfddca8SPierre Schweitzer IN KPROCESSOR_MODE PreviousMode) 1878abfddca8SPierre Schweitzer { 1879abfddca8SPierre Schweitzer return IopQueryNameInternal(ObjectBody, 1880abfddca8SPierre Schweitzer HasName, 1881abfddca8SPierre Schweitzer FALSE, 1882abfddca8SPierre Schweitzer ObjectNameInfo, 1883abfddca8SPierre Schweitzer Length, 1884abfddca8SPierre Schweitzer ReturnLength, 1885abfddca8SPierre Schweitzer PreviousMode); 1886abfddca8SPierre Schweitzer } 1887abfddca8SPierre Schweitzer 1888abfddca8SPierre Schweitzer NTSTATUS 1889abfddca8SPierre Schweitzer NTAPI 18901348f62fSPierre Schweitzer IopQueryNameInternal(IN PVOID ObjectBody, 1891c2c66affSColin Finck IN BOOLEAN HasName, 1892abfddca8SPierre Schweitzer IN BOOLEAN QueryDosName, 1893c2c66affSColin Finck OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 1894c2c66affSColin Finck IN ULONG Length, 1895c2c66affSColin Finck OUT PULONG ReturnLength, 1896c2c66affSColin Finck IN KPROCESSOR_MODE PreviousMode) 1897c2c66affSColin Finck { 1898c2c66affSColin Finck POBJECT_NAME_INFORMATION LocalInfo; 1899c2c66affSColin Finck PFILE_NAME_INFORMATION LocalFileInfo; 1900c2c66affSColin Finck PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 1901c2c66affSColin Finck ULONG LocalReturnLength, FileLength; 1902c2c66affSColin Finck BOOLEAN LengthMismatch = FALSE; 1903c2c66affSColin Finck NTSTATUS Status; 1904c2c66affSColin Finck PWCHAR p; 1905c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 1906c2c66affSColin Finck 1907c2c66affSColin Finck /* Validate length */ 1908c2c66affSColin Finck if (Length < sizeof(OBJECT_NAME_INFORMATION)) 1909c2c66affSColin Finck { 1910c2c66affSColin Finck /* Wrong length, fail */ 1911c2c66affSColin Finck *ReturnLength = sizeof(OBJECT_NAME_INFORMATION); 1912c2c66affSColin Finck return STATUS_INFO_LENGTH_MISMATCH; 1913c2c66affSColin Finck } 1914c2c66affSColin Finck 1915abfddca8SPierre Schweitzer if (QueryDosName) return STATUS_NOT_IMPLEMENTED; 1916abfddca8SPierre Schweitzer 1917c2c66affSColin Finck /* Allocate Buffer */ 1918c2c66affSColin Finck LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO); 1919c2c66affSColin Finck if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES; 1920c2c66affSColin Finck 1921c2c66affSColin Finck /* Query the name */ 1922c2c66affSColin Finck Status = ObQueryNameString(FileObject->DeviceObject, 1923c2c66affSColin Finck LocalInfo, 1924c2c66affSColin Finck Length, 1925c2c66affSColin Finck &LocalReturnLength); 1926c2c66affSColin Finck if (!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) 1927c2c66affSColin Finck { 1928c2c66affSColin Finck /* Free the buffer and fail */ 1929c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 1930c2c66affSColin Finck return Status; 1931c2c66affSColin Finck } 1932c2c66affSColin Finck 1933c2c66affSColin Finck /* Copy the information */ 1934c2c66affSColin Finck RtlCopyMemory(ObjectNameInfo, 1935c2c66affSColin Finck LocalInfo, 1936c2c66affSColin Finck (LocalReturnLength > Length) ? 1937c2c66affSColin Finck Length : LocalReturnLength); 1938c2c66affSColin Finck 1939c2c66affSColin Finck /* Set buffer pointer */ 1940c2c66affSColin Finck p = (PWCHAR)(ObjectNameInfo + 1); 1941c2c66affSColin Finck ObjectNameInfo->Name.Buffer = p; 1942c2c66affSColin Finck 1943c2c66affSColin Finck /* Advance in buffer */ 1944c2c66affSColin Finck p += (LocalInfo->Name.Length / sizeof(WCHAR)); 1945c2c66affSColin Finck 1946c2c66affSColin Finck /* Check if this already filled our buffer */ 1947c2c66affSColin Finck if (LocalReturnLength > Length) 1948c2c66affSColin Finck { 1949c2c66affSColin Finck /* Set the length mismatch to true, so that we can return 1950c2c66affSColin Finck * the proper buffer size to the caller later 1951c2c66affSColin Finck */ 1952c2c66affSColin Finck LengthMismatch = TRUE; 1953c2c66affSColin Finck 1954c2c66affSColin Finck /* Save the initial buffer length value */ 1955c2c66affSColin Finck *ReturnLength = LocalReturnLength; 1956c2c66affSColin Finck } 1957c2c66affSColin Finck 1958c2c66affSColin Finck /* Now get the file name buffer and check the length needed */ 1959c2c66affSColin Finck LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo; 1960c2c66affSColin Finck FileLength = Length - 1961c2c66affSColin Finck LocalReturnLength + 1962c2c66affSColin Finck FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 1963c2c66affSColin Finck 1964c2c66affSColin Finck /* Query the File name */ 1965a1401a75SPierre Schweitzer if (PreviousMode == KernelMode && 1966a1401a75SPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 1967a1401a75SPierre Schweitzer { 1968a1401a75SPierre Schweitzer Status = IopGetFileInformation(FileObject, 1969a1401a75SPierre Schweitzer LengthMismatch ? Length : FileLength, 1970a1401a75SPierre Schweitzer FileNameInformation, 1971a1401a75SPierre Schweitzer LocalFileInfo, 1972a1401a75SPierre Schweitzer &LocalReturnLength); 1973a1401a75SPierre Schweitzer } 1974a1401a75SPierre Schweitzer else 1975a1401a75SPierre Schweitzer { 1976c2c66affSColin Finck Status = IoQueryFileInformation(FileObject, 1977c2c66affSColin Finck FileNameInformation, 1978c2c66affSColin Finck LengthMismatch ? Length : FileLength, 1979c2c66affSColin Finck LocalFileInfo, 1980c2c66affSColin Finck &LocalReturnLength); 1981a1401a75SPierre Schweitzer } 1982c2c66affSColin Finck if (NT_ERROR(Status)) 1983c2c66affSColin Finck { 1984*769157f6SPierre Schweitzer /* Allow status that would mean it's not implemented in the storage stack */ 1985*769157f6SPierre Schweitzer if (Status != STATUS_INVALID_PARAMETER && Status != STATUS_INVALID_DEVICE_REQUEST && 1986*769157f6SPierre Schweitzer Status != STATUS_NOT_IMPLEMENTED && Status != STATUS_INVALID_INFO_CLASS) 1987*769157f6SPierre Schweitzer { 1988c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 1989c2c66affSColin Finck return Status; 1990c2c66affSColin Finck } 1991c2c66affSColin Finck 1992*769157f6SPierre Schweitzer /* In such case, zero output */ 1993*769157f6SPierre Schweitzer LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 1994*769157f6SPierre Schweitzer LocalFileInfo->FileNameLength = 0; 1995*769157f6SPierre Schweitzer LocalFileInfo->FileName[0] = OBJ_NAME_PATH_SEPARATOR; 1996*769157f6SPierre Schweitzer } 1997*769157f6SPierre Schweitzer else 1998*769157f6SPierre Schweitzer { 1999*769157f6SPierre Schweitzer /* We'll at least return the name length */ 2000*769157f6SPierre Schweitzer if (LocalReturnLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName)) 2001*769157f6SPierre Schweitzer { 2002*769157f6SPierre Schweitzer LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 2003*769157f6SPierre Schweitzer } 2004*769157f6SPierre Schweitzer } 2005*769157f6SPierre Schweitzer 2006c2c66affSColin Finck /* If the provided buffer is too small, return the required size */ 2007c2c66affSColin Finck if (LengthMismatch) 2008c2c66affSColin Finck { 2009c2c66affSColin Finck /* Add the required length */ 2010c2c66affSColin Finck *ReturnLength += LocalFileInfo->FileNameLength; 2011c2c66affSColin Finck 2012c2c66affSColin Finck /* Free the allocated buffer and return failure */ 2013c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 2014c2c66affSColin Finck return STATUS_BUFFER_OVERFLOW; 2015c2c66affSColin Finck } 2016c2c66affSColin Finck 2017c2c66affSColin Finck /* Now calculate the new lengths left */ 2018c2c66affSColin Finck FileLength = LocalReturnLength - 2019c2c66affSColin Finck FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 2020c2c66affSColin Finck LocalReturnLength = (ULONG)((ULONG_PTR)p - 2021c2c66affSColin Finck (ULONG_PTR)ObjectNameInfo + 2022c2c66affSColin Finck LocalFileInfo->FileNameLength); 2023c2c66affSColin Finck 202446bda8a4SPierre Schweitzer /* Don't copy the name if it's not valid */ 202546bda8a4SPierre Schweitzer if (LocalFileInfo->FileName[0] != OBJ_NAME_PATH_SEPARATOR) 202646bda8a4SPierre Schweitzer { 202746bda8a4SPierre Schweitzer /* Free the allocated buffer and return failure */ 202846bda8a4SPierre Schweitzer ExFreePoolWithTag(LocalInfo, TAG_IO); 202946bda8a4SPierre Schweitzer return STATUS_OBJECT_PATH_INVALID; 203046bda8a4SPierre Schweitzer } 203146bda8a4SPierre Schweitzer 2032c2c66affSColin Finck /* Write the Name and null-terminate it */ 2033c2c66affSColin Finck RtlCopyMemory(p, LocalFileInfo->FileName, FileLength); 2034c2c66affSColin Finck p += (FileLength / sizeof(WCHAR)); 2035c2c66affSColin Finck *p = UNICODE_NULL; 2036c2c66affSColin Finck LocalReturnLength += sizeof(UNICODE_NULL); 2037c2c66affSColin Finck 2038c2c66affSColin Finck /* Return the length needed */ 2039c2c66affSColin Finck *ReturnLength = LocalReturnLength; 2040c2c66affSColin Finck 2041c2c66affSColin Finck /* Setup the length and maximum length */ 2042c2c66affSColin Finck FileLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo); 2043c2c66affSColin Finck ObjectNameInfo->Name.Length = (USHORT)FileLength - 2044c2c66affSColin Finck sizeof(OBJECT_NAME_INFORMATION); 2045c2c66affSColin Finck ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length + 2046c2c66affSColin Finck sizeof(UNICODE_NULL); 2047c2c66affSColin Finck 2048c2c66affSColin Finck /* Free buffer and return */ 2049c2c66affSColin Finck ExFreePoolWithTag(LocalInfo, TAG_IO); 2050c2c66affSColin Finck return Status; 2051c2c66affSColin Finck } 2052c2c66affSColin Finck 2053c2c66affSColin Finck VOID 2054c2c66affSColin Finck NTAPI 2055c2c66affSColin Finck IopCloseFile(IN PEPROCESS Process OPTIONAL, 2056c2c66affSColin Finck IN PVOID ObjectBody, 2057c2c66affSColin Finck IN ACCESS_MASK GrantedAccess, 2058c2c66affSColin Finck IN ULONG HandleCount, 2059c2c66affSColin Finck IN ULONG SystemHandleCount) 2060c2c66affSColin Finck { 2061c2c66affSColin Finck PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 2062c2c66affSColin Finck KEVENT Event; 2063c2c66affSColin Finck PIRP Irp; 2064c2c66affSColin Finck PIO_STACK_LOCATION StackPtr; 2065c2c66affSColin Finck NTSTATUS Status; 2066c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 2067c2c66affSColin Finck KIRQL OldIrql; 20685472c1dbSPierre Schweitzer IO_STATUS_BLOCK IoStatusBlock; 2069c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 2070c2c66affSColin Finck 2071c2c66affSColin Finck /* If this isn't the last handle for the current process, quit */ 2072c2c66affSColin Finck if (HandleCount != 1) return; 2073c2c66affSColin Finck 2074c2c66affSColin Finck /* Check if the file is locked and has more then one handle opened */ 2075c2c66affSColin Finck if ((FileObject->LockOperation) && (SystemHandleCount != 1)) 2076c2c66affSColin Finck { 20775472c1dbSPierre Schweitzer /* Check if this is a direct open or not */ 20785472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN)) 20795472c1dbSPierre Schweitzer { 20805472c1dbSPierre Schweitzer /* Get the attached device */ 20815472c1dbSPierre Schweitzer DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 20825472c1dbSPierre Schweitzer } 20835472c1dbSPierre Schweitzer else 20845472c1dbSPierre Schweitzer { 20855472c1dbSPierre Schweitzer /* Get the FO's device */ 20865472c1dbSPierre Schweitzer DeviceObject = IoGetRelatedDeviceObject(FileObject); 20875472c1dbSPierre Schweitzer } 20885472c1dbSPierre Schweitzer 20895472c1dbSPierre Schweitzer /* Check if this is a sync FO and lock it */ 20905472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 20915472c1dbSPierre Schweitzer { 20928fbc4880SThomas Faber (VOID)IopLockFileObject(FileObject, KernelMode); 20935472c1dbSPierre Schweitzer } 20945472c1dbSPierre Schweitzer 20955472c1dbSPierre Schweitzer /* Go the FastIO path if possible, otherwise fall back to IRP */ 20965472c1dbSPierre Schweitzer if (DeviceObject->DriverObject->FastIoDispatch == NULL || 20975472c1dbSPierre Schweitzer DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL || 20985472c1dbSPierre Schweitzer !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject)) 20995472c1dbSPierre Schweitzer { 21005472c1dbSPierre Schweitzer /* Clear and set up Events */ 21015472c1dbSPierre Schweitzer KeClearEvent(&FileObject->Event); 21025472c1dbSPierre Schweitzer KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 21035472c1dbSPierre Schweitzer 21045472c1dbSPierre Schweitzer /* Allocate an IRP */ 21055472c1dbSPierre Schweitzer Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 21065472c1dbSPierre Schweitzer 21075472c1dbSPierre Schweitzer /* Set it up */ 21085472c1dbSPierre Schweitzer Irp->UserEvent = &Event; 21095472c1dbSPierre Schweitzer Irp->UserIosb = &Irp->IoStatus; 21105472c1dbSPierre Schweitzer Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 21115472c1dbSPierre Schweitzer Irp->Tail.Overlay.OriginalFileObject = FileObject; 21125472c1dbSPierre Schweitzer Irp->RequestorMode = KernelMode; 21135472c1dbSPierre Schweitzer Irp->Flags = IRP_SYNCHRONOUS_API; 21145472c1dbSPierre Schweitzer Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 2115207ff944SPierre Schweitzer ObReferenceObject(FileObject); 21165472c1dbSPierre Schweitzer 21175472c1dbSPierre Schweitzer /* Set up Stack Pointer Data */ 21185472c1dbSPierre Schweitzer StackPtr = IoGetNextIrpStackLocation(Irp); 21195472c1dbSPierre Schweitzer StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; 21205472c1dbSPierre Schweitzer StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL; 21215472c1dbSPierre Schweitzer StackPtr->FileObject = FileObject; 21225472c1dbSPierre Schweitzer 21235472c1dbSPierre Schweitzer /* Queue the IRP */ 21245472c1dbSPierre Schweitzer IopQueueIrpToThread(Irp); 21255472c1dbSPierre Schweitzer 21265472c1dbSPierre Schweitzer /* Call the FS Driver */ 21275472c1dbSPierre Schweitzer Status = IoCallDriver(DeviceObject, Irp); 21285472c1dbSPierre Schweitzer if (Status == STATUS_PENDING) 21295472c1dbSPierre Schweitzer { 21305472c1dbSPierre Schweitzer /* Wait for completion */ 21315472c1dbSPierre Schweitzer KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); 21325472c1dbSPierre Schweitzer } 21335472c1dbSPierre Schweitzer 21345472c1dbSPierre Schweitzer /* IO will unqueue & free for us */ 21355472c1dbSPierre Schweitzer } 21365472c1dbSPierre Schweitzer 21375472c1dbSPierre Schweitzer /* Release the lock if we were holding it */ 21385472c1dbSPierre Schweitzer if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 21395472c1dbSPierre Schweitzer { 21405472c1dbSPierre Schweitzer IopUnlockFileObject(FileObject); 21415472c1dbSPierre Schweitzer } 2142c2c66affSColin Finck } 2143c2c66affSColin Finck 2144c2c66affSColin Finck /* Make sure this is the last handle */ 2145c2c66affSColin Finck if (SystemHandleCount != 1) return; 2146c2c66affSColin Finck 2147c2c66affSColin Finck /* Check if this is a direct open or not */ 2148c2c66affSColin Finck if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 2149c2c66affSColin Finck { 2150c2c66affSColin Finck /* Get the attached device */ 2151c2c66affSColin Finck DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 2152c2c66affSColin Finck } 2153c2c66affSColin Finck else 2154c2c66affSColin Finck { 2155c2c66affSColin Finck /* Get the FO's device */ 2156c2c66affSColin Finck DeviceObject = IoGetRelatedDeviceObject(FileObject); 2157c2c66affSColin Finck } 2158c2c66affSColin Finck 2159c2c66affSColin Finck /* Set the handle created flag */ 2160c2c66affSColin Finck FileObject->Flags |= FO_HANDLE_CREATED; 2161c2c66affSColin Finck 2162c2c66affSColin Finck /* Check if this is a sync FO and lock it */ 2163cf25432eSPierre Schweitzer if (Process != NULL && 2164cf25432eSPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 2165cf25432eSPierre Schweitzer { 21668fbc4880SThomas Faber (VOID)IopLockFileObject(FileObject, KernelMode); 2167cf25432eSPierre Schweitzer } 2168c2c66affSColin Finck 2169c2c66affSColin Finck /* Clear and set up Events */ 2170c2c66affSColin Finck KeClearEvent(&FileObject->Event); 2171c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 2172c2c66affSColin Finck 2173c2c66affSColin Finck /* Allocate an IRP */ 2174c2c66affSColin Finck Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 2175c2c66affSColin Finck 2176c2c66affSColin Finck /* Set it up */ 2177c2c66affSColin Finck Irp->UserEvent = &Event; 2178c2c66affSColin Finck Irp->UserIosb = &Irp->IoStatus; 2179c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 2180c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 2181c2c66affSColin Finck Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 2182c2c66affSColin Finck Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 2183c2c66affSColin Finck 2184c2c66affSColin Finck /* Set up Stack Pointer Data */ 2185c2c66affSColin Finck StackPtr = IoGetNextIrpStackLocation(Irp); 2186c2c66affSColin Finck StackPtr->MajorFunction = IRP_MJ_CLEANUP; 2187c2c66affSColin Finck StackPtr->FileObject = FileObject; 2188c2c66affSColin Finck 2189c2c66affSColin Finck /* Queue the IRP */ 2190c2c66affSColin Finck IopQueueIrpToThread(Irp); 2191c2c66affSColin Finck 2192c2c66affSColin Finck /* Update operation counts */ 2193c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2194c2c66affSColin Finck 2195c2c66affSColin Finck /* Call the FS Driver */ 2196c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 2197c2c66affSColin Finck if (Status == STATUS_PENDING) 2198c2c66affSColin Finck { 2199c2c66affSColin Finck /* Wait for completion */ 2200c2c66affSColin Finck KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); 2201c2c66affSColin Finck } 2202c2c66affSColin Finck 2203c2c66affSColin Finck /* Unqueue the IRP */ 2204c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 2205c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 2206c2c66affSColin Finck KeLowerIrql(OldIrql); 2207c2c66affSColin Finck 2208c2c66affSColin Finck /* Free the IRP */ 2209c2c66affSColin Finck IoFreeIrp(Irp); 2210c2c66affSColin Finck 2211c2c66affSColin Finck /* Release the lock if we were holding it */ 2212cf25432eSPierre Schweitzer if (Process != NULL && 2213cf25432eSPierre Schweitzer BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO)) 2214cf25432eSPierre Schweitzer { 2215cf25432eSPierre Schweitzer IopUnlockFileObject(FileObject); 2216cf25432eSPierre Schweitzer } 2217c2c66affSColin Finck } 2218c2c66affSColin Finck 2219c2c66affSColin Finck NTSTATUS 2220c2c66affSColin Finck NTAPI 2221c2c66affSColin Finck IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 2222c2c66affSColin Finck IN FILE_INFORMATION_CLASS FileInformationClass, 2223c2c66affSColin Finck IN ULONG FileInformationSize, 2224c2c66affSColin Finck OUT PVOID FileInformation) 2225c2c66affSColin Finck { 2226c2c66affSColin Finck NTSTATUS Status; 2227c2c66affSColin Finck KPROCESSOR_MODE AccessMode = ExGetPreviousMode(); 2228c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 2229c2c66affSColin Finck FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo; 2230c2c66affSColin Finck HANDLE Handle; 2231c2c66affSColin Finck OPEN_PACKET OpenPacket; 2232c2c66affSColin Finck BOOLEAN IsBasic; 2233c2c66affSColin Finck PAGED_CODE(); 2234c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass); 2235c2c66affSColin Finck 2236c2c66affSColin Finck /* Check if the caller was user mode */ 2237c2c66affSColin Finck if (AccessMode != KernelMode) 2238c2c66affSColin Finck { 2239c2c66affSColin Finck /* Protect probe in SEH */ 2240c2c66affSColin Finck _SEH2_TRY 2241c2c66affSColin Finck { 2242c2c66affSColin Finck /* Probe the buffer */ 2243c2c66affSColin Finck ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG)); 2244c2c66affSColin Finck } 2245c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2246c2c66affSColin Finck { 2247c2c66affSColin Finck /* Return the exception code */ 2248c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 2249c2c66affSColin Finck } 2250c2c66affSColin Finck _SEH2_END; 2251c2c66affSColin Finck } 2252c2c66affSColin Finck 2253c2c66affSColin Finck /* Check if this is a basic or full request */ 2254c2c66affSColin Finck IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION)); 2255c2c66affSColin Finck 2256c2c66affSColin Finck /* Setup the Open Packet */ 2257c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 2258c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 2259c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 2260c2c66affSColin Finck OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; 2261c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 2262c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 2263c2c66affSColin Finck OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL; 2264c2c66affSColin Finck OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo : 2265c2c66affSColin Finck (AccessMode != KernelMode) ? 2266c2c66affSColin Finck &NetworkOpenInfo : FileInformation; 2267c2c66affSColin Finck OpenPacket.QueryOnly = TRUE; 2268c2c66affSColin Finck OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE; 2269c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 2270c2c66affSColin Finck 2271c2c66affSColin Finck /* Update the operation count */ 2272c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2273c2c66affSColin Finck 2274c2c66affSColin Finck /* 2275c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 2276c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 2277c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 2278c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 2279c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 2280c2c66affSColin Finck * by the Parse Check member. 2281c2c66affSColin Finck */ 2282c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 2283c2c66affSColin Finck NULL, 2284c2c66affSColin Finck AccessMode, 2285c2c66affSColin Finck NULL, 2286c2c66affSColin Finck FILE_READ_ATTRIBUTES, 2287c2c66affSColin Finck &OpenPacket, 2288c2c66affSColin Finck &Handle); 2289c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) 2290c2c66affSColin Finck { 2291c2c66affSColin Finck /* Parse failed */ 2292c2c66affSColin Finck DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n", 2293c2c66affSColin Finck ObjectAttributes->ObjectName, Status); 2294c2c66affSColin Finck return Status; 2295c2c66affSColin Finck } 2296c2c66affSColin Finck else 2297c2c66affSColin Finck { 2298c2c66affSColin Finck /* Use the Io status */ 2299c2c66affSColin Finck Status = OpenPacket.FinalStatus; 2300c2c66affSColin Finck } 2301c2c66affSColin Finck 2302c2c66affSColin Finck /* Check if we were succesful and this was user mode and a full query */ 2303c2c66affSColin Finck if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic)) 2304c2c66affSColin Finck { 2305c2c66affSColin Finck /* Enter SEH for copy */ 2306c2c66affSColin Finck _SEH2_TRY 2307c2c66affSColin Finck { 2308c2c66affSColin Finck /* Copy the buffer back */ 2309c2c66affSColin Finck RtlCopyMemory(FileInformation, 2310c2c66affSColin Finck &NetworkOpenInfo, 2311c2c66affSColin Finck FileInformationSize); 2312c2c66affSColin Finck } 2313c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2314c2c66affSColin Finck { 2315c2c66affSColin Finck /* Get exception code */ 2316c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2317c2c66affSColin Finck } 2318c2c66affSColin Finck _SEH2_END; 2319c2c66affSColin Finck } 2320c2c66affSColin Finck 2321c2c66affSColin Finck /* Return status */ 2322c2c66affSColin Finck return Status; 2323c2c66affSColin Finck } 2324c2c66affSColin Finck 23258fbc4880SThomas Faber NTSTATUS 23268fbc4880SThomas Faber NTAPI 23278fbc4880SThomas Faber IopAcquireFileObjectLock( 23288fbc4880SThomas Faber _In_ PFILE_OBJECT FileObject, 23298fbc4880SThomas Faber _In_ KPROCESSOR_MODE WaitMode, 23308fbc4880SThomas Faber _In_ BOOLEAN Alertable, 23318fbc4880SThomas Faber _Out_ PBOOLEAN LockFailed) 23328fbc4880SThomas Faber { 23338fbc4880SThomas Faber NTSTATUS Status; 23348fbc4880SThomas Faber 23358fbc4880SThomas Faber PAGED_CODE(); 23368fbc4880SThomas Faber 23378fbc4880SThomas Faber InterlockedIncrement((PLONG)&FileObject->Waiters); 23388fbc4880SThomas Faber 23398fbc4880SThomas Faber Status = STATUS_SUCCESS; 23408fbc4880SThomas Faber do 23418fbc4880SThomas Faber { 23428fbc4880SThomas Faber if (!InterlockedExchange((PLONG)&FileObject->Busy, TRUE)) 23438fbc4880SThomas Faber { 23448fbc4880SThomas Faber break; 23458fbc4880SThomas Faber } 23468fbc4880SThomas Faber Status = KeWaitForSingleObject(&FileObject->Lock, 23478fbc4880SThomas Faber Executive, 23488fbc4880SThomas Faber WaitMode, 23498fbc4880SThomas Faber Alertable, 23508fbc4880SThomas Faber NULL); 23518fbc4880SThomas Faber } while (Status == STATUS_SUCCESS); 23528fbc4880SThomas Faber 23538fbc4880SThomas Faber InterlockedDecrement((PLONG)&FileObject->Waiters); 23548fbc4880SThomas Faber if (Status == STATUS_SUCCESS) 23558fbc4880SThomas Faber { 23568fbc4880SThomas Faber ObReferenceObject(FileObject); 23578fbc4880SThomas Faber *LockFailed = FALSE; 23588fbc4880SThomas Faber } 23598fbc4880SThomas Faber else 23608fbc4880SThomas Faber { 23618fbc4880SThomas Faber if (!FileObject->Busy && FileObject->Waiters) 23628fbc4880SThomas Faber { 23638fbc4880SThomas Faber KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE); 23648fbc4880SThomas Faber } 23658fbc4880SThomas Faber *LockFailed = TRUE; 23668fbc4880SThomas Faber } 23678fbc4880SThomas Faber 23688fbc4880SThomas Faber return Status; 23698fbc4880SThomas Faber } 23708fbc4880SThomas Faber 2371c2c66affSColin Finck PVOID 2372c2c66affSColin Finck NTAPI 2373c2c66affSColin Finck IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject) 2374c2c66affSColin Finck { 2375c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 2376c2c66affSColin Finck { 2377c2c66affSColin Finck UNIMPLEMENTED; 2378c2c66affSColin Finck /* FIXME: return NULL for the moment ~ */ 2379c2c66affSColin Finck return NULL; 2380c2c66affSColin Finck } 2381c2c66affSColin Finck 2382c2c66affSColin Finck return NULL; 2383c2c66affSColin Finck } 2384c2c66affSColin Finck 2385c2c66affSColin Finck NTSTATUS 2386c2c66affSColin Finck NTAPI 2387c2c66affSColin Finck IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, 2388c2c66affSColin Finck IN PVOID FilterContext, 2389c2c66affSColin Finck IN BOOLEAN Define) 2390c2c66affSColin Finck { 2391c2c66affSColin Finck if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) 2392c2c66affSColin Finck { 2393c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2394c2c66affSColin Finck } 2395c2c66affSColin Finck 2396c2c66affSColin Finck UNIMPLEMENTED; 2397c2c66affSColin Finck 2398c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2399c2c66affSColin Finck } 2400c2c66affSColin Finck 2401c2c66affSColin Finck NTSTATUS 2402c2c66affSColin Finck NTAPI 2403c2c66affSColin Finck IopCreateFile(OUT PHANDLE FileHandle, 2404c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2405c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2406c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2407c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2408c2c66affSColin Finck IN ULONG FileAttributes, 2409c2c66affSColin Finck IN ULONG ShareAccess, 2410c2c66affSColin Finck IN ULONG Disposition, 2411c2c66affSColin Finck IN ULONG CreateOptions, 2412c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2413c2c66affSColin Finck IN ULONG EaLength, 2414c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2415c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2416c2c66affSColin Finck IN ULONG Options, 2417c2c66affSColin Finck IN ULONG Flags, 2418c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL) 2419c2c66affSColin Finck { 2420c2c66affSColin Finck KPROCESSOR_MODE AccessMode; 2421c2c66affSColin Finck HANDLE LocalHandle = 0; 2422c2c66affSColin Finck LARGE_INTEGER SafeAllocationSize; 2423c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 2424c2c66affSColin Finck PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters; 2425c2c66affSColin Finck POPEN_PACKET OpenPacket; 2426c2c66affSColin Finck ULONG EaErrorOffset; 2427c2c66affSColin Finck PAGED_CODE(); 2428c2c66affSColin Finck 2429c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 2430c2c66affSColin Finck 2431c2c66affSColin Finck 2432c2c66affSColin Finck /* Check if we have no parameter checking to do */ 2433c2c66affSColin Finck if (Options & IO_NO_PARAMETER_CHECKING) 2434c2c66affSColin Finck { 2435c2c66affSColin Finck /* Then force kernel-mode access to avoid checks */ 2436c2c66affSColin Finck AccessMode = KernelMode; 2437c2c66affSColin Finck } 2438c2c66affSColin Finck else 2439c2c66affSColin Finck { 2440c2c66affSColin Finck /* Otherwise, use the actual mode */ 2441c2c66affSColin Finck AccessMode = ExGetPreviousMode(); 2442c2c66affSColin Finck } 2443c2c66affSColin Finck 2444c2c66affSColin Finck /* Check if we need to do parameter checking */ 2445c2c66affSColin Finck if ((AccessMode != KernelMode) || (Options & IO_CHECK_CREATE_PARAMETERS)) 2446c2c66affSColin Finck { 2447c2c66affSColin Finck /* Validate parameters */ 2448c2c66affSColin Finck if (FileAttributes & ~FILE_ATTRIBUTE_VALID_FLAGS) 2449c2c66affSColin Finck { 2450c2c66affSColin Finck DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n"); 2451c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2452c2c66affSColin Finck } 2453c2c66affSColin Finck 2454c2c66affSColin Finck if (ShareAccess & ~FILE_SHARE_VALID_FLAGS) 2455c2c66affSColin Finck { 2456c2c66affSColin Finck DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n"); 2457c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2458c2c66affSColin Finck } 2459c2c66affSColin Finck 2460c2c66affSColin Finck if (Disposition > FILE_MAXIMUM_DISPOSITION) 2461c2c66affSColin Finck { 2462c2c66affSColin Finck DPRINT1("File Create 'Disposition' Parameter is out of range!\n"); 2463c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2464c2c66affSColin Finck } 2465c2c66affSColin Finck 2466c2c66affSColin Finck if (CreateOptions & ~FILE_VALID_OPTION_FLAGS) 2467c2c66affSColin Finck { 2468c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n"); 2469c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2470c2c66affSColin Finck } 2471c2c66affSColin Finck 2472c2c66affSColin Finck if ((CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) && 2473c2c66affSColin Finck (!(DesiredAccess & SYNCHRONIZE))) 2474c2c66affSColin Finck { 2475c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n"); 2476c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2477c2c66affSColin Finck } 2478c2c66affSColin Finck 2479c2c66affSColin Finck if ((CreateOptions & FILE_DELETE_ON_CLOSE) && (!(DesiredAccess & DELETE))) 2480c2c66affSColin Finck { 2481c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n"); 2482c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2483c2c66affSColin Finck } 2484c2c66affSColin Finck 2485c2c66affSColin Finck if ((CreateOptions & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)) == 2486c2c66affSColin Finck (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)) 2487c2c66affSColin Finck { 2488c2c66affSColin Finck DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n"); 2489c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2490c2c66affSColin Finck } 2491c2c66affSColin Finck 2492c2c66affSColin Finck if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) && 2493c2c66affSColin Finck (CreateOptions & ~(FILE_DIRECTORY_FILE | 2494c2c66affSColin Finck FILE_SYNCHRONOUS_IO_ALERT | 2495c2c66affSColin Finck FILE_SYNCHRONOUS_IO_NONALERT | 2496c2c66affSColin Finck FILE_WRITE_THROUGH | 2497c2c66affSColin Finck FILE_COMPLETE_IF_OPLOCKED | 2498c2c66affSColin Finck FILE_OPEN_FOR_BACKUP_INTENT | 2499c2c66affSColin Finck FILE_DELETE_ON_CLOSE | 2500c2c66affSColin Finck FILE_OPEN_FOR_FREE_SPACE_QUERY | 2501c2c66affSColin Finck FILE_OPEN_BY_FILE_ID | 2502c2c66affSColin Finck FILE_NO_COMPRESSION | 2503c2c66affSColin Finck FILE_OPEN_REPARSE_POINT))) 2504c2c66affSColin Finck { 2505c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n"); 2506c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2507c2c66affSColin Finck } 2508c2c66affSColin Finck 2509c2c66affSColin Finck if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) && 2510c2c66affSColin Finck (Disposition != FILE_CREATE) && (Disposition != FILE_OPEN) && (Disposition != FILE_OPEN_IF)) 2511c2c66affSColin Finck { 2512c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n"); 2513c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2514c2c66affSColin Finck } 2515c2c66affSColin Finck 2516c2c66affSColin Finck if ((CreateOptions & FILE_COMPLETE_IF_OPLOCKED) && (CreateOptions & FILE_RESERVE_OPFILTER)) 2517c2c66affSColin Finck { 2518c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n"); 2519c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2520c2c66affSColin Finck } 2521c2c66affSColin Finck 2522c2c66affSColin Finck if ((CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) && (DesiredAccess & FILE_APPEND_DATA)) 2523c2c66affSColin Finck { 2524c2c66affSColin Finck DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n"); 2525c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2526c2c66affSColin Finck } 2527c2c66affSColin Finck 2528c2c66affSColin Finck /* Now check if this is a named pipe */ 2529c2c66affSColin Finck if (CreateFileType == CreateFileTypeNamedPipe) 2530c2c66affSColin Finck { 2531c2c66affSColin Finck /* Make sure we have extra parameters */ 2532c2c66affSColin Finck if (!ExtraCreateParameters) 2533c2c66affSColin Finck { 2534c2c66affSColin Finck DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n"); 2535c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2536c2c66affSColin Finck } 2537c2c66affSColin Finck 2538c2c66affSColin Finck /* Get the parameters and validate them */ 2539c2c66affSColin Finck NamedPipeCreateParameters = ExtraCreateParameters; 2540c2c66affSColin Finck if ((NamedPipeCreateParameters->NamedPipeType > FILE_PIPE_MESSAGE_TYPE) || 2541c2c66affSColin Finck (NamedPipeCreateParameters->ReadMode > FILE_PIPE_MESSAGE_MODE) || 2542c2c66affSColin Finck (NamedPipeCreateParameters->CompletionMode > FILE_PIPE_COMPLETE_OPERATION) || 2543c2c66affSColin Finck (ShareAccess & FILE_SHARE_DELETE) || 2544c2c66affSColin Finck ((Disposition < FILE_OPEN) || (Disposition > FILE_OPEN_IF)) || 2545c2c66affSColin Finck (CreateOptions & ~FILE_VALID_PIPE_OPTION_FLAGS)) 2546c2c66affSColin Finck { 2547c2c66affSColin Finck /* Invalid named pipe create */ 2548c2c66affSColin Finck DPRINT1("Invalid named pipe create\n"); 2549c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2550c2c66affSColin Finck } 2551c2c66affSColin Finck } 2552c2c66affSColin Finck else if (CreateFileType == CreateFileTypeMailslot) 2553c2c66affSColin Finck { 2554c2c66affSColin Finck /* Make sure we have extra parameters */ 2555c2c66affSColin Finck if (!ExtraCreateParameters) 2556c2c66affSColin Finck { 2557c2c66affSColin Finck DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n"); 2558c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2559c2c66affSColin Finck } 2560c2c66affSColin Finck 2561c2c66affSColin Finck /* Get the parameters and validate them */ 2562c2c66affSColin Finck if ((ShareAccess & FILE_SHARE_DELETE) || 2563c2c66affSColin Finck !(ShareAccess & ~FILE_SHARE_WRITE) || 2564c2c66affSColin Finck (Disposition != FILE_CREATE) || 2565c2c66affSColin Finck (CreateOptions & ~FILE_VALID_MAILSLOT_OPTION_FLAGS)) 2566c2c66affSColin Finck { 2567c2c66affSColin Finck /* Invalid mailslot create */ 2568c2c66affSColin Finck DPRINT1("Invalid mailslot create\n"); 2569c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2570c2c66affSColin Finck } 2571c2c66affSColin Finck } 2572c2c66affSColin Finck } 2573c2c66affSColin Finck 2574c2c66affSColin Finck /* Allocate the open packet */ 2575c2c66affSColin Finck OpenPacket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*OpenPacket), 'pOoI'); 2576c2c66affSColin Finck if (!OpenPacket) return STATUS_INSUFFICIENT_RESOURCES; 2577c2c66affSColin Finck RtlZeroMemory(OpenPacket, sizeof(*OpenPacket)); 2578c2c66affSColin Finck 2579c2c66affSColin Finck /* Check if the call came from user mode */ 2580c2c66affSColin Finck if (AccessMode != KernelMode) 2581c2c66affSColin Finck { 2582c2c66affSColin Finck _SEH2_TRY 2583c2c66affSColin Finck { 2584c2c66affSColin Finck /* Probe the output parameters */ 2585c2c66affSColin Finck ProbeForWriteHandle(FileHandle); 2586c2c66affSColin Finck ProbeForWriteIoStatusBlock(IoStatusBlock); 2587c2c66affSColin Finck 2588c2c66affSColin Finck /* Probe the allocation size if one was passed in */ 2589c2c66affSColin Finck if (AllocationSize) 2590c2c66affSColin Finck { 2591c2c66affSColin Finck SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize); 2592c2c66affSColin Finck } 2593c2c66affSColin Finck else 2594c2c66affSColin Finck { 2595c2c66affSColin Finck SafeAllocationSize.QuadPart = 0; 2596c2c66affSColin Finck } 2597c2c66affSColin Finck 2598c2c66affSColin Finck /* Make sure it's valid */ 2599c2c66affSColin Finck if (SafeAllocationSize.QuadPart < 0) 2600c2c66affSColin Finck { 2601c2c66affSColin Finck RtlRaiseStatus(STATUS_INVALID_PARAMETER); 2602c2c66affSColin Finck } 2603c2c66affSColin Finck 2604c2c66affSColin Finck /* Check if EA was passed in */ 2605c2c66affSColin Finck if ((EaBuffer) && (EaLength)) 2606c2c66affSColin Finck { 2607c2c66affSColin Finck /* Probe it */ 2608c2c66affSColin Finck ProbeForRead(EaBuffer, EaLength, sizeof(ULONG)); 2609c2c66affSColin Finck 2610c2c66affSColin Finck /* And marshall it */ 2611c2c66affSColin Finck OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool, 2612c2c66affSColin Finck EaLength, 2613c2c66affSColin Finck TAG_EA); 2614c2c66affSColin Finck OpenPacket->EaLength = EaLength; 2615c2c66affSColin Finck RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength); 2616c2c66affSColin Finck 2617c2c66affSColin Finck /* Validate the buffer */ 2618c2c66affSColin Finck Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer, 2619c2c66affSColin Finck EaLength, 2620c2c66affSColin Finck &EaErrorOffset); 2621c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2622c2c66affSColin Finck { 2623c2c66affSColin Finck /* Undo everything if it's invalid */ 2624c2c66affSColin Finck DPRINT1("Invalid EA buffer\n"); 2625c2c66affSColin Finck IoStatusBlock->Status = Status; 2626c2c66affSColin Finck IoStatusBlock->Information = EaErrorOffset; 2627c2c66affSColin Finck RtlRaiseStatus(Status); 2628c2c66affSColin Finck } 2629c2c66affSColin Finck } 2630c2c66affSColin Finck } 2631c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2632c2c66affSColin Finck { 2633c2c66affSColin Finck /* Return the exception code */ 2634c2c66affSColin Finck if (OpenPacket->EaBuffer != NULL) ExFreePool(OpenPacket->EaBuffer); 2635c2c66affSColin Finck ExFreePool(OpenPacket); 2636c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 2637c2c66affSColin Finck } 2638c2c66affSColin Finck _SEH2_END; 2639c2c66affSColin Finck } 2640c2c66affSColin Finck else 2641c2c66affSColin Finck { 2642c2c66affSColin Finck /* Check if this is a device attach */ 2643c2c66affSColin Finck if (CreateOptions & IO_ATTACH_DEVICE_API) 2644c2c66affSColin Finck { 2645c2c66affSColin Finck /* Set the flag properly */ 2646c2c66affSColin Finck Options |= IO_ATTACH_DEVICE; 2647c2c66affSColin Finck CreateOptions &= ~IO_ATTACH_DEVICE_API; 2648c2c66affSColin Finck } 2649c2c66affSColin Finck 2650c2c66affSColin Finck /* Check if we have allocation size */ 2651c2c66affSColin Finck if (AllocationSize) 2652c2c66affSColin Finck { 2653c2c66affSColin Finck /* Capture it */ 2654c2c66affSColin Finck SafeAllocationSize = *AllocationSize; 2655c2c66affSColin Finck } 2656c2c66affSColin Finck else 2657c2c66affSColin Finck { 2658c2c66affSColin Finck /* Otherwise, no size */ 2659c2c66affSColin Finck SafeAllocationSize.QuadPart = 0; 2660c2c66affSColin Finck } 2661c2c66affSColin Finck 2662c2c66affSColin Finck /* Check if we have an EA packet */ 2663c2c66affSColin Finck if ((EaBuffer) && (EaLength)) 2664c2c66affSColin Finck { 2665c2c66affSColin Finck /* Allocate the kernel copy */ 2666c2c66affSColin Finck OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool, 2667c2c66affSColin Finck EaLength, 2668c2c66affSColin Finck TAG_EA); 2669c2c66affSColin Finck if (!OpenPacket->EaBuffer) 2670c2c66affSColin Finck { 2671c2c66affSColin Finck ExFreePool(OpenPacket); 2672c2c66affSColin Finck DPRINT1("Failed to allocate open packet EA buffer\n"); 2673c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 2674c2c66affSColin Finck } 2675c2c66affSColin Finck 2676c2c66affSColin Finck /* Copy the data */ 2677c2c66affSColin Finck OpenPacket->EaLength = EaLength; 2678c2c66affSColin Finck RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength); 2679c2c66affSColin Finck 2680c2c66affSColin Finck /* Validate the buffer */ 2681c2c66affSColin Finck Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer, 2682c2c66affSColin Finck EaLength, 2683c2c66affSColin Finck &EaErrorOffset); 2684c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2685c2c66affSColin Finck { 2686c2c66affSColin Finck /* Undo everything if it's invalid */ 2687c2c66affSColin Finck DPRINT1("Invalid EA buffer\n"); 2688c2c66affSColin Finck ExFreePool(OpenPacket->EaBuffer); 2689c2c66affSColin Finck IoStatusBlock->Status = Status; 2690c2c66affSColin Finck IoStatusBlock->Information = EaErrorOffset; 2691c2c66affSColin Finck ExFreePool(OpenPacket); 2692c2c66affSColin Finck return Status; 2693c2c66affSColin Finck } 2694c2c66affSColin Finck } 2695c2c66affSColin Finck } 2696c2c66affSColin Finck 2697c2c66affSColin Finck /* Setup the Open Packet */ 2698c2c66affSColin Finck OpenPacket->Type = IO_TYPE_OPEN_PACKET; 2699c2c66affSColin Finck OpenPacket->Size = sizeof(*OpenPacket); 2700c2c66affSColin Finck OpenPacket->AllocationSize = SafeAllocationSize; 2701c2c66affSColin Finck OpenPacket->CreateOptions = CreateOptions; 2702c2c66affSColin Finck OpenPacket->FileAttributes = (USHORT)FileAttributes; 2703c2c66affSColin Finck OpenPacket->ShareAccess = (USHORT)ShareAccess; 2704c2c66affSColin Finck OpenPacket->Options = Options; 2705c2c66affSColin Finck OpenPacket->Disposition = Disposition; 2706c2c66affSColin Finck OpenPacket->CreateFileType = CreateFileType; 2707c2c66affSColin Finck OpenPacket->ExtraCreateParameters = ExtraCreateParameters; 2708c2c66affSColin Finck OpenPacket->InternalFlags = Flags; 2709c2c66affSColin Finck OpenPacket->TopDeviceObjectHint = DeviceObject; 2710c2c66affSColin Finck 2711c2c66affSColin Finck /* Update the operation count */ 2712c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 2713c2c66affSColin Finck 2714c2c66affSColin Finck /* 2715c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 2716c2c66affSColin Finck * the File Object (IopParseDevice) which will create the object and 2717c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 2718c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 2719c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 2720c2c66affSColin Finck * by the Parse Check member. 2721c2c66affSColin Finck */ 2722c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 2723c2c66affSColin Finck NULL, 2724c2c66affSColin Finck AccessMode, 2725c2c66affSColin Finck NULL, 2726c2c66affSColin Finck DesiredAccess, 2727c2c66affSColin Finck OpenPacket, 2728c2c66affSColin Finck &LocalHandle); 2729c2c66affSColin Finck 2730c2c66affSColin Finck /* Free the EA Buffer */ 2731c2c66affSColin Finck if (OpenPacket->EaBuffer) ExFreePool(OpenPacket->EaBuffer); 2732c2c66affSColin Finck 2733c2c66affSColin Finck /* Now check for Ob or Io failure */ 2734c2c66affSColin Finck if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck == FALSE)) 2735c2c66affSColin Finck { 2736c2c66affSColin Finck /* Check if Ob thinks well went well */ 2737c2c66affSColin Finck if (NT_SUCCESS(Status)) 2738c2c66affSColin Finck { 2739c2c66affSColin Finck /* 2740c2c66affSColin Finck * Tell it otherwise. Because we didn't use an ObjectType, 2741c2c66affSColin Finck * it incorrectly returned us a handle to God knows what. 2742c2c66affSColin Finck */ 2743c2c66affSColin Finck ZwClose(LocalHandle); 2744c2c66affSColin Finck Status = STATUS_OBJECT_TYPE_MISMATCH; 2745c2c66affSColin Finck } 2746c2c66affSColin Finck 2747c2c66affSColin Finck /* Now check the Io status */ 2748c2c66affSColin Finck if (!NT_SUCCESS(OpenPacket->FinalStatus)) 2749c2c66affSColin Finck { 2750c2c66affSColin Finck /* Use this status instead of Ob's */ 2751c2c66affSColin Finck Status = OpenPacket->FinalStatus; 2752c2c66affSColin Finck 2753c2c66affSColin Finck /* Check if it was only a warning */ 2754c2c66affSColin Finck if (NT_WARNING(Status)) 2755c2c66affSColin Finck { 2756c2c66affSColin Finck /* Protect write with SEH */ 2757c2c66affSColin Finck _SEH2_TRY 2758c2c66affSColin Finck { 2759c2c66affSColin Finck /* In this case, we copy the I/O Status back */ 2760c2c66affSColin Finck IoStatusBlock->Information = OpenPacket->Information; 2761c2c66affSColin Finck IoStatusBlock->Status = OpenPacket->FinalStatus; 2762c2c66affSColin Finck } 2763c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2764c2c66affSColin Finck { 2765c2c66affSColin Finck /* Get exception code */ 2766c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2767c2c66affSColin Finck } 2768c2c66affSColin Finck _SEH2_END; 2769c2c66affSColin Finck } 2770c2c66affSColin Finck } 2771c2c66affSColin Finck else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck == FALSE)) 2772c2c66affSColin Finck { 2773c2c66affSColin Finck /* 2774c2c66affSColin Finck * This can happen in the very bizarre case where the parse routine 2775c2c66affSColin Finck * actually executed more then once (due to a reparse) and ended 2776c2c66affSColin Finck * up failing after already having created the File Object. 2777c2c66affSColin Finck */ 2778c2c66affSColin Finck if (OpenPacket->FileObject->FileName.Length) 2779c2c66affSColin Finck { 2780c2c66affSColin Finck /* It had a name, free it */ 2781c2c66affSColin Finck ExFreePoolWithTag(OpenPacket->FileObject->FileName.Buffer, TAG_IO_NAME); 2782c2c66affSColin Finck } 2783c2c66affSColin Finck 2784c2c66affSColin Finck /* Clear the device object to invalidate the FO, and dereference */ 2785c2c66affSColin Finck OpenPacket->FileObject->DeviceObject = NULL; 2786c2c66affSColin Finck ObDereferenceObject(OpenPacket->FileObject); 2787c2c66affSColin Finck } 2788c2c66affSColin Finck } 2789c2c66affSColin Finck else 2790c2c66affSColin Finck { 2791c2c66affSColin Finck /* We reached success and have a valid file handle */ 2792c2c66affSColin Finck OpenPacket->FileObject->Flags |= FO_HANDLE_CREATED; 2793c2c66affSColin Finck ASSERT(OpenPacket->FileObject->Type == IO_TYPE_FILE); 2794c2c66affSColin Finck 2795c2c66affSColin Finck /* Enter SEH for write back */ 2796c2c66affSColin Finck _SEH2_TRY 2797c2c66affSColin Finck { 2798c2c66affSColin Finck /* Write back the handle and I/O Status */ 2799c2c66affSColin Finck *FileHandle = LocalHandle; 2800c2c66affSColin Finck IoStatusBlock->Information = OpenPacket->Information; 2801c2c66affSColin Finck IoStatusBlock->Status = OpenPacket->FinalStatus; 2802c2c66affSColin Finck 2803c2c66affSColin Finck /* Get the Io status */ 2804c2c66affSColin Finck Status = OpenPacket->FinalStatus; 2805c2c66affSColin Finck } 2806c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2807c2c66affSColin Finck { 2808c2c66affSColin Finck /* Get the exception status */ 2809c2c66affSColin Finck Status = _SEH2_GetExceptionCode(); 2810c2c66affSColin Finck } 2811c2c66affSColin Finck _SEH2_END; 2812c2c66affSColin Finck } 2813c2c66affSColin Finck 2814c2c66affSColin Finck /* Check if we were 100% successful */ 2815c2c66affSColin Finck if ((OpenPacket->ParseCheck != FALSE) && (OpenPacket->FileObject)) 2816c2c66affSColin Finck { 2817c2c66affSColin Finck /* Dereference the File Object */ 2818c2c66affSColin Finck ObDereferenceObject(OpenPacket->FileObject); 2819c2c66affSColin Finck } 2820c2c66affSColin Finck 2821c2c66affSColin Finck /* Return status */ 2822c2c66affSColin Finck ExFreePool(OpenPacket); 2823c2c66affSColin Finck return Status; 2824c2c66affSColin Finck } 2825c2c66affSColin Finck 2826c2c66affSColin Finck /* FUNCTIONS *****************************************************************/ 2827c2c66affSColin Finck 2828c2c66affSColin Finck /* 2829c2c66affSColin Finck * @unimplemented 2830c2c66affSColin Finck */ 2831c2c66affSColin Finck NTSTATUS 2832c2c66affSColin Finck NTAPI 2833c2c66affSColin Finck IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass, 2834c2c66affSColin Finck IN ULONG Length, 2835c2c66affSColin Finck IN BOOLEAN SetOperation) 2836c2c66affSColin Finck { 2837c2c66affSColin Finck UNIMPLEMENTED; 2838c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2839c2c66affSColin Finck } 2840c2c66affSColin Finck 2841c2c66affSColin Finck /* 2842c2c66affSColin Finck * @unimplemented 2843c2c66affSColin Finck */ 2844c2c66affSColin Finck NTSTATUS 2845c2c66affSColin Finck NTAPI 2846c2c66affSColin Finck IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer, 2847c2c66affSColin Finck IN ULONG QuotaLength, 2848c2c66affSColin Finck OUT PULONG ErrorOffset) 2849c2c66affSColin Finck { 2850c2c66affSColin Finck UNIMPLEMENTED; 2851c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED; 2852c2c66affSColin Finck } 2853c2c66affSColin Finck 2854c2c66affSColin Finck /* 2855c2c66affSColin Finck * @implemented 2856c2c66affSColin Finck */ 2857c2c66affSColin Finck NTSTATUS 2858c2c66affSColin Finck NTAPI 2859c2c66affSColin Finck IoCreateFile(OUT PHANDLE FileHandle, 2860c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2861c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2862c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2863c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2864c2c66affSColin Finck IN ULONG FileAttributes, 2865c2c66affSColin Finck IN ULONG ShareAccess, 2866c2c66affSColin Finck IN ULONG Disposition, 2867c2c66affSColin Finck IN ULONG CreateOptions, 2868c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2869c2c66affSColin Finck IN ULONG EaLength, 2870c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2871c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2872c2c66affSColin Finck IN ULONG Options) 2873c2c66affSColin Finck { 2874c2c66affSColin Finck PAGED_CODE(); 2875c2c66affSColin Finck 2876c2c66affSColin Finck return IopCreateFile(FileHandle, 2877c2c66affSColin Finck DesiredAccess, 2878c2c66affSColin Finck ObjectAttributes, 2879c2c66affSColin Finck IoStatusBlock, 2880c2c66affSColin Finck AllocationSize, 2881c2c66affSColin Finck FileAttributes, 2882c2c66affSColin Finck ShareAccess, 2883c2c66affSColin Finck Disposition, 2884c2c66affSColin Finck CreateOptions, 2885c2c66affSColin Finck EaBuffer, 2886c2c66affSColin Finck EaLength, 2887c2c66affSColin Finck CreateFileType, 2888c2c66affSColin Finck ExtraCreateParameters, 2889c2c66affSColin Finck Options, 2890c2c66affSColin Finck 0, 2891c2c66affSColin Finck NULL); 2892c2c66affSColin Finck } 2893c2c66affSColin Finck 2894c2c66affSColin Finck /* 2895c2c66affSColin Finck * @unimplemented 2896c2c66affSColin Finck */ 2897c2c66affSColin Finck NTSTATUS 2898c2c66affSColin Finck NTAPI 2899c2c66affSColin Finck IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle, 2900c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 2901c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 2902c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 2903c2c66affSColin Finck IN PLARGE_INTEGER AllocationSize OPTIONAL, 2904c2c66affSColin Finck IN ULONG FileAttributes, 2905c2c66affSColin Finck IN ULONG ShareAccess, 2906c2c66affSColin Finck IN ULONG Disposition, 2907c2c66affSColin Finck IN ULONG CreateOptions, 2908c2c66affSColin Finck IN PVOID EaBuffer OPTIONAL, 2909c2c66affSColin Finck IN ULONG EaLength, 2910c2c66affSColin Finck IN CREATE_FILE_TYPE CreateFileType, 2911c2c66affSColin Finck IN PVOID ExtraCreateParameters OPTIONAL, 2912c2c66affSColin Finck IN ULONG Options, 2913c2c66affSColin Finck IN PVOID DeviceObject) 2914c2c66affSColin Finck { 2915c2c66affSColin Finck ULONG Flags = 0; 2916c2c66affSColin Finck 2917c2c66affSColin Finck PAGED_CODE(); 2918c2c66affSColin Finck 2919c2c66affSColin Finck /* Check if we were passed a device to send the create request to*/ 2920c2c66affSColin Finck if (DeviceObject) 2921c2c66affSColin Finck { 2922c2c66affSColin Finck /* We'll tag this request into a file object extension */ 2923c2c66affSColin Finck Flags = (IOP_CREATE_FILE_OBJECT_EXTENSION | IOP_USE_TOP_LEVEL_DEVICE_HINT); 2924c2c66affSColin Finck } 2925c2c66affSColin Finck 2926c2c66affSColin Finck return IopCreateFile(FileHandle, 2927c2c66affSColin Finck DesiredAccess, 2928c2c66affSColin Finck ObjectAttributes, 2929c2c66affSColin Finck IoStatusBlock, 2930c2c66affSColin Finck AllocationSize, 2931c2c66affSColin Finck FileAttributes, 2932c2c66affSColin Finck ShareAccess, 2933c2c66affSColin Finck Disposition, 2934c2c66affSColin Finck CreateOptions, 2935c2c66affSColin Finck EaBuffer, 2936c2c66affSColin Finck EaLength, 2937c2c66affSColin Finck CreateFileType, 2938c2c66affSColin Finck ExtraCreateParameters, 2939c2c66affSColin Finck Options | IO_NO_PARAMETER_CHECKING, 2940c2c66affSColin Finck Flags, 2941c2c66affSColin Finck DeviceObject); 2942c2c66affSColin Finck } 2943c2c66affSColin Finck 2944c2c66affSColin Finck /* 2945c2c66affSColin Finck * @implemented 2946c2c66affSColin Finck */ 2947c2c66affSColin Finck PFILE_OBJECT 2948c2c66affSColin Finck NTAPI 2949c2c66affSColin Finck IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL, 2950c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL, 2951c2c66affSColin Finck OUT PHANDLE FileObjectHandle OPTIONAL) 2952c2c66affSColin Finck { 2953c2c66affSColin Finck PFILE_OBJECT CreatedFileObject; 2954c2c66affSColin Finck NTSTATUS Status; 2955c2c66affSColin Finck HANDLE FileHandle; 2956c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 2957c2c66affSColin Finck PAGED_CODE(); 2958c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 2959c2c66affSColin Finck 2960c2c66affSColin Finck /* Choose Device Object */ 2961c2c66affSColin Finck if (FileObject) DeviceObject = FileObject->DeviceObject; 2962c2c66affSColin Finck 2963c2c66affSColin Finck /* Reference the device object and initialize attributes */ 2964c2c66affSColin Finck InterlockedIncrement(&DeviceObject->ReferenceCount); 2965c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 2966c2c66affSColin Finck 2967c2c66affSColin Finck /* Create the File Object */ 2968c2c66affSColin Finck Status = ObCreateObject(KernelMode, 2969c2c66affSColin Finck IoFileObjectType, 2970c2c66affSColin Finck &ObjectAttributes, 2971c2c66affSColin Finck KernelMode, 2972c2c66affSColin Finck NULL, 2973c2c66affSColin Finck sizeof(FILE_OBJECT), 2974c2c66affSColin Finck sizeof(FILE_OBJECT), 2975c2c66affSColin Finck 0, 2976c2c66affSColin Finck (PVOID*)&CreatedFileObject); 2977c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2978c2c66affSColin Finck { 2979c2c66affSColin Finck /* Fail */ 2980c2c66affSColin Finck IopDereferenceDeviceObject(DeviceObject, FALSE); 2981c2c66affSColin Finck ExRaiseStatus(Status); 2982c2c66affSColin Finck } 2983c2c66affSColin Finck 2984c2c66affSColin Finck /* Set File Object Data */ 2985c2c66affSColin Finck RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 2986c2c66affSColin Finck CreatedFileObject->DeviceObject = DeviceObject; 2987c2c66affSColin Finck CreatedFileObject->Type = IO_TYPE_FILE; 2988c2c66affSColin Finck CreatedFileObject->Size = sizeof(FILE_OBJECT); 2989c2c66affSColin Finck CreatedFileObject->Flags = FO_STREAM_FILE; 2990c2c66affSColin Finck 2991c2c66affSColin Finck /* Initialize the wait event */ 2992c2c66affSColin Finck KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 2993c2c66affSColin Finck 2994c2c66affSColin Finck /* Insert it to create a handle for it */ 2995c2c66affSColin Finck Status = ObInsertObject(CreatedFileObject, 2996c2c66affSColin Finck NULL, 2997c2c66affSColin Finck FILE_READ_DATA, 2998c2c66affSColin Finck 1, 2999c2c66affSColin Finck (PVOID*)&CreatedFileObject, 3000c2c66affSColin Finck &FileHandle); 3001c2c66affSColin Finck if (!NT_SUCCESS(Status)) ExRaiseStatus(Status); 3002c2c66affSColin Finck 3003c2c66affSColin Finck /* Set the handle created flag */ 3004c2c66affSColin Finck CreatedFileObject->Flags |= FO_HANDLE_CREATED; 3005c2c66affSColin Finck ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 3006c2c66affSColin Finck 3007c2c66affSColin Finck /* Check if we have a VPB */ 3008c2c66affSColin Finck if (DeviceObject->Vpb) 3009c2c66affSColin Finck { 3010c2c66affSColin Finck /* Reference it */ 3011c2c66affSColin Finck InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 3012c2c66affSColin Finck } 3013c2c66affSColin Finck 3014c2c66affSColin Finck /* Check if the caller wants the handle */ 3015c2c66affSColin Finck if (FileObjectHandle) 3016c2c66affSColin Finck { 3017c2c66affSColin Finck /* Return it */ 3018c2c66affSColin Finck *FileObjectHandle = FileHandle; 3019c2c66affSColin Finck ObDereferenceObject(CreatedFileObject); 3020c2c66affSColin Finck } 3021c2c66affSColin Finck else 3022c2c66affSColin Finck { 3023c2c66affSColin Finck /* Otherwise, close it */ 3024c2c66affSColin Finck ObCloseHandle(FileHandle, KernelMode); 3025c2c66affSColin Finck } 3026c2c66affSColin Finck 3027c2c66affSColin Finck /* Return the file object */ 3028c2c66affSColin Finck return CreatedFileObject; 3029c2c66affSColin Finck } 3030c2c66affSColin Finck 3031c2c66affSColin Finck /* 3032c2c66affSColin Finck * @implemented 3033c2c66affSColin Finck */ 3034c2c66affSColin Finck PFILE_OBJECT 3035c2c66affSColin Finck NTAPI 3036c2c66affSColin Finck IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, 3037c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject) 3038c2c66affSColin Finck { 3039c2c66affSColin Finck /* Call the newer function */ 3040c2c66affSColin Finck return IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL); 3041c2c66affSColin Finck } 3042c2c66affSColin Finck 3043c2c66affSColin Finck /* 3044c2c66affSColin Finck * @implemented 3045c2c66affSColin Finck */ 3046c2c66affSColin Finck PFILE_OBJECT 3047c2c66affSColin Finck NTAPI 3048c2c66affSColin Finck IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL, 3049c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL) 3050c2c66affSColin Finck { 3051c2c66affSColin Finck PFILE_OBJECT CreatedFileObject; 3052c2c66affSColin Finck NTSTATUS Status; 3053c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 3054c2c66affSColin Finck PAGED_CODE(); 3055c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 3056c2c66affSColin Finck 3057c2c66affSColin Finck /* Choose Device Object */ 3058c2c66affSColin Finck if (FileObject) DeviceObject = FileObject->DeviceObject; 3059c2c66affSColin Finck 3060c2c66affSColin Finck /* Reference the device object and initialize attributes */ 3061c2c66affSColin Finck InterlockedIncrement(&DeviceObject->ReferenceCount); 3062c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 3063c2c66affSColin Finck 3064c2c66affSColin Finck /* Create the File Object */ 3065c2c66affSColin Finck Status = ObCreateObject(KernelMode, 3066c2c66affSColin Finck IoFileObjectType, 3067c2c66affSColin Finck &ObjectAttributes, 3068c2c66affSColin Finck KernelMode, 3069c2c66affSColin Finck NULL, 3070c2c66affSColin Finck sizeof(FILE_OBJECT), 3071c2c66affSColin Finck sizeof(FILE_OBJECT), 3072c2c66affSColin Finck 0, 3073c2c66affSColin Finck (PVOID*)&CreatedFileObject); 3074c2c66affSColin Finck if (!NT_SUCCESS(Status)) 3075c2c66affSColin Finck { 3076c2c66affSColin Finck /* Fail */ 3077c2c66affSColin Finck IopDereferenceDeviceObject(DeviceObject, FALSE); 3078c2c66affSColin Finck ExRaiseStatus(Status); 3079c2c66affSColin Finck } 3080c2c66affSColin Finck 3081c2c66affSColin Finck /* Set File Object Data */ 3082c2c66affSColin Finck RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 3083c2c66affSColin Finck CreatedFileObject->DeviceObject = DeviceObject; 3084c2c66affSColin Finck CreatedFileObject->Type = IO_TYPE_FILE; 3085c2c66affSColin Finck CreatedFileObject->Size = sizeof(FILE_OBJECT); 3086c2c66affSColin Finck CreatedFileObject->Flags = FO_STREAM_FILE; 3087c2c66affSColin Finck 3088c2c66affSColin Finck /* Initialize the wait event */ 3089c2c66affSColin Finck KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 3090c2c66affSColin Finck 3091c2c66affSColin Finck /* Destroy create information */ 3092c2c66affSColin Finck ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject)-> 3093c2c66affSColin Finck ObjectCreateInfo); 3094c2c66affSColin Finck OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL; 3095c2c66affSColin Finck 3096c2c66affSColin Finck /* Set the handle created flag */ 3097c2c66affSColin Finck CreatedFileObject->Flags |= FO_HANDLE_CREATED; 3098c2c66affSColin Finck ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 3099c2c66affSColin Finck 3100c2c66affSColin Finck /* Check if we have a VPB */ 3101c2c66affSColin Finck if (DeviceObject->Vpb) 3102c2c66affSColin Finck { 3103c2c66affSColin Finck /* Reference it */ 3104c2c66affSColin Finck InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 3105c2c66affSColin Finck } 3106c2c66affSColin Finck 3107c2c66affSColin Finck /* Return the file object */ 3108c2c66affSColin Finck return CreatedFileObject; 3109c2c66affSColin Finck } 3110c2c66affSColin Finck 3111c2c66affSColin Finck /* 3112c2c66affSColin Finck * @implemented 3113c2c66affSColin Finck */ 3114c2c66affSColin Finck PGENERIC_MAPPING 3115c2c66affSColin Finck NTAPI 3116c2c66affSColin Finck IoGetFileObjectGenericMapping(VOID) 3117c2c66affSColin Finck { 3118c2c66affSColin Finck /* Return the mapping */ 3119c2c66affSColin Finck return &IopFileMapping; 3120c2c66affSColin Finck } 3121c2c66affSColin Finck 3122c2c66affSColin Finck /* 3123c2c66affSColin Finck * @implemented 3124c2c66affSColin Finck */ 3125c2c66affSColin Finck BOOLEAN 3126c2c66affSColin Finck NTAPI 3127c2c66affSColin Finck IoIsFileOriginRemote(IN PFILE_OBJECT FileObject) 3128c2c66affSColin Finck { 3129c2c66affSColin Finck /* Return the flag status */ 3130c2c66affSColin Finck return FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 3131c2c66affSColin Finck } 3132c2c66affSColin Finck 3133c2c66affSColin Finck /* 3134c2c66affSColin Finck * @implemented 3135c2c66affSColin Finck */ 3136c2c66affSColin Finck BOOLEAN 3137c2c66affSColin Finck NTAPI 3138c2c66affSColin Finck IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, 3139c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3140c2c66affSColin Finck IN ULONG OpenOptions, 3141c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatus, 3142c2c66affSColin Finck OUT PFILE_NETWORK_OPEN_INFORMATION Buffer) 3143c2c66affSColin Finck { 3144c2c66affSColin Finck NTSTATUS Status; 3145c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 3146c2c66affSColin Finck HANDLE Handle; 3147c2c66affSColin Finck OPEN_PACKET OpenPacket; 3148c2c66affSColin Finck PAGED_CODE(); 3149c2c66affSColin Finck IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 3150c2c66affSColin Finck 3151c2c66affSColin Finck /* Setup the Open Packet */ 3152c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 3153c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 3154c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 3155c2c66affSColin Finck OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT; 3156c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 3157c2c66affSColin Finck OpenPacket.Options = IO_FORCE_ACCESS_CHECK; 3158c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 3159c2c66affSColin Finck OpenPacket.NetworkInformation = Buffer; 3160c2c66affSColin Finck OpenPacket.QueryOnly = TRUE; 3161c2c66affSColin Finck OpenPacket.FullAttributes = TRUE; 3162c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 3163c2c66affSColin Finck 3164c2c66affSColin Finck /* 3165c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 3166c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 3167c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 3168c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 3169c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 3170c2c66affSColin Finck * by the Parse Check member. 3171c2c66affSColin Finck */ 3172c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 3173c2c66affSColin Finck NULL, 3174c2c66affSColin Finck KernelMode, 3175c2c66affSColin Finck NULL, 3176c2c66affSColin Finck DesiredAccess, 3177c2c66affSColin Finck &OpenPacket, 3178c2c66affSColin Finck &Handle); 3179c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) 3180c2c66affSColin Finck { 3181c2c66affSColin Finck /* Parse failed */ 3182c2c66affSColin Finck IoStatus->Status = Status; 3183c2c66affSColin Finck } 3184c2c66affSColin Finck else 3185c2c66affSColin Finck { 3186c2c66affSColin Finck /* Use the Io status */ 3187c2c66affSColin Finck IoStatus->Status = OpenPacket.FinalStatus; 3188c2c66affSColin Finck IoStatus->Information = OpenPacket.Information; 3189c2c66affSColin Finck } 3190c2c66affSColin Finck 3191c2c66affSColin Finck /* Return success */ 3192c2c66affSColin Finck return TRUE; 3193c2c66affSColin Finck } 3194c2c66affSColin Finck 3195c2c66affSColin Finck /* 3196c2c66affSColin Finck * @implemented 3197c2c66affSColin Finck */ 3198c2c66affSColin Finck VOID 3199c2c66affSColin Finck NTAPI 3200c2c66affSColin Finck IoUpdateShareAccess(IN PFILE_OBJECT FileObject, 3201c2c66affSColin Finck OUT PSHARE_ACCESS ShareAccess) 3202c2c66affSColin Finck { 3203c2c66affSColin Finck PAGED_CODE(); 3204c2c66affSColin Finck 3205c2c66affSColin Finck /* Check if the file has an extension */ 3206c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3207c2c66affSColin Finck { 3208c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3209c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3210c2c66affSColin Finck { 3211c2c66affSColin Finck /* Don't update share access */ 3212c2c66affSColin Finck return; 3213c2c66affSColin Finck } 3214c2c66affSColin Finck } 3215c2c66affSColin Finck 3216c2c66affSColin Finck /* Otherwise, check if there's any access present */ 3217c2c66affSColin Finck if ((FileObject->ReadAccess) || 3218c2c66affSColin Finck (FileObject->WriteAccess) || 3219c2c66affSColin Finck (FileObject->DeleteAccess)) 3220c2c66affSColin Finck { 3221c2c66affSColin Finck /* Increase the open count */ 3222c2c66affSColin Finck ShareAccess->OpenCount++; 3223c2c66affSColin Finck 3224c2c66affSColin Finck /* Add new share access */ 3225c2c66affSColin Finck ShareAccess->Readers += FileObject->ReadAccess; 3226c2c66affSColin Finck ShareAccess->Writers += FileObject->WriteAccess; 3227c2c66affSColin Finck ShareAccess->Deleters += FileObject->DeleteAccess; 3228c2c66affSColin Finck ShareAccess->SharedRead += FileObject->SharedRead; 3229c2c66affSColin Finck ShareAccess->SharedWrite += FileObject->SharedWrite; 3230c2c66affSColin Finck ShareAccess->SharedDelete += FileObject->SharedDelete; 3231c2c66affSColin Finck } 3232c2c66affSColin Finck } 3233c2c66affSColin Finck 3234c2c66affSColin Finck /* 3235c2c66affSColin Finck * @implemented 3236c2c66affSColin Finck */ 3237c2c66affSColin Finck NTSTATUS 3238c2c66affSColin Finck NTAPI 3239c2c66affSColin Finck IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, 3240c2c66affSColin Finck IN ULONG DesiredShareAccess, 3241c2c66affSColin Finck IN PFILE_OBJECT FileObject, 3242c2c66affSColin Finck IN PSHARE_ACCESS ShareAccess, 3243c2c66affSColin Finck IN BOOLEAN Update) 3244c2c66affSColin Finck { 3245c2c66affSColin Finck BOOLEAN ReadAccess; 3246c2c66affSColin Finck BOOLEAN WriteAccess; 3247c2c66affSColin Finck BOOLEAN DeleteAccess; 3248c2c66affSColin Finck BOOLEAN SharedRead; 3249c2c66affSColin Finck BOOLEAN SharedWrite; 3250c2c66affSColin Finck BOOLEAN SharedDelete; 3251c2c66affSColin Finck PAGED_CODE(); 3252c2c66affSColin Finck 3253c2c66affSColin Finck /* Get access masks */ 3254c2c66affSColin Finck ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 3255c2c66affSColin Finck WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 3256c2c66affSColin Finck DeleteAccess = (DesiredAccess & DELETE) != 0; 3257c2c66affSColin Finck 3258c2c66affSColin Finck /* Set them in the file object */ 3259c2c66affSColin Finck FileObject->ReadAccess = ReadAccess; 3260c2c66affSColin Finck FileObject->WriteAccess = WriteAccess; 3261c2c66affSColin Finck FileObject->DeleteAccess = DeleteAccess; 3262c2c66affSColin Finck 3263c2c66affSColin Finck /* Check if the file has an extension */ 3264c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3265c2c66affSColin Finck { 3266c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3267c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3268c2c66affSColin Finck { 3269c2c66affSColin Finck /* Don't check share access */ 3270c2c66affSColin Finck return STATUS_SUCCESS; 3271c2c66affSColin Finck } 3272c2c66affSColin Finck } 3273c2c66affSColin Finck 3274c2c66affSColin Finck /* Check if we have any access */ 3275c2c66affSColin Finck if ((ReadAccess) || (WriteAccess) || (DeleteAccess)) 3276c2c66affSColin Finck { 3277c2c66affSColin Finck /* Get shared access masks */ 3278c2c66affSColin Finck SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 3279c2c66affSColin Finck SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 3280c2c66affSColin Finck SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 3281c2c66affSColin Finck 3282c2c66affSColin Finck /* Set them */ 3283c2c66affSColin Finck FileObject->SharedRead = SharedRead; 3284c2c66affSColin Finck FileObject->SharedWrite = SharedWrite; 3285c2c66affSColin Finck FileObject->SharedDelete = SharedDelete; 3286c2c66affSColin Finck 3287c2c66affSColin Finck /* Check if the shared access is violated */ 3288c2c66affSColin Finck if ((ReadAccess && 3289c2c66affSColin Finck (ShareAccess->SharedRead < ShareAccess->OpenCount)) || 3290c2c66affSColin Finck (WriteAccess && 3291c2c66affSColin Finck (ShareAccess->SharedWrite < ShareAccess->OpenCount)) || 3292c2c66affSColin Finck (DeleteAccess && 3293c2c66affSColin Finck (ShareAccess->SharedDelete < ShareAccess->OpenCount)) || 3294c2c66affSColin Finck ((ShareAccess->Readers != 0) && !SharedRead) || 3295c2c66affSColin Finck ((ShareAccess->Writers != 0) && !SharedWrite) || 3296c2c66affSColin Finck ((ShareAccess->Deleters != 0) && !SharedDelete)) 3297c2c66affSColin Finck { 3298c2c66affSColin Finck /* Sharing violation, fail */ 3299c2c66affSColin Finck return STATUS_SHARING_VIOLATION; 3300c2c66affSColin Finck } 3301c2c66affSColin Finck 3302c2c66affSColin Finck /* It's not, check if caller wants us to update it */ 3303c2c66affSColin Finck if (Update) 3304c2c66affSColin Finck { 3305c2c66affSColin Finck /* Increase open count */ 3306c2c66affSColin Finck ShareAccess->OpenCount++; 3307c2c66affSColin Finck 3308c2c66affSColin Finck /* Update shared access */ 3309c2c66affSColin Finck ShareAccess->Readers += ReadAccess; 3310c2c66affSColin Finck ShareAccess->Writers += WriteAccess; 3311c2c66affSColin Finck ShareAccess->Deleters += DeleteAccess; 3312c2c66affSColin Finck ShareAccess->SharedRead += SharedRead; 3313c2c66affSColin Finck ShareAccess->SharedWrite += SharedWrite; 3314c2c66affSColin Finck ShareAccess->SharedDelete += SharedDelete; 3315c2c66affSColin Finck } 3316c2c66affSColin Finck } 3317c2c66affSColin Finck 3318c2c66affSColin Finck /* Validation successful */ 3319c2c66affSColin Finck return STATUS_SUCCESS; 3320c2c66affSColin Finck } 3321c2c66affSColin Finck 3322c2c66affSColin Finck /* 3323c2c66affSColin Finck * @implemented 3324c2c66affSColin Finck */ 3325c2c66affSColin Finck VOID 3326c2c66affSColin Finck NTAPI 3327c2c66affSColin Finck IoRemoveShareAccess(IN PFILE_OBJECT FileObject, 3328c2c66affSColin Finck IN PSHARE_ACCESS ShareAccess) 3329c2c66affSColin Finck { 3330c2c66affSColin Finck PAGED_CODE(); 3331c2c66affSColin Finck 3332c2c66affSColin Finck /* Check if the file has an extension */ 3333c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3334c2c66affSColin Finck { 3335c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3336c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3337c2c66affSColin Finck { 3338c2c66affSColin Finck /* Don't update share access */ 3339c2c66affSColin Finck return; 3340c2c66affSColin Finck } 3341c2c66affSColin Finck } 3342c2c66affSColin Finck 3343c2c66affSColin Finck /* Otherwise, check if there's any access present */ 3344c2c66affSColin Finck if ((FileObject->ReadAccess) || 3345c2c66affSColin Finck (FileObject->WriteAccess) || 3346c2c66affSColin Finck (FileObject->DeleteAccess)) 3347c2c66affSColin Finck { 3348c2c66affSColin Finck /* Decrement the open count */ 3349c2c66affSColin Finck ShareAccess->OpenCount--; 3350c2c66affSColin Finck 3351c2c66affSColin Finck /* Remove share access */ 3352c2c66affSColin Finck ShareAccess->Readers -= FileObject->ReadAccess; 3353c2c66affSColin Finck ShareAccess->Writers -= FileObject->WriteAccess; 3354c2c66affSColin Finck ShareAccess->Deleters -= FileObject->DeleteAccess; 3355c2c66affSColin Finck ShareAccess->SharedRead -= FileObject->SharedRead; 3356c2c66affSColin Finck ShareAccess->SharedWrite -= FileObject->SharedWrite; 3357c2c66affSColin Finck ShareAccess->SharedDelete -= FileObject->SharedDelete; 3358c2c66affSColin Finck } 3359c2c66affSColin Finck } 3360c2c66affSColin Finck 3361c2c66affSColin Finck /* 3362c2c66affSColin Finck * @implemented 3363c2c66affSColin Finck */ 3364c2c66affSColin Finck VOID 3365c2c66affSColin Finck NTAPI 3366c2c66affSColin Finck IoSetShareAccess(IN ACCESS_MASK DesiredAccess, 3367c2c66affSColin Finck IN ULONG DesiredShareAccess, 3368c2c66affSColin Finck IN PFILE_OBJECT FileObject, 3369c2c66affSColin Finck OUT PSHARE_ACCESS ShareAccess) 3370c2c66affSColin Finck { 3371c2c66affSColin Finck BOOLEAN ReadAccess; 3372c2c66affSColin Finck BOOLEAN WriteAccess; 3373c2c66affSColin Finck BOOLEAN DeleteAccess; 3374c2c66affSColin Finck BOOLEAN SharedRead; 3375c2c66affSColin Finck BOOLEAN SharedWrite; 3376c2c66affSColin Finck BOOLEAN SharedDelete; 3377c2c66affSColin Finck BOOLEAN Update = TRUE; 3378c2c66affSColin Finck PAGED_CODE(); 3379c2c66affSColin Finck 3380c2c66affSColin Finck ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 3381c2c66affSColin Finck WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 3382c2c66affSColin Finck DeleteAccess = (DesiredAccess & DELETE) != 0; 3383c2c66affSColin Finck 3384c2c66affSColin Finck /* Check if the file has an extension */ 3385c2c66affSColin Finck if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 3386c2c66affSColin Finck { 3387c2c66affSColin Finck /* Check if caller specified to ignore access checks */ 3388c2c66affSColin Finck //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 3389c2c66affSColin Finck { 3390c2c66affSColin Finck /* Don't update share access */ 3391c2c66affSColin Finck Update = FALSE; 3392c2c66affSColin Finck } 3393c2c66affSColin Finck } 3394c2c66affSColin Finck 3395c2c66affSColin Finck /* Update basic access */ 3396c2c66affSColin Finck FileObject->ReadAccess = ReadAccess; 3397c2c66affSColin Finck FileObject->WriteAccess = WriteAccess; 3398c2c66affSColin Finck FileObject->DeleteAccess = DeleteAccess; 3399c2c66affSColin Finck 3400c2c66affSColin Finck /* Check if we have no access as all */ 3401c2c66affSColin Finck if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess)) 3402c2c66affSColin Finck { 3403c2c66affSColin Finck /* Check if we need to update the structure */ 3404c2c66affSColin Finck if (!Update) return; 3405c2c66affSColin Finck 3406c2c66affSColin Finck /* Otherwise, clear data */ 3407c2c66affSColin Finck ShareAccess->OpenCount = 0; 3408c2c66affSColin Finck ShareAccess->Readers = 0; 3409c2c66affSColin Finck ShareAccess->Writers = 0; 3410c2c66affSColin Finck ShareAccess->Deleters = 0; 3411c2c66affSColin Finck ShareAccess->SharedRead = 0; 3412c2c66affSColin Finck ShareAccess->SharedWrite = 0; 3413c2c66affSColin Finck ShareAccess->SharedDelete = 0; 3414c2c66affSColin Finck } 3415c2c66affSColin Finck else 3416c2c66affSColin Finck { 3417c2c66affSColin Finck /* Calculate shared access */ 3418c2c66affSColin Finck SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 3419c2c66affSColin Finck SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 3420c2c66affSColin Finck SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 3421c2c66affSColin Finck 3422c2c66affSColin Finck /* Set it in the FO */ 3423c2c66affSColin Finck FileObject->SharedRead = SharedRead; 3424c2c66affSColin Finck FileObject->SharedWrite = SharedWrite; 3425c2c66affSColin Finck FileObject->SharedDelete = SharedDelete; 3426c2c66affSColin Finck 3427c2c66affSColin Finck /* Check if we need to update the structure */ 3428c2c66affSColin Finck if (!Update) return; 3429c2c66affSColin Finck 3430c2c66affSColin Finck /* Otherwise, set data */ 3431c2c66affSColin Finck ShareAccess->OpenCount = 1; 3432c2c66affSColin Finck ShareAccess->Readers = ReadAccess; 3433c2c66affSColin Finck ShareAccess->Writers = WriteAccess; 3434c2c66affSColin Finck ShareAccess->Deleters = DeleteAccess; 3435c2c66affSColin Finck ShareAccess->SharedRead = SharedRead; 3436c2c66affSColin Finck ShareAccess->SharedWrite = SharedWrite; 3437c2c66affSColin Finck ShareAccess->SharedDelete = SharedDelete; 3438c2c66affSColin Finck } 3439c2c66affSColin Finck } 3440c2c66affSColin Finck 3441c2c66affSColin Finck /* 3442c2c66affSColin Finck * @implemented 3443c2c66affSColin Finck */ 3444c2c66affSColin Finck VOID 3445c2c66affSColin Finck NTAPI 3446c2c66affSColin Finck IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject, 3447c2c66affSColin Finck IN PFILE_OBJECT FileObject) 3448c2c66affSColin Finck { 3449c2c66affSColin Finck PIRP Irp; 3450c2c66affSColin Finck KEVENT Event; 3451c2c66affSColin Finck KIRQL OldIrql; 3452c2c66affSColin Finck NTSTATUS Status; 3453c2c66affSColin Finck PIO_STACK_LOCATION Stack; 3454c2c66affSColin Finck 3455c2c66affSColin Finck /* Check if handles were already created for the 3456c2c66affSColin Finck * open file. If so, that's over. 3457c2c66affSColin Finck */ 3458c2c66affSColin Finck if (FileObject->Flags & FO_HANDLE_CREATED) 3459c2c66affSColin Finck KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN, 3460c2c66affSColin Finck (ULONG_PTR)FileObject, 3461c2c66affSColin Finck (ULONG_PTR)DeviceObject, 0, 0); 3462c2c66affSColin Finck 3463c2c66affSColin Finck /* Reset the events */ 3464c2c66affSColin Finck KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 3465c2c66affSColin Finck KeClearEvent(&FileObject->Event); 3466c2c66affSColin Finck 3467c2c66affSColin Finck /* Allocate the IRP we'll use */ 3468c2c66affSColin Finck Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); 3469c2c66affSColin Finck /* Properly set it */ 3470c2c66affSColin Finck Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 3471c2c66affSColin Finck Irp->UserEvent = &Event; 3472c2c66affSColin Finck Irp->UserIosb = &Irp->IoStatus; 3473c2c66affSColin Finck Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 3474c2c66affSColin Finck Irp->Tail.Overlay.OriginalFileObject = FileObject; 3475c2c66affSColin Finck Irp->RequestorMode = KernelMode; 3476c2c66affSColin Finck Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 3477c2c66affSColin Finck 3478c2c66affSColin Finck Stack = IoGetNextIrpStackLocation(Irp); 3479c2c66affSColin Finck Stack->MajorFunction = IRP_MJ_CLEANUP; 3480c2c66affSColin Finck Stack->FileObject = FileObject; 3481c2c66affSColin Finck 3482c2c66affSColin Finck /* Put on top of IRPs list of the thread */ 3483c2c66affSColin Finck IopQueueIrpToThread(Irp); 3484c2c66affSColin Finck 3485c2c66affSColin Finck /* Call the driver */ 3486c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 3487c2c66affSColin Finck if (Status == STATUS_PENDING) 3488c2c66affSColin Finck { 3489c2c66affSColin Finck KeWaitForSingleObject(&Event, UserRequest, 3490c2c66affSColin Finck KernelMode, FALSE, NULL); 3491c2c66affSColin Finck } 3492c2c66affSColin Finck 3493c2c66affSColin Finck /* Remove from IRPs list */ 3494c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3495c2c66affSColin Finck IopUnQueueIrpFromThread(Irp); 3496c2c66affSColin Finck KeLowerIrql(OldIrql); 3497c2c66affSColin Finck 3498c2c66affSColin Finck /* Free the IRP */ 3499c2c66affSColin Finck IoFreeIrp(Irp); 3500c2c66affSColin Finck 3501c2c66affSColin Finck /* Clear the event */ 3502c2c66affSColin Finck KeClearEvent(&FileObject->Event); 3503c2c66affSColin Finck /* And finally, mark the open operation as canceled */ 3504c2c66affSColin Finck FileObject->Flags |= FO_FILE_OPEN_CANCELLED; 3505c2c66affSColin Finck } 3506c2c66affSColin Finck 3507c2c66affSColin Finck /* 35084a7e8977SPierre Schweitzer * @implemented 3509c2c66affSColin Finck */ 3510c2c66affSColin Finck NTSTATUS 3511c2c66affSColin Finck NTAPI 3512c2c66affSColin Finck IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject, 3513c2c66affSColin Finck OUT POBJECT_NAME_INFORMATION *ObjectNameInformation) 3514c2c66affSColin Finck { 35154a7e8977SPierre Schweitzer NTSTATUS Status; 35164a7e8977SPierre Schweitzer ULONG Length, ReturnLength; 35174a7e8977SPierre Schweitzer POBJECT_NAME_INFORMATION LocalInfo; 35184a7e8977SPierre Schweitzer 35194a7e8977SPierre Schweitzer /* Start with a buffer length of 200 */ 35204a7e8977SPierre Schweitzer ReturnLength = 200; 35214a7e8977SPierre Schweitzer /* 35224a7e8977SPierre Schweitzer * We'll loop until query works. 35234a7e8977SPierre Schweitzer * We will use returned length for next loop 35244a7e8977SPierre Schweitzer * iteration, trying to have a big enough buffer. 35254a7e8977SPierre Schweitzer */ 35264a7e8977SPierre Schweitzer for (Length = 200; ; Length = ReturnLength) 35274a7e8977SPierre Schweitzer { 35284a7e8977SPierre Schweitzer /* Allocate our work buffer */ 35294a7e8977SPierre Schweitzer LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, 'nDoI'); 35304a7e8977SPierre Schweitzer if (LocalInfo == NULL) 35314a7e8977SPierre Schweitzer { 35324a7e8977SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 35334a7e8977SPierre Schweitzer } 35344a7e8977SPierre Schweitzer 35354a7e8977SPierre Schweitzer /* Query the DOS name */ 35364a7e8977SPierre Schweitzer Status = IopQueryNameInternal(FileObject, 35374a7e8977SPierre Schweitzer TRUE, 35384a7e8977SPierre Schweitzer TRUE, 35394a7e8977SPierre Schweitzer LocalInfo, 35404a7e8977SPierre Schweitzer Length, 35414a7e8977SPierre Schweitzer &ReturnLength, 35424a7e8977SPierre Schweitzer KernelMode); 35434a7e8977SPierre Schweitzer /* If it succeed, nothing more to do */ 35444a7e8977SPierre Schweitzer if (Status == STATUS_SUCCESS) 35454a7e8977SPierre Schweitzer { 35464a7e8977SPierre Schweitzer break; 35474a7e8977SPierre Schweitzer } 35484a7e8977SPierre Schweitzer 35494a7e8977SPierre Schweitzer /* Otherwise, prepare for re-allocation */ 35504a7e8977SPierre Schweitzer ExFreePoolWithTag(LocalInfo, 'nDoI'); 35514a7e8977SPierre Schweitzer 35524a7e8977SPierre Schweitzer /* 35534a7e8977SPierre Schweitzer * If we failed because of something else 35544a7e8977SPierre Schweitzer * than memory, simply stop and fail here 35554a7e8977SPierre Schweitzer */ 35564a7e8977SPierre Schweitzer if (Status != STATUS_BUFFER_OVERFLOW) 35574a7e8977SPierre Schweitzer { 35584a7e8977SPierre Schweitzer return STATUS_BUFFER_OVERFLOW; 35594a7e8977SPierre Schweitzer } 35604a7e8977SPierre Schweitzer } 35614a7e8977SPierre Schweitzer 35624a7e8977SPierre Schweitzer /* Success case here: return our buffer */ 35634a7e8977SPierre Schweitzer *ObjectNameInformation = LocalInfo; 35644a7e8977SPierre Schweitzer return STATUS_SUCCESS; 3565c2c66affSColin Finck } 3566c2c66affSColin Finck 3567c2c66affSColin Finck /* 3568c2c66affSColin Finck * @implemented 3569c2c66affSColin Finck */ 3570c2c66affSColin Finck NTSTATUS 3571c2c66affSColin Finck NTAPI 3572c2c66affSColin Finck IoSetFileOrigin(IN PFILE_OBJECT FileObject, 3573c2c66affSColin Finck IN BOOLEAN Remote) 3574c2c66affSColin Finck { 3575c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 3576c2c66affSColin Finck BOOLEAN FlagSet; 3577c2c66affSColin Finck 3578c2c66affSColin Finck /* Get the flag status */ 3579c2c66affSColin Finck FlagSet = FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 3580c2c66affSColin Finck 3581c2c66affSColin Finck /* Don't set the flag if it was set already, and don't remove it if it wasn't set */ 3582c2c66affSColin Finck if (Remote && !FlagSet) 3583c2c66affSColin Finck { 3584c2c66affSColin Finck /* Set the flag */ 3585c2c66affSColin Finck FileObject->Flags |= FO_REMOTE_ORIGIN; 3586c2c66affSColin Finck } 3587c2c66affSColin Finck else if (!Remote && FlagSet) 3588c2c66affSColin Finck { 3589c2c66affSColin Finck /* Remove the flag */ 3590c2c66affSColin Finck FileObject->Flags &= ~FO_REMOTE_ORIGIN; 3591c2c66affSColin Finck } 3592c2c66affSColin Finck else 3593c2c66affSColin Finck { 3594c2c66affSColin Finck /* Fail */ 3595c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER_MIX; 3596c2c66affSColin Finck } 3597c2c66affSColin Finck 3598c2c66affSColin Finck /* Return status */ 3599c2c66affSColin Finck return Status; 3600c2c66affSColin Finck } 3601c2c66affSColin Finck 3602c2c66affSColin Finck /* 3603c2c66affSColin Finck * @implemented 3604c2c66affSColin Finck */ 3605c2c66affSColin Finck NTSTATUS 3606c2c66affSColin Finck NTAPI 3607c2c66affSColin Finck NtCreateFile(PHANDLE FileHandle, 3608c2c66affSColin Finck ACCESS_MASK DesiredAccess, 3609c2c66affSColin Finck POBJECT_ATTRIBUTES ObjectAttributes, 3610c2c66affSColin Finck PIO_STATUS_BLOCK IoStatusBlock, 3611c2c66affSColin Finck PLARGE_INTEGER AllocateSize, 3612c2c66affSColin Finck ULONG FileAttributes, 3613c2c66affSColin Finck ULONG ShareAccess, 3614c2c66affSColin Finck ULONG CreateDisposition, 3615c2c66affSColin Finck ULONG CreateOptions, 3616c2c66affSColin Finck PVOID EaBuffer, 3617c2c66affSColin Finck ULONG EaLength) 3618c2c66affSColin Finck { 3619c2c66affSColin Finck /* Call the I/O Function */ 3620c2c66affSColin Finck return IoCreateFile(FileHandle, 3621c2c66affSColin Finck DesiredAccess, 3622c2c66affSColin Finck ObjectAttributes, 3623c2c66affSColin Finck IoStatusBlock, 3624c2c66affSColin Finck AllocateSize, 3625c2c66affSColin Finck FileAttributes, 3626c2c66affSColin Finck ShareAccess, 3627c2c66affSColin Finck CreateDisposition, 3628c2c66affSColin Finck CreateOptions, 3629c2c66affSColin Finck EaBuffer, 3630c2c66affSColin Finck EaLength, 3631c2c66affSColin Finck CreateFileTypeNone, 3632c2c66affSColin Finck NULL, 3633c2c66affSColin Finck 0); 3634c2c66affSColin Finck } 3635c2c66affSColin Finck 3636c2c66affSColin Finck NTSTATUS 3637c2c66affSColin Finck NTAPI 3638c2c66affSColin Finck NtCreateMailslotFile(OUT PHANDLE FileHandle, 3639c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3640c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 3641c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 3642c2c66affSColin Finck IN ULONG CreateOptions, 3643c2c66affSColin Finck IN ULONG MailslotQuota, 3644c2c66affSColin Finck IN ULONG MaxMessageSize, 3645c2c66affSColin Finck IN PLARGE_INTEGER TimeOut) 3646c2c66affSColin Finck { 3647c2c66affSColin Finck MAILSLOT_CREATE_PARAMETERS Buffer; 3648c2c66affSColin Finck PAGED_CODE(); 3649c2c66affSColin Finck 3650c2c66affSColin Finck /* Check for Timeout */ 3651c2c66affSColin Finck if (TimeOut) 3652c2c66affSColin Finck { 3653c2c66affSColin Finck /* check if the call came from user mode */ 3654c2c66affSColin Finck if (KeGetPreviousMode() != KernelMode) 3655c2c66affSColin Finck { 3656c2c66affSColin Finck /* Enter SEH for Probe */ 3657c2c66affSColin Finck _SEH2_TRY 3658c2c66affSColin Finck { 3659c2c66affSColin Finck /* Probe the timeout */ 3660c2c66affSColin Finck Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut); 3661c2c66affSColin Finck } 3662c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3663c2c66affSColin Finck { 3664c2c66affSColin Finck /* Return the exception code */ 3665c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3666c2c66affSColin Finck } 3667c2c66affSColin Finck _SEH2_END; 3668c2c66affSColin Finck } 3669c2c66affSColin Finck else 3670c2c66affSColin Finck { 3671c2c66affSColin Finck /* Otherwise, capture directly */ 3672c2c66affSColin Finck Buffer.ReadTimeout = *TimeOut; 3673c2c66affSColin Finck } 3674c2c66affSColin Finck 3675c2c66affSColin Finck /* Set the correct setting */ 3676c2c66affSColin Finck Buffer.TimeoutSpecified = TRUE; 3677c2c66affSColin Finck } 3678c2c66affSColin Finck else 3679c2c66affSColin Finck { 3680c2c66affSColin Finck /* Tell the FSD we don't have a timeout */ 3681c2c66affSColin Finck Buffer.TimeoutSpecified = FALSE; 3682c2c66affSColin Finck } 3683c2c66affSColin Finck 3684c2c66affSColin Finck /* Set Settings */ 3685c2c66affSColin Finck Buffer.MailslotQuota = MailslotQuota; 3686c2c66affSColin Finck Buffer.MaximumMessageSize = MaxMessageSize; 3687c2c66affSColin Finck 3688c2c66affSColin Finck /* Call I/O */ 3689c2c66affSColin Finck return IoCreateFile(FileHandle, 3690c2c66affSColin Finck DesiredAccess, 3691c2c66affSColin Finck ObjectAttributes, 3692c2c66affSColin Finck IoStatusBlock, 3693c2c66affSColin Finck NULL, 3694c2c66affSColin Finck 0, 3695c2c66affSColin Finck FILE_SHARE_READ | FILE_SHARE_WRITE, 3696c2c66affSColin Finck FILE_CREATE, 3697c2c66affSColin Finck CreateOptions, 3698c2c66affSColin Finck NULL, 3699c2c66affSColin Finck 0, 3700c2c66affSColin Finck CreateFileTypeMailslot, 3701c2c66affSColin Finck (PVOID)&Buffer, 3702c2c66affSColin Finck 0); 3703c2c66affSColin Finck } 3704c2c66affSColin Finck 3705c2c66affSColin Finck NTSTATUS 3706c2c66affSColin Finck NTAPI 3707c2c66affSColin Finck NtCreateNamedPipeFile(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 CreateDisposition, 3713c2c66affSColin Finck IN ULONG CreateOptions, 3714c2c66affSColin Finck IN ULONG NamedPipeType, 3715c2c66affSColin Finck IN ULONG ReadMode, 3716c2c66affSColin Finck IN ULONG CompletionMode, 3717c2c66affSColin Finck IN ULONG MaximumInstances, 3718c2c66affSColin Finck IN ULONG InboundQuota, 3719c2c66affSColin Finck IN ULONG OutboundQuota, 3720c2c66affSColin Finck IN PLARGE_INTEGER DefaultTimeout) 3721c2c66affSColin Finck { 3722c2c66affSColin Finck NAMED_PIPE_CREATE_PARAMETERS Buffer; 3723c2c66affSColin Finck PAGED_CODE(); 3724c2c66affSColin Finck 3725c2c66affSColin Finck /* Check for Timeout */ 3726c2c66affSColin Finck if (DefaultTimeout) 3727c2c66affSColin Finck { 3728c2c66affSColin Finck /* check if the call came from user mode */ 3729c2c66affSColin Finck if (KeGetPreviousMode() != KernelMode) 3730c2c66affSColin Finck { 3731c2c66affSColin Finck /* Enter SEH for Probe */ 3732c2c66affSColin Finck _SEH2_TRY 3733c2c66affSColin Finck { 3734c2c66affSColin Finck /* Probe the timeout */ 3735c2c66affSColin Finck Buffer.DefaultTimeout = 3736c2c66affSColin Finck ProbeForReadLargeInteger(DefaultTimeout); 3737c2c66affSColin Finck } 3738c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3739c2c66affSColin Finck { 3740c2c66affSColin Finck /* Return the exception code */ 3741c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3742c2c66affSColin Finck } 3743c2c66affSColin Finck _SEH2_END; 3744c2c66affSColin Finck } 3745c2c66affSColin Finck else 3746c2c66affSColin Finck { 3747c2c66affSColin Finck /* Otherwise, capture directly */ 3748c2c66affSColin Finck Buffer.DefaultTimeout = *DefaultTimeout; 3749c2c66affSColin Finck } 3750c2c66affSColin Finck 3751c2c66affSColin Finck /* Set the correct setting */ 3752c2c66affSColin Finck Buffer.TimeoutSpecified = TRUE; 3753c2c66affSColin Finck } 3754c2c66affSColin Finck else 3755c2c66affSColin Finck { 3756c2c66affSColin Finck /* Tell the FSD we don't have a timeout */ 3757c2c66affSColin Finck Buffer.TimeoutSpecified = FALSE; 3758c2c66affSColin Finck } 3759c2c66affSColin Finck 3760c2c66affSColin Finck /* Set Settings */ 3761c2c66affSColin Finck Buffer.NamedPipeType = NamedPipeType; 3762c2c66affSColin Finck Buffer.ReadMode = ReadMode; 3763c2c66affSColin Finck Buffer.CompletionMode = CompletionMode; 3764c2c66affSColin Finck Buffer.MaximumInstances = MaximumInstances; 3765c2c66affSColin Finck Buffer.InboundQuota = InboundQuota; 3766c2c66affSColin Finck Buffer.OutboundQuota = OutboundQuota; 3767c2c66affSColin Finck 3768c2c66affSColin Finck /* Call I/O */ 3769c2c66affSColin Finck return IoCreateFile(FileHandle, 3770c2c66affSColin Finck DesiredAccess, 3771c2c66affSColin Finck ObjectAttributes, 3772c2c66affSColin Finck IoStatusBlock, 3773c2c66affSColin Finck NULL, 3774c2c66affSColin Finck 0, 3775c2c66affSColin Finck ShareAccess, 3776c2c66affSColin Finck CreateDisposition, 3777c2c66affSColin Finck CreateOptions, 3778c2c66affSColin Finck NULL, 3779c2c66affSColin Finck 0, 3780c2c66affSColin Finck CreateFileTypeNamedPipe, 3781c2c66affSColin Finck (PVOID)&Buffer, 3782c2c66affSColin Finck 0); 3783c2c66affSColin Finck } 3784c2c66affSColin Finck 3785c2c66affSColin Finck NTSTATUS 3786c2c66affSColin Finck NTAPI 3787c2c66affSColin Finck NtFlushWriteBuffer(VOID) 3788c2c66affSColin Finck { 3789c2c66affSColin Finck PAGED_CODE(); 3790c2c66affSColin Finck 3791c2c66affSColin Finck /* Call the kernel */ 3792c2c66affSColin Finck KeFlushWriteBuffer(); 3793c2c66affSColin Finck return STATUS_SUCCESS; 3794c2c66affSColin Finck } 3795c2c66affSColin Finck 3796c2c66affSColin Finck /* 3797c2c66affSColin Finck * @implemented 3798c2c66affSColin Finck */ 3799c2c66affSColin Finck NTSTATUS 3800c2c66affSColin Finck NTAPI 3801c2c66affSColin Finck NtOpenFile(OUT PHANDLE FileHandle, 3802c2c66affSColin Finck IN ACCESS_MASK DesiredAccess, 3803c2c66affSColin Finck IN POBJECT_ATTRIBUTES ObjectAttributes, 3804c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock, 3805c2c66affSColin Finck IN ULONG ShareAccess, 3806c2c66affSColin Finck IN ULONG OpenOptions) 3807c2c66affSColin Finck { 3808c2c66affSColin Finck /* Call the I/O Function */ 3809c2c66affSColin Finck return IoCreateFile(FileHandle, 3810c2c66affSColin Finck DesiredAccess, 3811c2c66affSColin Finck ObjectAttributes, 3812c2c66affSColin Finck IoStatusBlock, 3813c2c66affSColin Finck NULL, 3814c2c66affSColin Finck 0, 3815c2c66affSColin Finck ShareAccess, 3816c2c66affSColin Finck FILE_OPEN, 3817c2c66affSColin Finck OpenOptions, 3818c2c66affSColin Finck NULL, 3819c2c66affSColin Finck 0, 3820c2c66affSColin Finck CreateFileTypeNone, 3821c2c66affSColin Finck NULL, 3822c2c66affSColin Finck 0); 3823c2c66affSColin Finck } 3824c2c66affSColin Finck 3825c2c66affSColin Finck NTSTATUS 3826c2c66affSColin Finck NTAPI 3827c2c66affSColin Finck NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 3828c2c66affSColin Finck OUT PFILE_BASIC_INFORMATION FileInformation) 3829c2c66affSColin Finck { 3830c2c66affSColin Finck /* Call the internal helper API */ 3831c2c66affSColin Finck return IopQueryAttributesFile(ObjectAttributes, 3832c2c66affSColin Finck FileBasicInformation, 3833c2c66affSColin Finck sizeof(FILE_BASIC_INFORMATION), 3834c2c66affSColin Finck FileInformation); 3835c2c66affSColin Finck } 3836c2c66affSColin Finck 3837c2c66affSColin Finck NTSTATUS 3838c2c66affSColin Finck NTAPI 3839c2c66affSColin Finck NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 3840c2c66affSColin Finck OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation) 3841c2c66affSColin Finck { 3842c2c66affSColin Finck /* Call the internal helper API */ 3843c2c66affSColin Finck return IopQueryAttributesFile(ObjectAttributes, 3844c2c66affSColin Finck FileNetworkOpenInformation, 3845c2c66affSColin Finck sizeof(FILE_NETWORK_OPEN_INFORMATION), 3846c2c66affSColin Finck FileInformation); 3847c2c66affSColin Finck } 3848c2c66affSColin Finck 3849c2c66affSColin Finck /** 3850c2c66affSColin Finck * @name NtCancelIoFile 3851c2c66affSColin Finck * 3852c2c66affSColin Finck * Cancel all pending I/O operations in the current thread for specified 3853c2c66affSColin Finck * file object. 3854c2c66affSColin Finck * 3855c2c66affSColin Finck * @param FileHandle 3856c2c66affSColin Finck * Handle to file object to cancel requests for. No specific 3857c2c66affSColin Finck * access rights are needed. 3858c2c66affSColin Finck * @param IoStatusBlock 3859c2c66affSColin Finck * Pointer to status block which is filled with final completition 3860c2c66affSColin Finck * status on successful return. 3861c2c66affSColin Finck * 3862c2c66affSColin Finck * @return Status. 3863c2c66affSColin Finck * 3864c2c66affSColin Finck * @implemented 3865c2c66affSColin Finck */ 3866c2c66affSColin Finck NTSTATUS 3867c2c66affSColin Finck NTAPI 3868c2c66affSColin Finck NtCancelIoFile(IN HANDLE FileHandle, 3869c2c66affSColin Finck OUT PIO_STATUS_BLOCK IoStatusBlock) 3870c2c66affSColin Finck { 3871c2c66affSColin Finck PFILE_OBJECT FileObject; 3872c2c66affSColin Finck PETHREAD Thread; 3873c2c66affSColin Finck PIRP Irp; 3874c2c66affSColin Finck KIRQL OldIrql; 3875c2c66affSColin Finck BOOLEAN OurIrpsInList = FALSE; 3876c2c66affSColin Finck LARGE_INTEGER Interval; 3877c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 3878c2c66affSColin Finck NTSTATUS Status; 3879c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry; 3880c2c66affSColin Finck PAGED_CODE(); 3881c2c66affSColin Finck IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 3882c2c66affSColin Finck 3883c2c66affSColin Finck /* Check the previous mode */ 3884c2c66affSColin Finck if (PreviousMode != KernelMode) 3885c2c66affSColin Finck { 3886c2c66affSColin Finck /* Enter SEH for probing */ 3887c2c66affSColin Finck _SEH2_TRY 3888c2c66affSColin Finck { 3889c2c66affSColin Finck /* Probe the I/O Status Block */ 3890c2c66affSColin Finck ProbeForWriteIoStatusBlock(IoStatusBlock); 3891c2c66affSColin Finck } 3892c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3893c2c66affSColin Finck { 3894c2c66affSColin Finck /* Return the exception code */ 3895c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode()); 3896c2c66affSColin Finck } 3897c2c66affSColin Finck _SEH2_END; 3898c2c66affSColin Finck } 3899c2c66affSColin Finck 3900c2c66affSColin Finck /* Reference the file object */ 3901c2c66affSColin Finck Status = ObReferenceObjectByHandle(FileHandle, 3902c2c66affSColin Finck 0, 3903c2c66affSColin Finck IoFileObjectType, 3904c2c66affSColin Finck PreviousMode, 3905c2c66affSColin Finck (PVOID*)&FileObject, 3906c2c66affSColin Finck NULL); 3907c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 3908c2c66affSColin Finck 3909c2c66affSColin Finck /* IRP cancellations are synchronized at APC_LEVEL. */ 3910c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3911c2c66affSColin Finck 3912c2c66affSColin Finck /* Get the current thread */ 3913c2c66affSColin Finck Thread = PsGetCurrentThread(); 3914c2c66affSColin Finck 3915c2c66affSColin Finck /* Update the operation counts */ 3916c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 3917c2c66affSColin Finck 3918c2c66affSColin Finck /* Loop the list */ 3919c2c66affSColin Finck ListHead = &Thread->IrpList; 3920c2c66affSColin Finck NextEntry = ListHead->Flink; 3921c2c66affSColin Finck while (ListHead != NextEntry) 3922c2c66affSColin Finck { 3923c2c66affSColin Finck /* Get the IRP and check if the File Object matches */ 3924c2c66affSColin Finck Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 3925c2c66affSColin Finck if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 3926c2c66affSColin Finck { 3927c2c66affSColin Finck /* Cancel this IRP and keep looping */ 3928c2c66affSColin Finck IoCancelIrp(Irp); 3929c2c66affSColin Finck OurIrpsInList = TRUE; 3930c2c66affSColin Finck } 3931c2c66affSColin Finck 3932c2c66affSColin Finck /* Go to the next entry */ 3933c2c66affSColin Finck NextEntry = NextEntry->Flink; 3934c2c66affSColin Finck } 3935c2c66affSColin Finck 3936c2c66affSColin Finck /* Lower the IRQL */ 3937c2c66affSColin Finck KeLowerIrql(OldIrql); 3938c2c66affSColin Finck 3939c2c66affSColin Finck /* Check if we had found an IRP */ 3940c2c66affSColin Finck if (OurIrpsInList) 3941c2c66affSColin Finck { 3942c2c66affSColin Finck /* Setup a 10ms wait */ 3943c2c66affSColin Finck Interval.QuadPart = -100000; 3944c2c66affSColin Finck 3945c2c66affSColin Finck /* Start looping */ 3946c2c66affSColin Finck while (OurIrpsInList) 3947c2c66affSColin Finck { 3948c2c66affSColin Finck /* Do the wait */ 3949c2c66affSColin Finck KeDelayExecutionThread(KernelMode, FALSE, &Interval); 3950c2c66affSColin Finck OurIrpsInList = FALSE; 3951c2c66affSColin Finck 3952c2c66affSColin Finck /* Raise IRQL */ 3953c2c66affSColin Finck KeRaiseIrql(APC_LEVEL, &OldIrql); 3954c2c66affSColin Finck 3955c2c66affSColin Finck /* Now loop the list again */ 3956c2c66affSColin Finck NextEntry = ListHead->Flink; 3957c2c66affSColin Finck while (NextEntry != ListHead) 3958c2c66affSColin Finck { 3959c2c66affSColin Finck /* Get the IRP and check if the File Object matches */ 3960c2c66affSColin Finck Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 3961c2c66affSColin Finck if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 3962c2c66affSColin Finck { 3963c2c66affSColin Finck /* Keep looping */ 3964c2c66affSColin Finck OurIrpsInList = TRUE; 3965c2c66affSColin Finck break; 3966c2c66affSColin Finck } 3967c2c66affSColin Finck 3968c2c66affSColin Finck /* Go to the next entry */ 3969c2c66affSColin Finck NextEntry = NextEntry->Flink; 3970c2c66affSColin Finck } 3971c2c66affSColin Finck 3972c2c66affSColin Finck /* Lower the IRQL */ 3973c2c66affSColin Finck KeLowerIrql(OldIrql); 3974c2c66affSColin Finck } 3975c2c66affSColin Finck } 3976c2c66affSColin Finck 3977c2c66affSColin Finck /* Enter SEH for writing back the I/O Status */ 3978c2c66affSColin Finck _SEH2_TRY 3979c2c66affSColin Finck { 3980c2c66affSColin Finck /* Write success */ 3981c2c66affSColin Finck IoStatusBlock->Status = STATUS_SUCCESS; 3982c2c66affSColin Finck IoStatusBlock->Information = 0; 3983c2c66affSColin Finck } 3984c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3985c2c66affSColin Finck { 3986c2c66affSColin Finck /* Ignore exception */ 3987c2c66affSColin Finck } 3988c2c66affSColin Finck _SEH2_END; 3989c2c66affSColin Finck 3990c2c66affSColin Finck /* Dereference the file object and return success */ 3991c2c66affSColin Finck ObDereferenceObject(FileObject); 3992c2c66affSColin Finck return STATUS_SUCCESS; 3993c2c66affSColin Finck } 3994c2c66affSColin Finck 3995c2c66affSColin Finck /* 3996c2c66affSColin Finck * @implemented 3997c2c66affSColin Finck */ 3998c2c66affSColin Finck NTSTATUS 3999c2c66affSColin Finck NTAPI 4000c2c66affSColin Finck NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes) 4001c2c66affSColin Finck { 4002c2c66affSColin Finck NTSTATUS Status; 4003c2c66affSColin Finck DUMMY_FILE_OBJECT LocalFileObject; 4004c2c66affSColin Finck HANDLE Handle; 4005c2c66affSColin Finck KPROCESSOR_MODE AccessMode = KeGetPreviousMode(); 4006c2c66affSColin Finck OPEN_PACKET OpenPacket; 4007c2c66affSColin Finck PAGED_CODE(); 4008c2c66affSColin Finck IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName); 4009c2c66affSColin Finck 4010c2c66affSColin Finck /* Setup the Open Packet */ 4011c2c66affSColin Finck RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 4012c2c66affSColin Finck OpenPacket.Type = IO_TYPE_OPEN_PACKET; 4013c2c66affSColin Finck OpenPacket.Size = sizeof(OPEN_PACKET); 4014c2c66affSColin Finck OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE; 4015c2c66affSColin Finck OpenPacket.ShareAccess = FILE_SHARE_READ | 4016c2c66affSColin Finck FILE_SHARE_WRITE | 4017c2c66affSColin Finck FILE_SHARE_DELETE; 4018c2c66affSColin Finck OpenPacket.Disposition = FILE_OPEN; 4019c2c66affSColin Finck OpenPacket.DeleteOnly = TRUE; 4020c2c66affSColin Finck OpenPacket.LocalFileObject = &LocalFileObject; 4021c2c66affSColin Finck 4022c2c66affSColin Finck /* Update the operation counts */ 4023c2c66affSColin Finck IopUpdateOperationCount(IopOtherTransfer); 4024c2c66affSColin Finck 4025c2c66affSColin Finck /* 4026c2c66affSColin Finck * Attempt opening the file. This will call the I/O Parse Routine for 4027c2c66affSColin Finck * the File Object (IopParseDevice) which will use the dummy file obejct 4028c2c66affSColin Finck * send the IRP to its device object. Note that we have two statuses 4029c2c66affSColin Finck * to worry about: the Object Manager's status (in Status) and the I/O 4030c2c66affSColin Finck * status, which is in the Open Packet's Final Status, and determined 4031c2c66affSColin Finck * by the Parse Check member. 4032c2c66affSColin Finck */ 4033c2c66affSColin Finck Status = ObOpenObjectByName(ObjectAttributes, 4034c2c66affSColin Finck NULL, 4035c2c66affSColin Finck AccessMode, 4036c2c66affSColin Finck NULL, 4037c2c66affSColin Finck DELETE, 4038c2c66affSColin Finck &OpenPacket, 4039c2c66affSColin Finck &Handle); 4040c2c66affSColin Finck if (OpenPacket.ParseCheck == FALSE) return Status; 4041c2c66affSColin Finck 4042c2c66affSColin Finck /* Retrn the Io status */ 4043c2c66affSColin Finck return OpenPacket.FinalStatus; 4044c2c66affSColin Finck } 4045c2c66affSColin Finck 4046c2c66affSColin Finck /* EOF */ 4047