Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfile.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/file.c 00005 * PURPOSE: Functions that deal with managing the FILE_OBJECT itself. 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Gunnar Dalsnes 00008 * Eric Kohl 00009 * Filip Navara (navaraf@reactos.org) 00010 */ 00011 00012 /* INCLUDES *****************************************************************/ 00013 00014 #include <ntoskrnl.h> 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* PRIVATE FUNCTIONS *********************************************************/ 00019 00020 VOID 00021 NTAPI 00022 IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState, 00023 IN OUT PULONG CreateOptions, 00024 IN KPROCESSOR_MODE PreviousMode, 00025 IN ULONG Disposition) 00026 { 00027 ACCESS_MASK DesiredAccess, ReadAccess, WriteAccess; 00028 PRIVILEGE_SET Privileges; 00029 BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE; 00030 PAGED_CODE(); 00031 00032 /* Don't do anything if privileges were checked already */ 00033 if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return; 00034 00035 /* Check if the file was actually opened for backup purposes */ 00036 if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT) 00037 { 00038 /* Set the check flag since were doing it now */ 00039 AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED; 00040 00041 /* Set the access masks required */ 00042 ReadAccess = READ_CONTROL | 00043 ACCESS_SYSTEM_SECURITY | 00044 FILE_GENERIC_READ | 00045 FILE_TRAVERSE; 00046 WriteAccess = WRITE_DAC | 00047 WRITE_OWNER | 00048 ACCESS_SYSTEM_SECURITY | 00049 FILE_GENERIC_WRITE | 00050 FILE_ADD_FILE | 00051 FILE_ADD_SUBDIRECTORY | 00052 DELETE; 00053 DesiredAccess = AccessState->RemainingDesiredAccess; 00054 00055 /* Check if desired access was the maximum */ 00056 if (DesiredAccess & MAXIMUM_ALLOWED) 00057 { 00058 /* Then add all the access masks required */ 00059 DesiredAccess |= (ReadAccess | WriteAccess); 00060 } 00061 00062 /* Check if the file already exists */ 00063 if (Disposition & FILE_OPEN) 00064 { 00065 /* Check if desired access has the read mask */ 00066 if (ReadAccess & DesiredAccess) 00067 { 00068 /* Setup the privilege check lookup */ 00069 Privileges.PrivilegeCount = 1; 00070 Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 00071 Privileges.Privilege[0].Luid = SeBackupPrivilege; 00072 Privileges.Privilege[0].Attributes = 0; 00073 AccessGranted = SePrivilegeCheck(&Privileges, 00074 &AccessState-> 00075 SubjectSecurityContext, 00076 PreviousMode); 00077 if (AccessGranted) 00078 { 00079 /* Remember that backup was allowed */ 00080 HaveBackupPriv = TRUE; 00081 00082 /* Append the privileges and update the access state */ 00083 SeAppendPrivileges(AccessState, &Privileges); 00084 AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess); 00085 AccessState->RemainingDesiredAccess &= ~ReadAccess; 00086 DesiredAccess &= ~ReadAccess; 00087 00088 /* Set backup privilege for the token */ 00089 AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE; 00090 } 00091 } 00092 } 00093 else 00094 { 00095 /* Caller is creating the file, check restore privileges later */ 00096 CheckRestore = TRUE; 00097 } 00098 00099 /* Check if caller wants write access or if it's creating a file */ 00100 if ((WriteAccess & DesiredAccess) || (CheckRestore)) 00101 { 00102 /* Setup the privilege lookup and do it */ 00103 Privileges.PrivilegeCount = 1; 00104 Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY; 00105 Privileges.Privilege[0].Luid = SeRestorePrivilege; 00106 Privileges.Privilege[0].Attributes = 0; 00107 AccessGranted = SePrivilegeCheck(&Privileges, 00108 &AccessState->SubjectSecurityContext, 00109 PreviousMode); 00110 if (AccessGranted) 00111 { 00112 /* Remember that privilege was given */ 00113 HaveBackupPriv = TRUE; 00114 00115 /* Append the privileges and update the access state */ 00116 SeAppendPrivileges(AccessState, &Privileges); 00117 AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess); 00118 AccessState->RemainingDesiredAccess &= ~WriteAccess; 00119 00120 /* Set restore privilege for the token */ 00121 AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE; 00122 } 00123 } 00124 00125 /* If we don't have the privilege, remove the option */ 00126 if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT; 00127 } 00128 } 00129 00130 NTSTATUS 00131 NTAPI 00132 IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket, 00133 IN PDEVICE_OBJECT DeviceObject) 00134 { 00135 /* Make sure the object is valid */ 00136 if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags & 00137 (DOE_UNLOAD_PENDING | 00138 DOE_DELETE_PENDING | 00139 DOE_REMOVE_PENDING | 00140 DOE_REMOVE_PROCESSED)) || 00141 (DeviceObject->Flags & DO_DEVICE_INITIALIZING)) 00142 { 00143 /* It's unloading or initializing, so fail */ 00144 DPRINT1("You are seeing this because the following ROS driver: %wZ\n" 00145 " sucks. Please fix it's AddDevice Routine\n", 00146 &DeviceObject->DriverObject->DriverName); 00147 return STATUS_NO_SUCH_DEVICE; 00148 } 00149 else if ((DeviceObject->Flags & DO_EXCLUSIVE) && 00150 (DeviceObject->ReferenceCount) && 00151 !(OpenPacket->RelatedFileObject) && 00152 !(OpenPacket->Options & IO_ATTACH_DEVICE)) 00153 { 00154 return STATUS_ACCESS_DENIED; 00155 } 00156 00157 else 00158 { 00159 /* Increase reference count */ 00160 InterlockedIncrement(&DeviceObject->ReferenceCount); 00161 return STATUS_SUCCESS; 00162 } 00163 } 00164 00165 NTSTATUS 00166 NTAPI 00167 IopParseDevice(IN PVOID ParseObject, 00168 IN PVOID ObjectType, 00169 IN OUT PACCESS_STATE AccessState, 00170 IN KPROCESSOR_MODE AccessMode, 00171 IN ULONG Attributes, 00172 IN OUT PUNICODE_STRING CompleteName, 00173 IN OUT PUNICODE_STRING RemainingName, 00174 IN OUT PVOID Context, 00175 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, 00176 OUT PVOID *Object) 00177 { 00178 POPEN_PACKET OpenPacket = (POPEN_PACKET)Context; 00179 PDEVICE_OBJECT OriginalDeviceObject = (PDEVICE_OBJECT)ParseObject; 00180 PDEVICE_OBJECT DeviceObject, OwnerDevice; 00181 NTSTATUS Status; 00182 PFILE_OBJECT FileObject; 00183 PVPB Vpb = NULL; 00184 PIRP Irp; 00185 PEXTENDED_IO_STACK_LOCATION StackLoc; 00186 IO_SECURITY_CONTEXT SecurityContext; 00187 IO_STATUS_BLOCK IoStatusBlock; 00188 BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile; 00189 OBJECT_ATTRIBUTES ObjectAttributes; 00190 KIRQL OldIrql; 00191 PDUMMY_FILE_OBJECT DummyFileObject; 00192 PFILE_BASIC_INFORMATION FileBasicInfo; 00193 ULONG ReturnLength; 00194 KPROCESSOR_MODE CheckMode; 00195 BOOLEAN VolumeOpen = FALSE; 00196 ACCESS_MASK DesiredAccess, GrantedAccess; 00197 BOOLEAN AccessGranted, LockHeld = FALSE; 00198 PPRIVILEGE_SET Privileges = NULL; 00199 IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n", 00200 ParseObject, RemainingName); 00201 00202 /* Assume failure */ 00203 *Object = NULL; 00204 00205 /* Validate the open packet */ 00206 if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH; 00207 00208 /* Check if we have a related file object */ 00209 if (OpenPacket->RelatedFileObject) 00210 { 00211 /* Use the related file object's device object */ 00212 OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject; 00213 } 00214 00215 /* Validate device status */ 00216 Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject); 00217 if (!NT_SUCCESS(Status)) 00218 { 00219 /* We failed, return status */ 00220 OpenPacket->FinalStatus = Status; 00221 return Status; 00222 } 00223 00224 /* Map the generic mask and set the new mapping in the access state */ 00225 RtlMapGenericMask(&AccessState->RemainingDesiredAccess, 00226 &IoFileObjectType->TypeInfo.GenericMapping); 00227 RtlMapGenericMask(&AccessState->OriginalDesiredAccess, 00228 &IoFileObjectType->TypeInfo.GenericMapping); 00229 SeSetAccessStateGenericMapping(AccessState, 00230 &IoFileObjectType->TypeInfo.GenericMapping); 00231 DesiredAccess = AccessState->RemainingDesiredAccess; 00232 00233 /* Check what kind of access checks to do */ 00234 if ((AccessMode != KernelMode) || 00235 (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) 00236 { 00237 /* Call is from user-mode or kernel is forcing checks */ 00238 CheckMode = UserMode; 00239 } 00240 else 00241 { 00242 /* Call is from the kernel */ 00243 CheckMode = KernelMode; 00244 } 00245 00246 /* Check privilege for backup or restore operation */ 00247 IopCheckBackupRestorePrivilege(AccessState, 00248 &OpenPacket->CreateOptions, 00249 CheckMode, 00250 OpenPacket->Disposition); 00251 00252 /* Check if we are re-parsing */ 00253 if (((OpenPacket->Override) && !(RemainingName->Length)) || 00254 (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED)) 00255 { 00256 /* Get granted access from the last call */ 00257 DesiredAccess |= AccessState->PreviouslyGrantedAccess; 00258 } 00259 00260 /* Check if this is a volume open */ 00261 if ((OpenPacket->RelatedFileObject) && 00262 (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) && 00263 !(RemainingName->Length)) 00264 { 00265 /* It is */ 00266 VolumeOpen = TRUE; 00267 } 00268 00269 /* Now check if we need access checks */ 00270 if (((AccessMode != KernelMode) || 00271 (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) && 00272 (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) && 00273 !(OpenPacket->Override)) 00274 { 00275 /* Check if a device object is being parsed */ 00276 if (!RemainingName->Length) 00277 { 00278 /* Lock the subject context */ 00279 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00280 LockHeld = TRUE; 00281 00282 /* Do access check */ 00283 AccessGranted = SeAccessCheck(OriginalDeviceObject-> 00284 SecurityDescriptor, 00285 &AccessState->SubjectSecurityContext, 00286 LockHeld, 00287 DesiredAccess, 00288 0, 00289 &Privileges, 00290 &IoFileObjectType-> 00291 TypeInfo.GenericMapping, 00292 UserMode, 00293 &GrantedAccess, 00294 &Status); 00295 if (Privileges) 00296 { 00297 /* Append and free the privileges */ 00298 SeAppendPrivileges(AccessState, Privileges); 00299 SeFreePrivileges(Privileges); 00300 } 00301 00302 /* Check if we got access */ 00303 if (AccessGranted) 00304 { 00305 /* Update access state */ 00306 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 00307 AccessState->RemainingDesiredAccess &= ~(GrantedAccess & 00308 MAXIMUM_ALLOWED); 00309 OpenPacket->Override= TRUE; 00310 } 00311 00312 /* FIXME: Do Audit/Alarm for open operation */ 00313 } 00314 else 00315 { 00316 /* Check if we need to do traverse validation */ 00317 if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) || 00318 ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) || 00319 (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM))) 00320 { 00321 /* Check if this is a restricted token */ 00322 if (!(AccessState->Flags & TOKEN_IS_RESTRICTED)) 00323 { 00324 /* FIXME: Do the FAST traverse check */ 00325 AccessGranted = FALSE; 00326 } 00327 else 00328 { 00329 /* Fail */ 00330 AccessGranted = FALSE; 00331 } 00332 00333 /* Check if we failed to get access */ 00334 if (!AccessGranted) 00335 { 00336 /* Lock the subject context */ 00337 SeLockSubjectContext(&AccessState->SubjectSecurityContext); 00338 LockHeld = TRUE; 00339 00340 /* Do access check */ 00341 AccessGranted = SeAccessCheck(OriginalDeviceObject-> 00342 SecurityDescriptor, 00343 &AccessState->SubjectSecurityContext, 00344 LockHeld, 00345 FILE_TRAVERSE, 00346 0, 00347 &Privileges, 00348 &IoFileObjectType-> 00349 TypeInfo.GenericMapping, 00350 UserMode, 00351 &GrantedAccess, 00352 &Status); 00353 if (Privileges) 00354 { 00355 /* Append and free the privileges */ 00356 SeAppendPrivileges(AccessState, Privileges); 00357 SeFreePrivileges(Privileges); 00358 } 00359 } 00360 00361 /* FIXME: Do Audit/Alarm for traverse check */ 00362 } 00363 else 00364 { 00365 /* Access automatically granted */ 00366 AccessGranted = TRUE; 00367 } 00368 } 00369 00370 /* Check if we hold the lock */ 00371 if (LockHeld) 00372 { 00373 /* Release it */ 00374 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext); 00375 } 00376 00377 /* Check if access failed */ 00378 if (!AccessGranted) 00379 { 00380 /* Dereference the device and fail */ 00381 DPRINT1("Traverse access failed!\n"); 00382 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 00383 return STATUS_ACCESS_DENIED; 00384 } 00385 } 00386 00387 /* Check if we can simply use a dummy file */ 00388 UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly)); 00389 00390 /* Check if this is a direct open */ 00391 if (!(RemainingName->Length) && 00392 !(OpenPacket->RelatedFileObject) && 00393 ((DesiredAccess & ~(SYNCHRONIZE | 00394 FILE_READ_ATTRIBUTES | 00395 READ_CONTROL | 00396 ACCESS_SYSTEM_SECURITY | 00397 WRITE_OWNER | 00398 WRITE_DAC)) == 0) && 00399 !(UseDummyFile)) 00400 { 00401 /* Remember this for later */ 00402 DirectOpen = TRUE; 00403 } 00404 00405 /* FIXME: Small hack still exists, have to check why... 00406 * This is triggered multiple times by usetup and then once per boot. 00407 */ 00408 if (!(DirectOpen) && 00409 !(RemainingName->Length) && 00410 !(OpenPacket->RelatedFileObject) && 00411 ((wcsstr(CompleteName->Buffer, L"Harddisk")) || 00412 (wcsstr(CompleteName->Buffer, L"Floppy"))) && 00413 !(UseDummyFile)) 00414 { 00415 DPRINT1("Using IopParseDevice() hack. Requested invalid attributes: %lx\n", 00416 DesiredAccess & ~(SYNCHRONIZE | 00417 FILE_READ_ATTRIBUTES | 00418 READ_CONTROL | 00419 ACCESS_SYSTEM_SECURITY | 00420 WRITE_OWNER | 00421 WRITE_DAC)); 00422 DirectOpen = TRUE; 00423 } 00424 00425 /* Check if we have a related FO that wasn't a direct open */ 00426 if ((OpenPacket->RelatedFileObject) && 00427 !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 00428 { 00429 /* The device object is the one we were given */ 00430 DeviceObject = ParseObject; 00431 00432 /* Check if the related FO had a VPB */ 00433 if (OpenPacket->RelatedFileObject->Vpb) 00434 { 00435 /* Yes, remember it */ 00436 Vpb = OpenPacket->RelatedFileObject->Vpb; 00437 00438 /* Reference it */ 00439 InterlockedIncrement((PLONG)&Vpb->ReferenceCount); 00440 } 00441 } 00442 else 00443 { 00444 /* The device object is the one we were given */ 00445 DeviceObject = OriginalDeviceObject; 00446 00447 /* Check if it has a VPB */ 00448 if ((OriginalDeviceObject->Vpb) && !(DirectOpen)) 00449 { 00450 /* Check if the VPB is mounted, and mount it */ 00451 Vpb = IopCheckVpbMounted(OpenPacket, 00452 OriginalDeviceObject, 00453 RemainingName, 00454 &Status); 00455 if (!Vpb) return Status; 00456 00457 /* Get the VPB's device object */ 00458 DeviceObject = Vpb->DeviceObject; 00459 } 00460 00461 /* Check if there's an attached device */ 00462 if (DeviceObject->AttachedDevice) 00463 { 00464 /* Get the attached device */ 00465 DeviceObject = IoGetAttachedDevice(DeviceObject); 00466 } 00467 } 00468 00469 /* Check if this is a secure FSD */ 00470 if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) && 00471 ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) && 00472 (!VolumeOpen)) 00473 { 00474 DPRINT("Fix Secure FSD support!!!\n"); 00475 } 00476 00477 /* Allocate the IRP */ 00478 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); 00479 if (!Irp) 00480 { 00481 /* Dereference the device and VPB, then fail */ 00482 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 00483 if (Vpb) IopDereferenceVpbAndFree(Vpb); 00484 return STATUS_INSUFFICIENT_RESOURCES; 00485 } 00486 00487 /* Now set the IRP data */ 00488 Irp->RequestorMode = AccessMode; 00489 Irp->Flags = IRP_CREATE_OPERATION | 00490 IRP_SYNCHRONOUS_API | 00491 IRP_DEFER_IO_COMPLETION; 00492 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00493 Irp->UserIosb = &IoStatusBlock; 00494 Irp->MdlAddress = NULL; 00495 Irp->PendingReturned = FALSE; 00496 Irp->UserEvent = NULL; 00497 Irp->Cancel = FALSE; 00498 Irp->CancelRoutine = NULL; 00499 Irp->Tail.Overlay.AuxiliaryBuffer = NULL; 00500 00501 /* Setup the security context */ 00502 SecurityContext.SecurityQos = SecurityQos; 00503 SecurityContext.AccessState = AccessState; 00504 SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess; 00505 SecurityContext.FullCreateOptions = OpenPacket->CreateOptions; 00506 00507 /* Get the I/O Stack location */ 00508 StackLoc = (PEXTENDED_IO_STACK_LOCATION)IoGetNextIrpStackLocation(Irp); 00509 StackLoc->Control = 0; 00510 00511 /* Check what kind of file this is */ 00512 switch (OpenPacket->CreateFileType) 00513 { 00514 /* Normal file */ 00515 case CreateFileTypeNone: 00516 00517 /* Set the major function and EA Length */ 00518 StackLoc->MajorFunction = IRP_MJ_CREATE; 00519 StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength; 00520 00521 /* Set the flags */ 00522 StackLoc->Flags = (UCHAR)OpenPacket->Options; 00523 StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ? 00524 SL_CASE_SENSITIVE: 0; 00525 break; 00526 00527 /* Named pipe */ 00528 case CreateFileTypeNamedPipe: 00529 00530 /* Set the named pipe MJ and set the parameters */ 00531 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE; 00532 StackLoc->Parameters.CreatePipe.Parameters = 00533 OpenPacket->MailslotOrPipeParameters; 00534 break; 00535 00536 /* Mailslot */ 00537 case CreateFileTypeMailslot: 00538 00539 /* Set the mailslot MJ and set the parameters */ 00540 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT; 00541 StackLoc->Parameters.CreateMailslot.Parameters = 00542 OpenPacket->MailslotOrPipeParameters; 00543 break; 00544 } 00545 00546 /* Set the common data */ 00547 Irp->Overlay.AllocationSize = OpenPacket->AllocationSize; 00548 Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer; 00549 StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) | 00550 (OpenPacket->CreateOptions & 00551 0xFFFFFF); 00552 StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes; 00553 StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess; 00554 StackLoc->Parameters.Create.SecurityContext = &SecurityContext; 00555 00556 /* Check if we really need to create an object */ 00557 if (!UseDummyFile) 00558 { 00559 /* Create the actual file object */ 00560 InitializeObjectAttributes(&ObjectAttributes, 00561 NULL, 00562 Attributes, 00563 NULL, 00564 NULL); 00565 Status = ObCreateObject(KernelMode, 00566 IoFileObjectType, 00567 &ObjectAttributes, 00568 AccessMode, 00569 NULL, 00570 sizeof(FILE_OBJECT), 00571 0, 00572 0, 00573 (PVOID*)&FileObject); 00574 if (!NT_SUCCESS(Status)) 00575 { 00576 /* Create failed, free the IRP */ 00577 IoFreeIrp(Irp); 00578 00579 /* Dereference the device and VPB */ 00580 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 00581 if (Vpb) IopDereferenceVpbAndFree(Vpb); 00582 00583 /* We failed, return status */ 00584 OpenPacket->FinalStatus = Status; 00585 return Status; 00586 } 00587 00588 /* Clear the file object */ 00589 RtlZeroMemory(FileObject, sizeof(FILE_OBJECT)); 00590 00591 /* Check if this is Synch I/O */ 00592 if (OpenPacket->CreateOptions & 00593 (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) 00594 { 00595 /* Set the synch flag */ 00596 FileObject->Flags |= FO_SYNCHRONOUS_IO; 00597 00598 /* Check if it's also alertable */ 00599 if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) 00600 { 00601 /* It is, set the alertable flag */ 00602 FileObject->Flags |= FO_ALERTABLE_IO; 00603 } 00604 } 00605 00606 /* Check if this is synch I/O */ 00607 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 00608 { 00609 /* Initialize the event */ 00610 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE); 00611 } 00612 00613 /* Check if the caller requested no intermediate buffering */ 00614 if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) 00615 { 00616 /* Set the correct flag for the FSD to read */ 00617 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING; 00618 } 00619 00620 /* Check if the caller requested write through support */ 00621 if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH) 00622 { 00623 /* Set the correct flag for the FSD to read */ 00624 FileObject->Flags |= FO_WRITE_THROUGH; 00625 } 00626 00627 /* Check if the caller says the file will be only read sequentially */ 00628 if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY) 00629 { 00630 /* Set the correct flag for the FSD to read */ 00631 FileObject->Flags |= FO_SEQUENTIAL_ONLY; 00632 } 00633 00634 /* Check if the caller believes the file will be only read randomly */ 00635 if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS) 00636 { 00637 /* Set the correct flag for the FSD to read */ 00638 FileObject->Flags |= FO_RANDOM_ACCESS; 00639 } 00640 } 00641 else 00642 { 00643 /* Use the dummy object instead */ 00644 DummyFileObject = OpenPacket->DummyFileObject; 00645 RtlZeroMemory(DummyFileObject, sizeof(DUMMY_FILE_OBJECT)); 00646 00647 /* Set it up */ 00648 FileObject = (PFILE_OBJECT)&DummyFileObject->ObjectHeader.Body; 00649 DummyFileObject->ObjectHeader.Type = IoFileObjectType; 00650 DummyFileObject->ObjectHeader.PointerCount = 1; 00651 } 00652 00653 /* Setup the file header */ 00654 FileObject->Type = IO_TYPE_FILE; 00655 FileObject->Size = sizeof(FILE_OBJECT); 00656 FileObject->RelatedFileObject = OpenPacket->RelatedFileObject; 00657 FileObject->DeviceObject = OriginalDeviceObject; 00658 00659 /* Check if this is a direct device open */ 00660 if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN; 00661 00662 /* Check if the caller wants case sensitivity */ 00663 if (!(Attributes & OBJ_CASE_INSENSITIVE)) 00664 { 00665 /* Tell the driver about it */ 00666 FileObject->Flags |= FO_OPENED_CASE_SENSITIVE; 00667 } 00668 00669 /* Now set the file object */ 00670 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00671 StackLoc->FileObject = FileObject; 00672 00673 /* Check if the file object has a name */ 00674 if (RemainingName->Length) 00675 { 00676 /* Setup the unicode string */ 00677 FileObject->FileName.MaximumLength = RemainingName->Length + 00678 sizeof(WCHAR); 00679 FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool, 00680 FileObject-> 00681 FileName. 00682 MaximumLength, 00683 TAG_IO_NAME); 00684 if (!FileObject->FileName.Buffer) 00685 { 00686 /* Failed to allocate the name, free the IRP */ 00687 IoFreeIrp(Irp); 00688 00689 /* Dereference the device object and VPB */ 00690 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 00691 if (Vpb) IopDereferenceVpbAndFree(Vpb); 00692 00693 /* Clear the FO and dereference it */ 00694 FileObject->DeviceObject = NULL; 00695 if (!UseDummyFile) ObDereferenceObject(FileObject); 00696 00697 /* Fail */ 00698 return STATUS_INSUFFICIENT_RESOURCES; 00699 } 00700 } 00701 00702 /* Copy the name */ 00703 RtlCopyUnicodeString(&FileObject->FileName, RemainingName); 00704 00705 /* Initialize the File Object event and set the FO */ 00706 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE); 00707 OpenPacket->FileObject = FileObject; 00708 00709 /* Queue the IRP and call the driver */ 00710 IopQueueIrpToThread(Irp); 00711 Status = IoCallDriver(DeviceObject, Irp); 00712 if (Status == STATUS_PENDING) 00713 { 00714 /* Wait for the driver to complete the create */ 00715 KeWaitForSingleObject(&FileObject->Event, 00716 Executive, 00717 KernelMode, 00718 FALSE, 00719 NULL); 00720 00721 /* Get the new status */ 00722 Status = IoStatusBlock.Status; 00723 } 00724 else 00725 { 00726 /* We'll have to complete it ourselves */ 00727 ASSERT(!Irp->PendingReturned); 00728 ASSERT(!Irp->MdlAddress); 00729 00730 /* Completion happens at APC_LEVEL */ 00731 KeRaiseIrql(APC_LEVEL, &OldIrql); 00732 00733 /* Get the new I/O Status block ourselves */ 00734 IoStatusBlock = Irp->IoStatus; 00735 Status = IoStatusBlock.Status; 00736 00737 /* Manually signal the even, we can't have any waiters */ 00738 FileObject->Event.Header.SignalState = 1; 00739 00740 /* Now that we've signaled the events, de-associate the IRP */ 00741 IopUnQueueIrpFromThread(Irp); 00742 00743 /* Check if the IRP had an input buffer */ 00744 if ((Irp->Flags & IRP_BUFFERED_IO) && 00745 (Irp->Flags & IRP_DEALLOCATE_BUFFER)) 00746 { 00747 /* Free it. A driver might've tacked one on */ 00748 ExFreePool(Irp->AssociatedIrp.SystemBuffer); 00749 } 00750 00751 /* Free the IRP and bring the IRQL back down */ 00752 IoFreeIrp(Irp); 00753 KeLowerIrql(OldIrql); 00754 } 00755 00756 /* Copy the I/O Status */ 00757 OpenPacket->Information = IoStatusBlock.Information; 00758 00759 /* The driver failed to create the file */ 00760 if (!NT_SUCCESS(Status)) 00761 { 00762 /* Check if we have a name */ 00763 if (FileObject->FileName.Length) 00764 { 00765 /* Free it */ 00766 ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME); 00767 FileObject->FileName.Length = 0; 00768 } 00769 00770 /* Clear its device object */ 00771 FileObject->DeviceObject = NULL; 00772 00773 /* Save this now because the FO might go away */ 00774 OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ? 00775 TRUE : FALSE; 00776 00777 /* Clear the file object in the open packet */ 00778 OpenPacket->FileObject = NULL; 00779 00780 /* Dereference the file object */ 00781 if (!UseDummyFile) ObDereferenceObject(FileObject); 00782 00783 /* Dereference the device object */ 00784 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE); 00785 00786 /* Unless the driver cancelled the open, dereference the VPB */ 00787 if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb); 00788 00789 /* Set the status and return */ 00790 OpenPacket->FinalStatus = Status; 00791 return Status; 00792 } 00793 else if (Status == STATUS_REPARSE) 00794 { 00795 /* FIXME: We don't handle this at all! */ 00796 ASSERT(FALSE); 00797 } 00798 00799 /* Get the owner of the File Object */ 00800 OwnerDevice = IoGetRelatedDeviceObject(FileObject); 00801 00802 /* 00803 * It's possible that the device to whom we sent the IRP to 00804 * isn't actually the device that ended opening the file object 00805 * internally. 00806 */ 00807 if (OwnerDevice != DeviceObject) 00808 { 00809 /* We have to de-reference the VPB we had associated */ 00810 if (Vpb) IopDereferenceVpbAndFree(Vpb); 00811 00812 /* And re-associate with the actual one */ 00813 Vpb = FileObject->Vpb; 00814 if (Vpb) InterlockedIncrement((PLONG)&Vpb->ReferenceCount); 00815 } 00816 00817 /* Make sure we are not using a dummy */ 00818 if (!UseDummyFile) 00819 { 00820 /* Check if this was a volume open */ 00821 if ((!(FileObject->RelatedFileObject) || 00822 (FileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN)) && 00823 !(FileObject->FileName.Length)) 00824 { 00825 /* All signs point to it, but make sure it was actually an FSD */ 00826 if ((OwnerDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) || 00827 (OwnerDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || 00828 (OwnerDevice->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) || 00829 (OwnerDevice->DeviceType == FILE_DEVICE_FILE_SYSTEM)) 00830 { 00831 /* The owner device is an FSD, so this is a volume open for real */ 00832 FileObject->Flags |= FO_VOLUME_OPEN; 00833 } 00834 } 00835 00836 /* Reference the object and set the parse check */ 00837 ObReferenceObject(FileObject); 00838 *Object = FileObject; 00839 OpenPacket->FinalStatus = IoStatusBlock.Status; 00840 OpenPacket->ParseCheck = TRUE; 00841 return OpenPacket->FinalStatus; 00842 } 00843 else 00844 { 00845 /* Check if this was a query */ 00846 if (OpenPacket->QueryOnly) 00847 { 00848 /* Check if the caller wants basic info only */ 00849 if (!OpenPacket->FullAttributes) 00850 { 00851 /* Allocate the buffer */ 00852 FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool, 00853 sizeof(*FileBasicInfo), 00854 TAG_IO); 00855 if (FileBasicInfo) 00856 { 00857 /* Do the query */ 00858 Status = IoQueryFileInformation(FileObject, 00859 FileBasicInformation, 00860 sizeof(*FileBasicInfo), 00861 FileBasicInfo, 00862 &ReturnLength); 00863 if (NT_SUCCESS(Status)) 00864 { 00865 /* Copy the data */ 00866 RtlCopyMemory(OpenPacket->BasicInformation, 00867 FileBasicInfo, 00868 ReturnLength); 00869 } 00870 00871 /* Free our buffer */ 00872 ExFreePoolWithTag(FileBasicInfo, TAG_IO); 00873 } 00874 else 00875 { 00876 /* Fail */ 00877 Status = STATUS_INSUFFICIENT_RESOURCES; 00878 } 00879 } 00880 else 00881 { 00882 /* This is a full query */ 00883 Status = IoQueryFileInformation( 00884 FileObject, 00885 FileNetworkOpenInformation, 00886 sizeof(FILE_NETWORK_OPEN_INFORMATION), 00887 OpenPacket->NetworkInformation, 00888 &ReturnLength); 00889 if (!NT_SUCCESS(Status)) ASSERT(Status != STATUS_NOT_IMPLEMENTED); 00890 } 00891 } 00892 00893 /* Delete the file object */ 00894 IopDeleteFile(FileObject); 00895 00896 /* Clear out the file */ 00897 OpenPacket->FileObject = NULL; 00898 00899 /* Set and return status */ 00900 OpenPacket->FinalStatus = Status; 00901 OpenPacket->ParseCheck = TRUE; 00902 return Status; 00903 } 00904 } 00905 00906 NTSTATUS 00907 NTAPI 00908 IopParseFile(IN PVOID ParseObject, 00909 IN PVOID ObjectType, 00910 IN OUT PACCESS_STATE AccessState, 00911 IN KPROCESSOR_MODE AccessMode, 00912 IN ULONG Attributes, 00913 IN OUT PUNICODE_STRING CompleteName, 00914 IN OUT PUNICODE_STRING RemainingName, 00915 IN OUT PVOID Context OPTIONAL, 00916 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, 00917 OUT PVOID *Object) 00918 { 00919 PVOID DeviceObject; 00920 POPEN_PACKET OpenPacket = (POPEN_PACKET)Context; 00921 00922 /* Validate the open packet */ 00923 if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH; 00924 00925 /* Get the device object */ 00926 DeviceObject = IoGetRelatedDeviceObject(ParseObject); 00927 OpenPacket->RelatedFileObject = ParseObject; 00928 00929 /* Call the main routine */ 00930 return IopParseDevice(DeviceObject, 00931 ObjectType, 00932 AccessState, 00933 AccessMode, 00934 Attributes, 00935 CompleteName, 00936 RemainingName, 00937 OpenPacket, 00938 SecurityQos, 00939 Object); 00940 } 00941 00942 VOID 00943 NTAPI 00944 IopDeleteFile(IN PVOID ObjectBody) 00945 { 00946 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 00947 PIRP Irp; 00948 PIO_STACK_LOCATION StackPtr; 00949 NTSTATUS Status; 00950 KEVENT Event; 00951 PDEVICE_OBJECT DeviceObject; 00952 BOOLEAN DereferenceDone = FALSE; 00953 PVPB Vpb; 00954 KIRQL OldIrql; 00955 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 00956 00957 /* Check if the file has a device object */ 00958 if (FileObject->DeviceObject) 00959 { 00960 /* Check if this is a direct open or not */ 00961 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 00962 { 00963 /* Get the attached device */ 00964 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 00965 } 00966 else 00967 { 00968 /* Use the file object's device object */ 00969 DeviceObject = IoGetRelatedDeviceObject(FileObject); 00970 } 00971 00972 /* Sanity check */ 00973 ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) || 00974 (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE)); 00975 00976 /* Check if the handle wasn't created yet */ 00977 if (!(FileObject->Flags & FO_HANDLE_CREATED)) 00978 { 00979 /* Send the cleanup IRP */ 00980 IopCloseFile(NULL, ObjectBody, 0, 1, 1); 00981 } 00982 00983 /* Clear and set up Events */ 00984 KeClearEvent(&FileObject->Event); 00985 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 00986 00987 /* Allocate an IRP */ 00988 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 00989 if (!Irp) return; 00990 00991 /* Set it up */ 00992 Irp->UserEvent = &Event; 00993 Irp->UserIosb = &Irp->IoStatus; 00994 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00995 Irp->Tail.Overlay.OriginalFileObject = FileObject; 00996 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 00997 00998 /* Set up Stack Pointer Data */ 00999 StackPtr = IoGetNextIrpStackLocation(Irp); 01000 StackPtr->MajorFunction = IRP_MJ_CLOSE; 01001 StackPtr->FileObject = FileObject; 01002 01003 /* Queue the IRP */ 01004 IopQueueIrpToThread(Irp); 01005 01006 /* Get the VPB and check if this isn't a direct open */ 01007 Vpb = FileObject->Vpb; 01008 if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 01009 { 01010 /* Dereference the VPB before the close */ 01011 InterlockedDecrement((PLONG)&Vpb->ReferenceCount); 01012 } 01013 01014 /* Check if the FS will never disappear by itself */ 01015 if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE) 01016 { 01017 /* Dereference it */ 01018 InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount); 01019 DereferenceDone = TRUE; 01020 } 01021 01022 /* Call the FS Driver */ 01023 Status = IoCallDriver(DeviceObject, Irp); 01024 if (Status == STATUS_PENDING) 01025 { 01026 /* Wait for completion */ 01027 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 01028 } 01029 01030 /* De-queue the IRP */ 01031 KeRaiseIrql(APC_LEVEL, &OldIrql); 01032 IopUnQueueIrpFromThread(Irp); 01033 KeLowerIrql(OldIrql); 01034 01035 /* Free the IRP */ 01036 IoFreeIrp(Irp); 01037 01038 /* Clear the file name */ 01039 if (FileObject->FileName.Buffer) 01040 { 01041 ExFreePoolWithTag(FileObject->FileName.Buffer, TAG_IO_NAME); 01042 FileObject->FileName.Buffer = NULL; 01043 } 01044 01045 /* Check if the FO had a completion port */ 01046 if (FileObject->CompletionContext) 01047 { 01048 /* Free it */ 01049 ObDereferenceObject(FileObject->CompletionContext->Port); 01050 ExFreePool(FileObject->CompletionContext); 01051 } 01052 01053 /* Check if the FO had extension */ 01054 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 01055 { 01056 /* Release filter context structure if any */ 01057 FsRtlPTeardownPerFileObjectContexts(FileObject); 01058 } 01059 01060 /* Check if dereference has been done yet */ 01061 if (!DereferenceDone) 01062 { 01063 /* Dereference device object */ 01064 IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE); 01065 } 01066 } 01067 } 01068 01069 NTSTATUS 01070 NTAPI 01071 IopSecurityFile(IN PVOID ObjectBody, 01072 IN SECURITY_OPERATION_CODE OperationCode, 01073 IN PSECURITY_INFORMATION SecurityInformation, 01074 IN PSECURITY_DESCRIPTOR SecurityDescriptor, 01075 IN OUT PULONG BufferLength, 01076 IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor, 01077 IN POOL_TYPE PoolType, 01078 IN OUT PGENERIC_MAPPING GenericMapping) 01079 { 01080 IO_STATUS_BLOCK IoStatusBlock; 01081 PIO_STACK_LOCATION StackPtr; 01082 PFILE_OBJECT FileObject; 01083 PDEVICE_OBJECT DeviceObject; 01084 PIRP Irp; 01085 BOOLEAN LocalEvent = FALSE; 01086 KEVENT Event; 01087 NTSTATUS Status = STATUS_SUCCESS; 01088 PAGED_CODE(); 01089 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 01090 01091 /* Check if this is a device or file */ 01092 if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE) 01093 { 01094 /* It's a device */ 01095 DeviceObject = (PDEVICE_OBJECT)ObjectBody; 01096 FileObject = NULL; 01097 } 01098 else 01099 { 01100 /* It's a file */ 01101 FileObject = (PFILE_OBJECT)ObjectBody; 01102 01103 /* Check if this is a direct open */ 01104 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 01105 { 01106 /* Get the Device Object */ 01107 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 01108 } 01109 else 01110 { 01111 /* Otherwise, use the direct device*/ 01112 DeviceObject = FileObject->DeviceObject; 01113 } 01114 } 01115 01116 /* Check if the request was for a device object */ 01117 if (!(FileObject) || 01118 (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) || 01119 (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)) 01120 { 01121 /* Check what kind of request this was */ 01122 if (OperationCode == QuerySecurityDescriptor) 01123 { 01124 return SeQuerySecurityDescriptorInfo(SecurityInformation, 01125 SecurityDescriptor, 01126 BufferLength, 01127 &DeviceObject->SecurityDescriptor); 01128 } 01129 else if (OperationCode == DeleteSecurityDescriptor) 01130 { 01131 /* Simply return success */ 01132 return STATUS_SUCCESS; 01133 } 01134 else if (OperationCode == AssignSecurityDescriptor) 01135 { 01136 /* Make absolutely sure this is a device object */ 01137 if (!(FileObject) || !(FileObject->Flags & FO_STREAM_FILE)) 01138 { 01139 /* Assign the Security Descriptor */ 01140 DeviceObject->SecurityDescriptor = SecurityDescriptor; 01141 } 01142 01143 /* Return success */ 01144 return STATUS_SUCCESS; 01145 } 01146 else 01147 { 01148 DPRINT1("FIXME: Set SD unimplemented for Devices\n"); 01149 return STATUS_SUCCESS; 01150 } 01151 } 01152 else if (OperationCode == DeleteSecurityDescriptor) 01153 { 01154 /* Same as for devices, do nothing */ 01155 return STATUS_SUCCESS; 01156 } 01157 01158 /* At this point, we know we're a file. Reference it */ 01159 ObReferenceObject(FileObject); 01160 01161 /* Check if we should use Sync IO or not */ 01162 if (FileObject->Flags & FO_SYNCHRONOUS_IO) 01163 { 01164 /* Lock the file object */ 01165 IopLockFileObject(FileObject); 01166 } 01167 else 01168 { 01169 /* Use local event */ 01170 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 01171 LocalEvent = TRUE; 01172 } 01173 01174 /* Clear the File Object event */ 01175 KeClearEvent(&FileObject->Event); 01176 01177 /* Get the device object */ 01178 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01179 01180 /* Allocate the IRP */ 01181 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 01182 if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL); 01183 01184 /* Set the IRP */ 01185 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01186 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01187 Irp->RequestorMode = ExGetPreviousMode(); 01188 Irp->UserIosb = &IoStatusBlock; 01189 Irp->UserEvent = (LocalEvent) ? &Event : NULL; 01190 Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; 01191 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 01192 01193 /* Set Stack Parameters */ 01194 StackPtr = IoGetNextIrpStackLocation(Irp); 01195 StackPtr->FileObject = FileObject; 01196 01197 /* Check if this is a query or set */ 01198 if (OperationCode == QuerySecurityDescriptor) 01199 { 01200 /* Set the major function and parameters */ 01201 StackPtr->MajorFunction = IRP_MJ_QUERY_SECURITY; 01202 StackPtr->Parameters.QuerySecurity.SecurityInformation = 01203 *SecurityInformation; 01204 StackPtr->Parameters.QuerySecurity.Length = *BufferLength; 01205 Irp->UserBuffer = SecurityDescriptor; 01206 } 01207 else 01208 { 01209 /* Set the major function and parameters for a set */ 01210 StackPtr->MajorFunction = IRP_MJ_SET_SECURITY; 01211 StackPtr->Parameters.SetSecurity.SecurityInformation = 01212 *SecurityInformation; 01213 StackPtr->Parameters.SetSecurity.SecurityDescriptor = 01214 SecurityDescriptor; 01215 } 01216 01217 /* Queue the IRP */ 01218 IopQueueIrpToThread(Irp); 01219 01220 /* Update operation counts */ 01221 IopUpdateOperationCount(IopOtherTransfer); 01222 01223 /* Call the Driver */ 01224 Status = IoCallDriver(DeviceObject, Irp); 01225 01226 /* Check if this was async I/O */ 01227 if (LocalEvent) 01228 { 01229 /* Check if the IRP is pending completion */ 01230 if (Status == STATUS_PENDING) 01231 { 01232 /* Wait on the local event */ 01233 KeWaitForSingleObject(&Event, 01234 Executive, 01235 KernelMode, 01236 FALSE, 01237 NULL); 01238 Status = IoStatusBlock.Status; 01239 } 01240 } 01241 else 01242 { 01243 /* Check if the IRP is pending completion */ 01244 if (Status == STATUS_PENDING) 01245 { 01246 /* Wait on the file object */ 01247 KeWaitForSingleObject(&FileObject->Event, 01248 Executive, 01249 KernelMode, 01250 FALSE, 01251 NULL); 01252 Status = FileObject->FinalStatus; 01253 } 01254 01255 /* Release the lock */ 01256 IopUnlockFileObject(FileObject); 01257 } 01258 01259 /* This Driver doesn't implement Security, so try to give it a default */ 01260 if (Status == STATUS_INVALID_DEVICE_REQUEST) 01261 { 01262 /* Was this a query? */ 01263 if (OperationCode == QuerySecurityDescriptor) 01264 { 01265 /* Set a World Security Descriptor */ 01266 Status = SeSetWorldSecurityDescriptor(*SecurityInformation, 01267 SecurityDescriptor, 01268 BufferLength); 01269 } 01270 else 01271 { 01272 /* It wasn't a query, so just fake success */ 01273 Status = STATUS_SUCCESS; 01274 } 01275 } 01276 else if (OperationCode == QuerySecurityDescriptor) 01277 { 01278 /* Callers usually expect the normalized form */ 01279 if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_BUFFER_TOO_SMALL; 01280 01281 _SEH2_TRY 01282 { 01283 /* Return length */ 01284 *BufferLength = (ULONG)IoStatusBlock.Information; 01285 } 01286 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01287 { 01288 /* Get the exception code */ 01289 Status = _SEH2_GetExceptionCode(); 01290 } 01291 _SEH2_END; 01292 } 01293 01294 /* Return Status */ 01295 return Status; 01296 } 01297 01298 NTSTATUS 01299 NTAPI 01300 IopQueryNameFile(IN PVOID ObjectBody, 01301 IN BOOLEAN HasName, 01302 OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 01303 IN ULONG Length, 01304 OUT PULONG ReturnLength, 01305 IN KPROCESSOR_MODE PreviousMode) 01306 { 01307 POBJECT_NAME_INFORMATION LocalInfo; 01308 PFILE_NAME_INFORMATION LocalFileInfo; 01309 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 01310 ULONG LocalReturnLength, FileLength; 01311 BOOLEAN LengthMismatch = FALSE; 01312 NTSTATUS Status; 01313 PWCHAR p; 01314 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 01315 01316 /* Validate length */ 01317 if (Length < sizeof(OBJECT_NAME_INFORMATION)) 01318 { 01319 /* Wrong length, fail */ 01320 *ReturnLength = sizeof(OBJECT_NAME_INFORMATION); 01321 return STATUS_INFO_LENGTH_MISMATCH; 01322 } 01323 01324 /* Allocate Buffer */ 01325 LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO); 01326 if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES; 01327 01328 /* Query the name */ 01329 Status = ObQueryNameString(FileObject->DeviceObject, 01330 LocalInfo, 01331 Length, 01332 &LocalReturnLength); 01333 if (!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH)) 01334 { 01335 /* Free the buffer and fail */ 01336 ExFreePoolWithTag(LocalInfo, TAG_IO); 01337 return Status; 01338 } 01339 01340 /* Copy the information */ 01341 RtlCopyMemory(ObjectNameInfo, 01342 LocalInfo, 01343 (LocalReturnLength > Length) ? 01344 Length : LocalReturnLength); 01345 01346 /* Set buffer pointer */ 01347 p = (PWCHAR)(ObjectNameInfo + 1); 01348 ObjectNameInfo->Name.Buffer = p; 01349 01350 /* Advance in buffer */ 01351 p += (LocalInfo->Name.Length / sizeof(WCHAR)); 01352 01353 /* Check if this already filled our buffer */ 01354 if (LocalReturnLength > Length) 01355 { 01356 /* Set the length mismatch to true, so that we can return 01357 * the proper buffer size to the caller later 01358 */ 01359 LengthMismatch = TRUE; 01360 01361 /* Save the initial buffer length value */ 01362 *ReturnLength = LocalReturnLength; 01363 } 01364 01365 /* Now get the file name buffer and check the length needed */ 01366 LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo; 01367 FileLength = Length - 01368 LocalReturnLength + 01369 FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 01370 01371 /* Query the File name */ 01372 Status = IoQueryFileInformation(FileObject, 01373 FileNameInformation, 01374 LengthMismatch ? Length : FileLength, 01375 LocalFileInfo, 01376 &LocalReturnLength); 01377 if (NT_ERROR(Status)) 01378 { 01379 /* Fail on errors only, allow warnings */ 01380 ExFreePoolWithTag(LocalInfo, TAG_IO); 01381 return Status; 01382 } 01383 01384 /* If the provided buffer is too small, return the required size */ 01385 if (LengthMismatch) 01386 { 01387 /* Add the required length */ 01388 *ReturnLength += LocalFileInfo->FileNameLength; 01389 01390 /* Free the allocated buffer and return failure */ 01391 ExFreePoolWithTag(LocalInfo, TAG_IO); 01392 return STATUS_BUFFER_OVERFLOW; 01393 } 01394 01395 /* Now calculate the new lengths left */ 01396 FileLength = LocalReturnLength - 01397 FIELD_OFFSET(FILE_NAME_INFORMATION, FileName); 01398 LocalReturnLength = (ULONG)((ULONG_PTR)p - 01399 (ULONG_PTR)ObjectNameInfo + 01400 LocalFileInfo->FileNameLength); 01401 01402 /* Write the Name and null-terminate it */ 01403 RtlCopyMemory(p, LocalFileInfo->FileName, FileLength); 01404 p += (FileLength / sizeof(WCHAR)); 01405 *p = UNICODE_NULL; 01406 LocalReturnLength += sizeof(UNICODE_NULL); 01407 01408 /* Return the length needed */ 01409 *ReturnLength = LocalReturnLength; 01410 01411 /* Setup the length and maximum length */ 01412 FileLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo); 01413 ObjectNameInfo->Name.Length = (USHORT)FileLength - 01414 sizeof(OBJECT_NAME_INFORMATION); 01415 ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length + 01416 sizeof(UNICODE_NULL); 01417 01418 /* Free buffer and return */ 01419 ExFreePoolWithTag(LocalInfo, TAG_IO); 01420 return Status; 01421 } 01422 01423 VOID 01424 NTAPI 01425 IopCloseFile(IN PEPROCESS Process OPTIONAL, 01426 IN PVOID ObjectBody, 01427 IN ACCESS_MASK GrantedAccess, 01428 IN ULONG HandleCount, 01429 IN ULONG SystemHandleCount) 01430 { 01431 PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody; 01432 KEVENT Event; 01433 PIRP Irp; 01434 PIO_STACK_LOCATION StackPtr; 01435 NTSTATUS Status; 01436 PDEVICE_OBJECT DeviceObject; 01437 KIRQL OldIrql; 01438 IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); 01439 01440 /* If this isn't the last handle for the current process, quit */ 01441 if (HandleCount != 1) return; 01442 01443 /* Check if the file is locked and has more then one handle opened */ 01444 if ((FileObject->LockOperation) && (SystemHandleCount != 1)) 01445 { 01446 DPRINT1("We need to unlock this file!\n"); 01447 ASSERT(FALSE); 01448 } 01449 01450 /* Make sure this is the last handle */ 01451 if (SystemHandleCount != 1) return; 01452 01453 /* Check if this is a direct open or not */ 01454 if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) 01455 { 01456 /* Get the attached device */ 01457 DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); 01458 } 01459 else 01460 { 01461 /* Get the FO's device */ 01462 DeviceObject = IoGetRelatedDeviceObject(FileObject); 01463 } 01464 01465 /* Set the handle created flag */ 01466 FileObject->Flags |= FO_HANDLE_CREATED; 01467 01468 /* Check if this is a sync FO and lock it */ 01469 if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopLockFileObject(FileObject); 01470 01471 /* Clear and set up Events */ 01472 KeClearEvent(&FileObject->Event); 01473 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 01474 01475 /* Allocate an IRP */ 01476 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 01477 if (!Irp) return; 01478 01479 /* Set it up */ 01480 Irp->UserEvent = &Event; 01481 Irp->UserIosb = &Irp->IoStatus; 01482 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01483 Irp->Tail.Overlay.OriginalFileObject = FileObject; 01484 Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; 01485 Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API; 01486 01487 /* Set up Stack Pointer Data */ 01488 StackPtr = IoGetNextIrpStackLocation(Irp); 01489 StackPtr->MajorFunction = IRP_MJ_CLEANUP; 01490 StackPtr->FileObject = FileObject; 01491 01492 /* Queue the IRP */ 01493 IopQueueIrpToThread(Irp); 01494 01495 /* Update operation counts */ 01496 IopUpdateOperationCount(IopOtherTransfer); 01497 01498 /* Call the FS Driver */ 01499 Status = IoCallDriver(DeviceObject, Irp); 01500 if (Status == STATUS_PENDING) 01501 { 01502 /* Wait for completion */ 01503 KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL); 01504 } 01505 01506 /* Unqueue the IRP */ 01507 KeRaiseIrql(APC_LEVEL, &OldIrql); 01508 IopUnQueueIrpFromThread(Irp); 01509 KeLowerIrql(OldIrql); 01510 01511 /* Free the IRP */ 01512 IoFreeIrp(Irp); 01513 01514 /* Release the lock if we were holding it */ 01515 if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject); 01516 } 01517 01518 NTSTATUS 01519 NTAPI 01520 IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 01521 IN FILE_INFORMATION_CLASS FileInformationClass, 01522 IN ULONG FileInformationSize, 01523 OUT PVOID FileInformation) 01524 { 01525 NTSTATUS Status; 01526 KPROCESSOR_MODE AccessMode = ExGetPreviousMode(); 01527 DUMMY_FILE_OBJECT DummyFileObject; 01528 FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo; 01529 HANDLE Handle; 01530 OPEN_PACKET OpenPacket; 01531 BOOLEAN IsBasic; 01532 PAGED_CODE(); 01533 IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass); 01534 01535 /* Check if the caller was user mode */ 01536 if (AccessMode != KernelMode) 01537 { 01538 /* Protect probe in SEH */ 01539 _SEH2_TRY 01540 { 01541 /* Probe the buffer */ 01542 ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG)); 01543 } 01544 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01545 { 01546 /* Return the exception code */ 01547 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01548 } 01549 _SEH2_END; 01550 } 01551 01552 /* Check if this is a basic or full request */ 01553 IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION)); 01554 01555 /* Setup the Open Packet */ 01556 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 01557 OpenPacket.Type = IO_TYPE_OPEN_PACKET; 01558 OpenPacket.Size = sizeof(OPEN_PACKET); 01559 OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; 01560 OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 01561 OpenPacket.Disposition = FILE_OPEN; 01562 OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL; 01563 OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo : 01564 (AccessMode != KernelMode) ? 01565 &NetworkOpenInfo : FileInformation; 01566 OpenPacket.QueryOnly = TRUE; 01567 OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE; 01568 OpenPacket.DummyFileObject = &DummyFileObject; 01569 01570 /* Update the operation count */ 01571 IopUpdateOperationCount(IopOtherTransfer); 01572 01573 /* 01574 * Attempt opening the file. This will call the I/O Parse Routine for 01575 * the File Object (IopParseDevice) which will use the dummy file obejct 01576 * send the IRP to its device object. Note that we have two statuses 01577 * to worry about: the Object Manager's status (in Status) and the I/O 01578 * status, which is in the Open Packet's Final Status, and determined 01579 * by the Parse Check member. 01580 */ 01581 Status = ObOpenObjectByName(ObjectAttributes, 01582 NULL, 01583 AccessMode, 01584 NULL, 01585 FILE_READ_ATTRIBUTES, 01586 &OpenPacket, 01587 &Handle); 01588 if (OpenPacket.ParseCheck != TRUE) 01589 { 01590 /* Parse failed */ 01591 return Status; 01592 } 01593 else 01594 { 01595 /* Use the Io status */ 01596 Status = OpenPacket.FinalStatus; 01597 } 01598 01599 /* Check if we were succesful and this was user mode and a full query */ 01600 if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic)) 01601 { 01602 /* Enter SEH for copy */ 01603 _SEH2_TRY 01604 { 01605 /* Copy the buffer back */ 01606 RtlCopyMemory(FileInformation, 01607 &NetworkOpenInfo, 01608 FileInformationSize); 01609 } 01610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01611 { 01612 /* Get exception code */ 01613 Status = _SEH2_GetExceptionCode(); 01614 } 01615 _SEH2_END; 01616 } 01617 01618 /* Return status */ 01619 return Status; 01620 } 01621 01622 PVOID 01623 NTAPI 01624 IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject) 01625 { 01626 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 01627 { 01628 UNIMPLEMENTED; 01629 /* FIXME: return NULL for the moment ~ */ 01630 return NULL; 01631 } 01632 01633 return NULL; 01634 } 01635 01636 NTSTATUS 01637 NTAPI 01638 IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject, 01639 IN PVOID FilterContext, 01640 IN BOOLEAN Define) 01641 { 01642 if (!(FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)) 01643 { 01644 return STATUS_INVALID_PARAMETER; 01645 } 01646 01647 UNIMPLEMENTED; 01648 01649 return STATUS_NOT_IMPLEMENTED; 01650 } 01651 01652 /* FUNCTIONS *****************************************************************/ 01653 01654 /* 01655 * @unimplemented 01656 */ 01657 NTSTATUS 01658 NTAPI 01659 IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass, 01660 IN ULONG Length, 01661 IN BOOLEAN SetOperation) 01662 { 01663 UNIMPLEMENTED; 01664 return STATUS_NOT_IMPLEMENTED; 01665 } 01666 01667 /* 01668 * @unimplemented 01669 */ 01670 NTSTATUS 01671 NTAPI 01672 IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer, 01673 IN ULONG QuotaLength, 01674 OUT PULONG ErrorOffset) 01675 { 01676 UNIMPLEMENTED; 01677 return STATUS_NOT_IMPLEMENTED; 01678 } 01679 01680 /* 01681 * @implemented 01682 */ 01683 NTSTATUS 01684 NTAPI 01685 IoCreateFile(OUT PHANDLE FileHandle, 01686 IN ACCESS_MASK DesiredAccess, 01687 IN POBJECT_ATTRIBUTES ObjectAttributes, 01688 OUT PIO_STATUS_BLOCK IoStatusBlock, 01689 IN PLARGE_INTEGER AllocationSize OPTIONAL, 01690 IN ULONG FileAttributes, 01691 IN ULONG ShareAccess, 01692 IN ULONG Disposition, 01693 IN ULONG CreateOptions, 01694 IN PVOID EaBuffer OPTIONAL, 01695 IN ULONG EaLength, 01696 IN CREATE_FILE_TYPE CreateFileType, 01697 IN PVOID ExtraCreateParameters OPTIONAL, 01698 IN ULONG Options) 01699 { 01700 KPROCESSOR_MODE AccessMode; 01701 HANDLE LocalHandle = 0; 01702 LARGE_INTEGER SafeAllocationSize; 01703 PVOID SystemEaBuffer = NULL; 01704 NTSTATUS Status; 01705 OPEN_PACKET OpenPacket; 01706 ULONG EaErrorOffset; 01707 01708 PAGED_CODE(); 01709 IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 01710 01711 /* Check if we have no parameter checking to do */ 01712 if (Options & IO_NO_PARAMETER_CHECKING) 01713 { 01714 /* Then force kernel-mode access to avoid checks */ 01715 AccessMode = KernelMode; 01716 } 01717 else 01718 { 01719 /* Otherwise, use the actual mode */ 01720 AccessMode = ExGetPreviousMode(); 01721 } 01722 01723 /* Check if the call came from user mode */ 01724 if (AccessMode != KernelMode) 01725 { 01726 _SEH2_TRY 01727 { 01728 ProbeForWriteHandle(FileHandle); 01729 ProbeForWriteIoStatusBlock(IoStatusBlock); 01730 if (AllocationSize) 01731 { 01732 SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize); 01733 } 01734 else 01735 { 01736 SafeAllocationSize.QuadPart = 0; 01737 } 01738 01739 if ((EaBuffer) && (EaLength)) 01740 { 01741 ProbeForRead(EaBuffer, 01742 EaLength, 01743 sizeof(ULONG)); 01744 01745 /* marshal EaBuffer */ 01746 SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool, 01747 EaLength, 01748 TAG_EA); 01749 if(!SystemEaBuffer) 01750 { 01751 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES); 01752 } 01753 01754 RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength); 01755 01756 /* Validate the buffer */ 01757 Status = IoCheckEaBufferValidity(SystemEaBuffer, 01758 EaLength, 01759 &EaErrorOffset); 01760 if (!NT_SUCCESS(Status)) 01761 { 01762 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with " 01763 "Status: %lx\n",Status); 01764 01765 /* Free EA Buffer and return the error */ 01766 ExFreePoolWithTag(SystemEaBuffer, TAG_EA); 01767 _SEH2_YIELD(return Status); 01768 } 01769 } 01770 } 01771 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01772 { 01773 /* Free SystemEaBuffer if needed */ 01774 if (SystemEaBuffer) ExFreePoolWithTag(SystemEaBuffer, TAG_EA); 01775 01776 /* Return the exception code */ 01777 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 01778 } 01779 _SEH2_END; 01780 } 01781 else 01782 { 01783 /* Check if this is a device attach */ 01784 if (CreateOptions & IO_ATTACH_DEVICE_API) 01785 { 01786 /* Set the flag properly */ 01787 Options |= IO_ATTACH_DEVICE; 01788 CreateOptions &= ~IO_ATTACH_DEVICE_API; 01789 } 01790 01791 /* Check if we have allocation size */ 01792 if (AllocationSize) 01793 { 01794 /* Capture it */ 01795 SafeAllocationSize = *AllocationSize; 01796 } 01797 else 01798 { 01799 /* Otherwise, no size */ 01800 SafeAllocationSize.QuadPart = 0; 01801 } 01802 01803 /* Check if we have an EA packet */ 01804 if ((EaBuffer) && (EaLength)) 01805 { 01806 /* Allocate the kernel copy */ 01807 SystemEaBuffer = ExAllocatePoolWithTag(NonPagedPool, 01808 EaLength, 01809 TAG_EA); 01810 if (!SystemEaBuffer) return STATUS_INSUFFICIENT_RESOURCES; 01811 01812 /* Copy the data */ 01813 RtlCopyMemory(SystemEaBuffer, EaBuffer, EaLength); 01814 01815 /* Validate the buffer */ 01816 Status = IoCheckEaBufferValidity(SystemEaBuffer, 01817 EaLength, 01818 &EaErrorOffset); 01819 if (!NT_SUCCESS(Status)) 01820 { 01821 DPRINT1("FIXME: IoCheckEaBufferValidity() failed with " 01822 "Status: %lx\n",Status); 01823 } 01824 } 01825 } 01826 01827 /* Setup the Open Packet */ 01828 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 01829 OpenPacket.Type = IO_TYPE_OPEN_PACKET; 01830 OpenPacket.Size = sizeof(OPEN_PACKET); 01831 OpenPacket.OriginalAttributes = *ObjectAttributes; 01832 OpenPacket.AllocationSize = SafeAllocationSize; 01833 OpenPacket.CreateOptions = CreateOptions; 01834 OpenPacket.FileAttributes = (USHORT)FileAttributes; 01835 OpenPacket.ShareAccess = (USHORT)ShareAccess; 01836 OpenPacket.EaBuffer = SystemEaBuffer; 01837 OpenPacket.EaLength = EaLength; 01838 OpenPacket.Options = Options; 01839 OpenPacket.Disposition = Disposition; 01840 OpenPacket.CreateFileType = CreateFileType; 01841 OpenPacket.MailslotOrPipeParameters = ExtraCreateParameters; 01842 01843 /* Update the operation count */ 01844 IopUpdateOperationCount(IopOtherTransfer); 01845 01846 /* 01847 * Attempt opening the file. This will call the I/O Parse Routine for 01848 * the File Object (IopParseDevice) which will create the object and 01849 * send the IRP to its device object. Note that we have two statuses 01850 * to worry about: the Object Manager's status (in Status) and the I/O 01851 * status, which is in the Open Packet's Final Status, and determined 01852 * by the Parse Check member. 01853 */ 01854 Status = ObOpenObjectByName(ObjectAttributes, 01855 NULL, 01856 AccessMode, 01857 NULL, 01858 DesiredAccess, 01859 &OpenPacket, 01860 &LocalHandle); 01861 01862 /* Free the EA Buffer */ 01863 if (OpenPacket.EaBuffer) ExFreePool(OpenPacket.EaBuffer); 01864 01865 /* Now check for Ob or Io failure */ 01866 if (!(NT_SUCCESS(Status)) || (OpenPacket.ParseCheck != TRUE)) 01867 { 01868 /* Check if Ob thinks well went well */ 01869 if (NT_SUCCESS(Status)) 01870 { 01871 /* 01872 * Tell it otherwise. Because we didn't use an ObjectType, 01873 * it incorrectly returned us a handle to God knows what. 01874 */ 01875 ZwClose(LocalHandle); 01876 Status = STATUS_OBJECT_TYPE_MISMATCH; 01877 } 01878 01879 /* Now check the Io status */ 01880 if (!NT_SUCCESS(OpenPacket.FinalStatus)) 01881 { 01882 /* Use this status instead of Ob's */ 01883 Status = OpenPacket.FinalStatus; 01884 01885 /* Check if it was only a warning */ 01886 if (NT_WARNING(Status)) 01887 { 01888 /* Protect write with SEH */ 01889 _SEH2_TRY 01890 { 01891 /* In this case, we copy the I/O Status back */ 01892 IoStatusBlock->Information = OpenPacket.Information; 01893 IoStatusBlock->Status = OpenPacket.FinalStatus; 01894 } 01895 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01896 { 01897 /* Get exception code */ 01898 Status = _SEH2_GetExceptionCode(); 01899 } 01900 _SEH2_END; 01901 } 01902 } 01903 else if ((OpenPacket.FileObject) && (OpenPacket.ParseCheck != 1)) 01904 { 01905 /* 01906 * This can happen in the very bizarre case where the parse routine 01907 * actually executed more then once (due to a reparse) and ended 01908 * up failing after already having created the File Object. 01909 */ 01910 if (OpenPacket.FileObject->FileName.Length) 01911 { 01912 /* It had a name, free it */ 01913 ExFreePoolWithTag(OpenPacket.FileObject->FileName.Buffer, TAG_IO_NAME); 01914 } 01915 01916 /* Clear the device object to invalidate the FO, and dereference */ 01917 OpenPacket.FileObject->DeviceObject = NULL; 01918 ObDereferenceObject(OpenPacket.FileObject); 01919 } 01920 } 01921 else 01922 { 01923 /* We reached success and have a valid file handle */ 01924 OpenPacket.FileObject->Flags |= FO_HANDLE_CREATED; 01925 01926 /* Enter SEH for write back */ 01927 _SEH2_TRY 01928 { 01929 /* Write back the handle and I/O Status */ 01930 *FileHandle = LocalHandle; 01931 IoStatusBlock->Information = OpenPacket.Information; 01932 IoStatusBlock->Status = OpenPacket.FinalStatus; 01933 01934 /* Get the Io status */ 01935 Status = OpenPacket.FinalStatus; 01936 } 01937 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01938 { 01939 /* Get the exception status */ 01940 Status = _SEH2_GetExceptionCode(); 01941 } 01942 _SEH2_END; 01943 } 01944 01945 /* Check if we were 100% successful */ 01946 if ((OpenPacket.ParseCheck == TRUE) && (OpenPacket.FileObject)) 01947 { 01948 /* Dereference the File Object */ 01949 ObDereferenceObject(OpenPacket.FileObject); 01950 } 01951 01952 /* Return status */ 01953 return Status; 01954 } 01955 01956 /* 01957 * @unimplemented 01958 */ 01959 NTSTATUS 01960 NTAPI 01961 IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle, 01962 IN ACCESS_MASK DesiredAccess, 01963 IN POBJECT_ATTRIBUTES ObjectAttributes, 01964 OUT PIO_STATUS_BLOCK IoStatusBlock, 01965 IN PLARGE_INTEGER AllocationSize OPTIONAL, 01966 IN ULONG FileAttributes, 01967 IN ULONG ShareAccess, 01968 IN ULONG Disposition, 01969 IN ULONG CreateOptions, 01970 IN PVOID EaBuffer OPTIONAL, 01971 IN ULONG EaLength, 01972 IN CREATE_FILE_TYPE CreateFileType, 01973 IN PVOID ExtraCreateParameters OPTIONAL, 01974 IN ULONG Options, 01975 IN PVOID DeviceObject) 01976 { 01977 UNIMPLEMENTED; 01978 return STATUS_NOT_IMPLEMENTED; 01979 } 01980 01981 /* 01982 * @implemented 01983 */ 01984 PFILE_OBJECT 01985 NTAPI 01986 IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL, 01987 IN PDEVICE_OBJECT DeviceObject OPTIONAL, 01988 OUT PHANDLE FileObjectHandle OPTIONAL) 01989 { 01990 PFILE_OBJECT CreatedFileObject; 01991 NTSTATUS Status; 01992 HANDLE FileHandle; 01993 OBJECT_ATTRIBUTES ObjectAttributes; 01994 PAGED_CODE(); 01995 IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 01996 01997 /* Choose Device Object */ 01998 if (FileObject) DeviceObject = FileObject->DeviceObject; 01999 02000 /* Reference the device object and initialize attributes */ 02001 InterlockedIncrement(&DeviceObject->ReferenceCount); 02002 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 02003 02004 /* Create the File Object */ 02005 Status = ObCreateObject(KernelMode, 02006 IoFileObjectType, 02007 &ObjectAttributes, 02008 KernelMode, 02009 NULL, 02010 sizeof(FILE_OBJECT), 02011 sizeof(FILE_OBJECT), 02012 0, 02013 (PVOID*)&CreatedFileObject); 02014 if (!NT_SUCCESS(Status)) 02015 { 02016 /* Fail */ 02017 IopDereferenceDeviceObject(DeviceObject, FALSE); 02018 ExRaiseStatus(Status); 02019 } 02020 02021 /* Set File Object Data */ 02022 RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 02023 CreatedFileObject->DeviceObject = DeviceObject; 02024 CreatedFileObject->Type = IO_TYPE_FILE; 02025 CreatedFileObject->Size = sizeof(FILE_OBJECT); 02026 CreatedFileObject->Flags = FO_STREAM_FILE; 02027 02028 /* Initialize the wait event */ 02029 KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 02030 02031 /* Insert it to create a handle for it */ 02032 Status = ObInsertObject(CreatedFileObject, 02033 NULL, 02034 FILE_READ_DATA, 02035 1, 02036 (PVOID*)&CreatedFileObject, 02037 &FileHandle); 02038 if (!NT_SUCCESS(Status)) ExRaiseStatus(Status); 02039 02040 /* Set the handle created flag */ 02041 CreatedFileObject->Flags |= FO_HANDLE_CREATED; 02042 ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 02043 02044 /* Check if we have a VPB */ 02045 if (DeviceObject->Vpb) 02046 { 02047 /* Reference it */ 02048 InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 02049 } 02050 02051 /* Check if the caller wants the handle */ 02052 if (FileObjectHandle) 02053 { 02054 /* Return it */ 02055 *FileObjectHandle = FileHandle; 02056 ObDereferenceObject(CreatedFileObject); 02057 } 02058 else 02059 { 02060 /* Otherwise, close it */ 02061 ObCloseHandle(FileHandle, KernelMode); 02062 } 02063 02064 /* Return the file object */ 02065 return CreatedFileObject; 02066 } 02067 02068 /* 02069 * @implemented 02070 */ 02071 PFILE_OBJECT 02072 NTAPI 02073 IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, 02074 IN PDEVICE_OBJECT DeviceObject) 02075 { 02076 /* Call the newer function */ 02077 return IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL); 02078 } 02079 02080 /* 02081 * @implemented 02082 */ 02083 PFILE_OBJECT 02084 NTAPI 02085 IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL, 02086 IN PDEVICE_OBJECT DeviceObject OPTIONAL) 02087 { 02088 PFILE_OBJECT CreatedFileObject; 02089 NTSTATUS Status; 02090 OBJECT_ATTRIBUTES ObjectAttributes; 02091 PAGED_CODE(); 02092 IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject); 02093 02094 /* Choose Device Object */ 02095 if (FileObject) DeviceObject = FileObject->DeviceObject; 02096 02097 /* Reference the device object and initialize attributes */ 02098 InterlockedIncrement(&DeviceObject->ReferenceCount); 02099 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 02100 02101 /* Create the File Object */ 02102 Status = ObCreateObject(KernelMode, 02103 IoFileObjectType, 02104 &ObjectAttributes, 02105 KernelMode, 02106 NULL, 02107 sizeof(FILE_OBJECT), 02108 sizeof(FILE_OBJECT), 02109 0, 02110 (PVOID*)&CreatedFileObject); 02111 if (!NT_SUCCESS(Status)) 02112 { 02113 /* Fail */ 02114 IopDereferenceDeviceObject(DeviceObject, FALSE); 02115 ExRaiseStatus(Status); 02116 } 02117 02118 /* Set File Object Data */ 02119 RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT)); 02120 CreatedFileObject->DeviceObject = DeviceObject; 02121 CreatedFileObject->Type = IO_TYPE_FILE; 02122 CreatedFileObject->Size = sizeof(FILE_OBJECT); 02123 CreatedFileObject->Flags = FO_STREAM_FILE; 02124 02125 /* Initialize the wait event */ 02126 KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE); 02127 02128 /* Destroy create information */ 02129 ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject)-> 02130 ObjectCreateInfo); 02131 OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL; 02132 02133 /* Set the handle created flag */ 02134 CreatedFileObject->Flags |= FO_HANDLE_CREATED; 02135 ASSERT(CreatedFileObject->Type == IO_TYPE_FILE); 02136 02137 /* Check if we have a VPB */ 02138 if (DeviceObject->Vpb) 02139 { 02140 /* Reference it */ 02141 InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount); 02142 } 02143 02144 /* Return the file object */ 02145 return CreatedFileObject; 02146 } 02147 02148 /* 02149 * @implemented 02150 */ 02151 PGENERIC_MAPPING 02152 NTAPI 02153 IoGetFileObjectGenericMapping(VOID) 02154 { 02155 /* Return the mapping */ 02156 return &IopFileMapping; 02157 } 02158 02159 /* 02160 * @implemented 02161 */ 02162 BOOLEAN 02163 NTAPI 02164 IoIsFileOriginRemote(IN PFILE_OBJECT FileObject) 02165 { 02166 /* Return the flag status */ 02167 return FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 02168 } 02169 02170 /* 02171 * @implemented 02172 */ 02173 BOOLEAN 02174 NTAPI 02175 IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes, 02176 IN ACCESS_MASK DesiredAccess, 02177 IN ULONG OpenOptions, 02178 OUT PIO_STATUS_BLOCK IoStatus, 02179 OUT PFILE_NETWORK_OPEN_INFORMATION Buffer) 02180 { 02181 NTSTATUS Status; 02182 DUMMY_FILE_OBJECT DummyFileObject; 02183 HANDLE Handle; 02184 OPEN_PACKET OpenPacket; 02185 PAGED_CODE(); 02186 IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName); 02187 02188 /* Setup the Open Packet */ 02189 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 02190 OpenPacket.Type = IO_TYPE_OPEN_PACKET; 02191 OpenPacket.Size = sizeof(OPEN_PACKET); 02192 OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT; 02193 OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 02194 OpenPacket.Options = IO_FORCE_ACCESS_CHECK; 02195 OpenPacket.Disposition = FILE_OPEN; 02196 OpenPacket.NetworkInformation = Buffer; 02197 OpenPacket.QueryOnly = TRUE; 02198 OpenPacket.FullAttributes = TRUE; 02199 OpenPacket.DummyFileObject = &DummyFileObject; 02200 02201 /* 02202 * Attempt opening the file. This will call the I/O Parse Routine for 02203 * the File Object (IopParseDevice) which will use the dummy file obejct 02204 * send the IRP to its device object. Note that we have two statuses 02205 * to worry about: the Object Manager's status (in Status) and the I/O 02206 * status, which is in the Open Packet's Final Status, and determined 02207 * by the Parse Check member. 02208 */ 02209 Status = ObOpenObjectByName(ObjectAttributes, 02210 NULL, 02211 KernelMode, 02212 NULL, 02213 DesiredAccess, 02214 &OpenPacket, 02215 &Handle); 02216 if (OpenPacket.ParseCheck != TRUE) 02217 { 02218 /* Parse failed */ 02219 IoStatus->Status = Status; 02220 } 02221 else 02222 { 02223 /* Use the Io status */ 02224 IoStatus->Status = OpenPacket.FinalStatus; 02225 IoStatus->Information = OpenPacket.Information; 02226 } 02227 02228 /* Return success */ 02229 return TRUE; 02230 } 02231 02232 /* 02233 * @implemented 02234 */ 02235 VOID 02236 NTAPI 02237 IoUpdateShareAccess(IN PFILE_OBJECT FileObject, 02238 OUT PSHARE_ACCESS ShareAccess) 02239 { 02240 PAGED_CODE(); 02241 02242 /* Check if the file has an extension */ 02243 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 02244 { 02245 /* Check if caller specified to ignore access checks */ 02246 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 02247 { 02248 /* Don't update share access */ 02249 return; 02250 } 02251 } 02252 02253 /* Otherwise, check if there's any access present */ 02254 if ((FileObject->ReadAccess) || 02255 (FileObject->WriteAccess) || 02256 (FileObject->DeleteAccess)) 02257 { 02258 /* Increase the open count */ 02259 ShareAccess->OpenCount++; 02260 02261 /* Add new share access */ 02262 ShareAccess->Readers += FileObject->ReadAccess; 02263 ShareAccess->Writers += FileObject->WriteAccess; 02264 ShareAccess->Deleters += FileObject->DeleteAccess; 02265 ShareAccess->SharedRead += FileObject->SharedRead; 02266 ShareAccess->SharedWrite += FileObject->SharedWrite; 02267 ShareAccess->SharedDelete += FileObject->SharedDelete; 02268 } 02269 } 02270 02271 /* 02272 * @implemented 02273 */ 02274 NTSTATUS 02275 NTAPI 02276 IoCheckShareAccess(IN ACCESS_MASK DesiredAccess, 02277 IN ULONG DesiredShareAccess, 02278 IN PFILE_OBJECT FileObject, 02279 IN PSHARE_ACCESS ShareAccess, 02280 IN BOOLEAN Update) 02281 { 02282 BOOLEAN ReadAccess; 02283 BOOLEAN WriteAccess; 02284 BOOLEAN DeleteAccess; 02285 BOOLEAN SharedRead; 02286 BOOLEAN SharedWrite; 02287 BOOLEAN SharedDelete; 02288 PAGED_CODE(); 02289 02290 /* Get access masks */ 02291 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 02292 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 02293 DeleteAccess = (DesiredAccess & DELETE) != 0; 02294 02295 /* Set them in the file object */ 02296 FileObject->ReadAccess = ReadAccess; 02297 FileObject->WriteAccess = WriteAccess; 02298 FileObject->DeleteAccess = DeleteAccess; 02299 02300 /* Check if the file has an extension */ 02301 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 02302 { 02303 /* Check if caller specified to ignore access checks */ 02304 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 02305 { 02306 /* Don't check share access */ 02307 return STATUS_SUCCESS; 02308 } 02309 } 02310 02311 /* Check if we have any access */ 02312 if ((ReadAccess) || (WriteAccess) || (DeleteAccess)) 02313 { 02314 /* Get shared access masks */ 02315 SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 02316 SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 02317 SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 02318 02319 /* Set them */ 02320 FileObject->SharedRead = SharedRead; 02321 FileObject->SharedWrite = SharedWrite; 02322 FileObject->SharedDelete = SharedDelete; 02323 02324 /* Check if the shared access is violated */ 02325 if ((ReadAccess && 02326 (ShareAccess->SharedRead < ShareAccess->OpenCount)) || 02327 (WriteAccess && 02328 (ShareAccess->SharedWrite < ShareAccess->OpenCount)) || 02329 (DeleteAccess && 02330 (ShareAccess->SharedDelete < ShareAccess->OpenCount)) || 02331 ((ShareAccess->Readers != 0) && !SharedRead) || 02332 ((ShareAccess->Writers != 0) && !SharedWrite) || 02333 ((ShareAccess->Deleters != 0) && !SharedDelete)) 02334 { 02335 /* Sharing violation, fail */ 02336 return STATUS_SHARING_VIOLATION; 02337 } 02338 02339 /* It's not, check if caller wants us to update it */ 02340 if (Update) 02341 { 02342 /* Increase open count */ 02343 ShareAccess->OpenCount++; 02344 02345 /* Update shared access */ 02346 ShareAccess->Readers += ReadAccess; 02347 ShareAccess->Writers += WriteAccess; 02348 ShareAccess->Deleters += DeleteAccess; 02349 ShareAccess->SharedRead += SharedRead; 02350 ShareAccess->SharedWrite += SharedWrite; 02351 ShareAccess->SharedDelete += SharedDelete; 02352 } 02353 } 02354 02355 /* Validation successful */ 02356 return STATUS_SUCCESS; 02357 } 02358 02359 /* 02360 * @implemented 02361 */ 02362 VOID 02363 NTAPI 02364 IoRemoveShareAccess(IN PFILE_OBJECT FileObject, 02365 IN PSHARE_ACCESS ShareAccess) 02366 { 02367 PAGED_CODE(); 02368 02369 /* Check if the file has an extension */ 02370 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 02371 { 02372 /* Check if caller specified to ignore access checks */ 02373 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 02374 { 02375 /* Don't update share access */ 02376 return; 02377 } 02378 } 02379 02380 /* Otherwise, check if there's any access present */ 02381 if ((FileObject->ReadAccess) || 02382 (FileObject->WriteAccess) || 02383 (FileObject->DeleteAccess)) 02384 { 02385 /* Decrement the open count */ 02386 ShareAccess->OpenCount--; 02387 02388 /* Remove share access */ 02389 ShareAccess->Readers -= FileObject->ReadAccess; 02390 ShareAccess->Writers -= FileObject->WriteAccess; 02391 ShareAccess->Deleters -= FileObject->DeleteAccess; 02392 ShareAccess->SharedRead -= FileObject->SharedRead; 02393 ShareAccess->SharedWrite -= FileObject->SharedWrite; 02394 ShareAccess->SharedDelete -= FileObject->SharedDelete; 02395 } 02396 } 02397 02398 /* 02399 * @implemented 02400 */ 02401 VOID 02402 NTAPI 02403 IoSetShareAccess(IN ACCESS_MASK DesiredAccess, 02404 IN ULONG DesiredShareAccess, 02405 IN PFILE_OBJECT FileObject, 02406 OUT PSHARE_ACCESS ShareAccess) 02407 { 02408 BOOLEAN ReadAccess; 02409 BOOLEAN WriteAccess; 02410 BOOLEAN DeleteAccess; 02411 BOOLEAN SharedRead; 02412 BOOLEAN SharedWrite; 02413 BOOLEAN SharedDelete; 02414 BOOLEAN Update = TRUE; 02415 PAGED_CODE(); 02416 02417 ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0; 02418 WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0; 02419 DeleteAccess = (DesiredAccess & DELETE) != 0; 02420 02421 /* Check if the file has an extension */ 02422 if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) 02423 { 02424 /* Check if caller specified to ignore access checks */ 02425 //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK) 02426 { 02427 /* Don't update share access */ 02428 Update = FALSE; 02429 } 02430 } 02431 02432 /* Update basic access */ 02433 FileObject->ReadAccess = ReadAccess; 02434 FileObject->WriteAccess = WriteAccess; 02435 FileObject->DeleteAccess = DeleteAccess; 02436 02437 /* Check if we have no access as all */ 02438 if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess)) 02439 { 02440 /* Check if we need to update the structure */ 02441 if (!Update) return; 02442 02443 /* Otherwise, clear data */ 02444 ShareAccess->OpenCount = 0; 02445 ShareAccess->Readers = 0; 02446 ShareAccess->Writers = 0; 02447 ShareAccess->Deleters = 0; 02448 ShareAccess->SharedRead = 0; 02449 ShareAccess->SharedWrite = 0; 02450 ShareAccess->SharedDelete = 0; 02451 } 02452 else 02453 { 02454 /* Calculate shared access */ 02455 SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0; 02456 SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0; 02457 SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0; 02458 02459 /* Set it in the FO */ 02460 FileObject->SharedRead = SharedRead; 02461 FileObject->SharedWrite = SharedWrite; 02462 FileObject->SharedDelete = SharedDelete; 02463 02464 /* Check if we need to update the structure */ 02465 if (!Update) return; 02466 02467 /* Otherwise, set data */ 02468 ShareAccess->OpenCount = 1; 02469 ShareAccess->Readers = ReadAccess; 02470 ShareAccess->Writers = WriteAccess; 02471 ShareAccess->Deleters = DeleteAccess; 02472 ShareAccess->SharedRead = SharedRead; 02473 ShareAccess->SharedWrite = SharedWrite; 02474 ShareAccess->SharedDelete = SharedDelete; 02475 } 02476 } 02477 02478 /* 02479 * @unimplemented 02480 */ 02481 VOID 02482 NTAPI 02483 IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject, 02484 IN PFILE_OBJECT FileObject) 02485 { 02486 UNIMPLEMENTED; 02487 } 02488 02489 /* 02490 * @unimplemented 02491 */ 02492 NTSTATUS 02493 NTAPI 02494 IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject, 02495 OUT POBJECT_NAME_INFORMATION *ObjectNameInformation) 02496 { 02497 UNIMPLEMENTED; 02498 return STATUS_NOT_IMPLEMENTED; 02499 } 02500 02501 /* 02502 * @implemented 02503 */ 02504 NTSTATUS 02505 NTAPI 02506 IoSetFileOrigin(IN PFILE_OBJECT FileObject, 02507 IN BOOLEAN Remote) 02508 { 02509 NTSTATUS Status = STATUS_SUCCESS; 02510 BOOLEAN FlagSet; 02511 02512 /* Get the flag status */ 02513 FlagSet = FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE; 02514 02515 /* Don't set the flag if it was set already, and don't remove it if it wasn't set */ 02516 if (Remote && !FlagSet) 02517 { 02518 /* Set the flag */ 02519 FileObject->Flags |= FO_REMOTE_ORIGIN; 02520 } 02521 else if (!Remote && FlagSet) 02522 { 02523 /* Remove the flag */ 02524 FileObject->Flags &= ~FO_REMOTE_ORIGIN; 02525 } 02526 else 02527 { 02528 /* Fail */ 02529 Status = STATUS_INVALID_PARAMETER_MIX; 02530 } 02531 02532 /* Return status */ 02533 return Status; 02534 } 02535 02536 /* 02537 * @implemented 02538 */ 02539 NTSTATUS 02540 NTAPI 02541 NtCreateFile(PHANDLE FileHandle, 02542 ACCESS_MASK DesiredAccess, 02543 POBJECT_ATTRIBUTES ObjectAttributes, 02544 PIO_STATUS_BLOCK IoStatusBlock, 02545 PLARGE_INTEGER AllocateSize, 02546 ULONG FileAttributes, 02547 ULONG ShareAccess, 02548 ULONG CreateDisposition, 02549 ULONG CreateOptions, 02550 PVOID EaBuffer, 02551 ULONG EaLength) 02552 { 02553 /* Call the I/O Function */ 02554 return IoCreateFile(FileHandle, 02555 DesiredAccess, 02556 ObjectAttributes, 02557 IoStatusBlock, 02558 AllocateSize, 02559 FileAttributes, 02560 ShareAccess, 02561 CreateDisposition, 02562 CreateOptions, 02563 EaBuffer, 02564 EaLength, 02565 CreateFileTypeNone, 02566 NULL, 02567 0); 02568 } 02569 02570 NTSTATUS 02571 NTAPI 02572 NtCreateMailslotFile(OUT PHANDLE FileHandle, 02573 IN ACCESS_MASK DesiredAccess, 02574 IN POBJECT_ATTRIBUTES ObjectAttributes, 02575 OUT PIO_STATUS_BLOCK IoStatusBlock, 02576 IN ULONG CreateOptions, 02577 IN ULONG MailslotQuota, 02578 IN ULONG MaxMessageSize, 02579 IN PLARGE_INTEGER TimeOut) 02580 { 02581 MAILSLOT_CREATE_PARAMETERS Buffer; 02582 PAGED_CODE(); 02583 02584 /* Check for Timeout */ 02585 if (TimeOut) 02586 { 02587 /* check if the call came from user mode */ 02588 if (KeGetPreviousMode() != KernelMode) 02589 { 02590 /* Enter SEH for Probe */ 02591 _SEH2_TRY 02592 { 02593 /* Probe the timeout */ 02594 Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut); 02595 } 02596 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02597 { 02598 /* Return the exception code */ 02599 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02600 } 02601 _SEH2_END; 02602 } 02603 else 02604 { 02605 /* Otherwise, capture directly */ 02606 Buffer.ReadTimeout = *TimeOut; 02607 } 02608 02609 /* Set the correct setting */ 02610 Buffer.TimeoutSpecified = TRUE; 02611 } 02612 else 02613 { 02614 /* Tell the FSD we don't have a timeout */ 02615 Buffer.TimeoutSpecified = FALSE; 02616 } 02617 02618 /* Set Settings */ 02619 Buffer.MailslotQuota = MailslotQuota; 02620 Buffer.MaximumMessageSize = MaxMessageSize; 02621 02622 /* Call I/O */ 02623 return IoCreateFile(FileHandle, 02624 DesiredAccess, 02625 ObjectAttributes, 02626 IoStatusBlock, 02627 NULL, 02628 0, 02629 FILE_SHARE_READ | FILE_SHARE_WRITE, 02630 FILE_CREATE, 02631 CreateOptions, 02632 NULL, 02633 0, 02634 CreateFileTypeMailslot, 02635 (PVOID)&Buffer, 02636 0); 02637 } 02638 02639 NTSTATUS 02640 NTAPI 02641 NtCreateNamedPipeFile(OUT PHANDLE FileHandle, 02642 IN ACCESS_MASK DesiredAccess, 02643 IN POBJECT_ATTRIBUTES ObjectAttributes, 02644 OUT PIO_STATUS_BLOCK IoStatusBlock, 02645 IN ULONG ShareAccess, 02646 IN ULONG CreateDisposition, 02647 IN ULONG CreateOptions, 02648 IN ULONG NamedPipeType, 02649 IN ULONG ReadMode, 02650 IN ULONG CompletionMode, 02651 IN ULONG MaximumInstances, 02652 IN ULONG InboundQuota, 02653 IN ULONG OutboundQuota, 02654 IN PLARGE_INTEGER DefaultTimeout) 02655 { 02656 NAMED_PIPE_CREATE_PARAMETERS Buffer; 02657 PAGED_CODE(); 02658 02659 /* Check for Timeout */ 02660 if (DefaultTimeout) 02661 { 02662 /* check if the call came from user mode */ 02663 if (KeGetPreviousMode() != KernelMode) 02664 { 02665 /* Enter SEH for Probe */ 02666 _SEH2_TRY 02667 { 02668 /* Probe the timeout */ 02669 Buffer.DefaultTimeout = 02670 ProbeForReadLargeInteger(DefaultTimeout); 02671 } 02672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02673 { 02674 /* Return the exception code */ 02675 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02676 } 02677 _SEH2_END; 02678 } 02679 else 02680 { 02681 /* Otherwise, capture directly */ 02682 Buffer.DefaultTimeout = *DefaultTimeout; 02683 } 02684 02685 /* Set the correct setting */ 02686 Buffer.TimeoutSpecified = TRUE; 02687 } 02688 else 02689 { 02690 /* Tell the FSD we don't have a timeout */ 02691 Buffer.TimeoutSpecified = FALSE; 02692 } 02693 02694 /* Set Settings */ 02695 Buffer.NamedPipeType = NamedPipeType; 02696 Buffer.ReadMode = ReadMode; 02697 Buffer.CompletionMode = CompletionMode; 02698 Buffer.MaximumInstances = MaximumInstances; 02699 Buffer.InboundQuota = InboundQuota; 02700 Buffer.OutboundQuota = OutboundQuota; 02701 02702 /* Call I/O */ 02703 return IoCreateFile(FileHandle, 02704 DesiredAccess, 02705 ObjectAttributes, 02706 IoStatusBlock, 02707 NULL, 02708 0, 02709 ShareAccess, 02710 CreateDisposition, 02711 CreateOptions, 02712 NULL, 02713 0, 02714 CreateFileTypeNamedPipe, 02715 (PVOID)&Buffer, 02716 0); 02717 } 02718 02719 NTSTATUS 02720 NTAPI 02721 NtFlushWriteBuffer(VOID) 02722 { 02723 PAGED_CODE(); 02724 02725 /* Call the kernel */ 02726 KeFlushWriteBuffer(); 02727 return STATUS_SUCCESS; 02728 } 02729 02730 /* 02731 * @implemented 02732 */ 02733 NTSTATUS 02734 NTAPI 02735 NtOpenFile(OUT PHANDLE FileHandle, 02736 IN ACCESS_MASK DesiredAccess, 02737 IN POBJECT_ATTRIBUTES ObjectAttributes, 02738 OUT PIO_STATUS_BLOCK IoStatusBlock, 02739 IN ULONG ShareAccess, 02740 IN ULONG OpenOptions) 02741 { 02742 /* Call the I/O Function */ 02743 return IoCreateFile(FileHandle, 02744 DesiredAccess, 02745 ObjectAttributes, 02746 IoStatusBlock, 02747 NULL, 02748 0, 02749 ShareAccess, 02750 FILE_OPEN, 02751 OpenOptions, 02752 NULL, 02753 0, 02754 CreateFileTypeNone, 02755 NULL, 02756 0); 02757 } 02758 02759 NTSTATUS 02760 NTAPI 02761 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 02762 OUT PFILE_BASIC_INFORMATION FileInformation) 02763 { 02764 /* Call the internal helper API */ 02765 return IopQueryAttributesFile(ObjectAttributes, 02766 FileBasicInformation, 02767 sizeof(FILE_BASIC_INFORMATION), 02768 FileInformation); 02769 } 02770 02771 NTSTATUS 02772 NTAPI 02773 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes, 02774 OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation) 02775 { 02776 /* Call the internal helper API */ 02777 return IopQueryAttributesFile(ObjectAttributes, 02778 FileNetworkOpenInformation, 02779 sizeof(FILE_NETWORK_OPEN_INFORMATION), 02780 FileInformation); 02781 } 02782 02800 NTSTATUS 02801 NTAPI 02802 NtCancelIoFile(IN HANDLE FileHandle, 02803 OUT PIO_STATUS_BLOCK IoStatusBlock) 02804 { 02805 PFILE_OBJECT FileObject; 02806 PETHREAD Thread; 02807 PIRP Irp; 02808 KIRQL OldIrql; 02809 BOOLEAN OurIrpsInList = FALSE; 02810 LARGE_INTEGER Interval; 02811 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 02812 NTSTATUS Status; 02813 PLIST_ENTRY ListHead, NextEntry; 02814 PAGED_CODE(); 02815 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); 02816 02817 /* Check the previous mode */ 02818 if (PreviousMode != KernelMode) 02819 { 02820 /* Enter SEH for probing */ 02821 _SEH2_TRY 02822 { 02823 /* Probe the I/O Status Block */ 02824 ProbeForWriteIoStatusBlock(IoStatusBlock); 02825 } 02826 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02827 { 02828 /* Return the exception code */ 02829 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 02830 } 02831 _SEH2_END; 02832 } 02833 02834 /* Reference the file object */ 02835 Status = ObReferenceObjectByHandle(FileHandle, 02836 0, 02837 IoFileObjectType, 02838 PreviousMode, 02839 (PVOID*)&FileObject, 02840 NULL); 02841 if (!NT_SUCCESS(Status)) return Status; 02842 02843 /* IRP cancellations are synchronized at APC_LEVEL. */ 02844 KeRaiseIrql(APC_LEVEL, &OldIrql); 02845 02846 /* Get the current thread */ 02847 Thread = PsGetCurrentThread(); 02848 02849 /* Update the operation counts */ 02850 IopUpdateOperationCount(IopOtherTransfer); 02851 02852 /* Loop the list */ 02853 ListHead = &Thread->IrpList; 02854 NextEntry = ListHead->Flink; 02855 while (ListHead != NextEntry) 02856 { 02857 /* Get the IRP and check if the File Object matches */ 02858 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 02859 if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 02860 { 02861 /* Cancel this IRP and keep looping */ 02862 IoCancelIrp(Irp); 02863 OurIrpsInList = TRUE; 02864 } 02865 02866 /* Go to the next entry */ 02867 NextEntry = NextEntry->Flink; 02868 } 02869 02870 /* Lower the IRQL */ 02871 KeLowerIrql(OldIrql); 02872 02873 /* Check if we had found an IRP */ 02874 if (OurIrpsInList) 02875 { 02876 /* Setup a 10ms wait */ 02877 Interval.QuadPart = -100000; 02878 02879 /* Start looping */ 02880 while (OurIrpsInList) 02881 { 02882 /* Do the wait */ 02883 KeDelayExecutionThread(KernelMode, FALSE, &Interval); 02884 OurIrpsInList = FALSE; 02885 02886 /* Raise IRQL */ 02887 KeRaiseIrql(APC_LEVEL, &OldIrql); 02888 02889 /* Now loop the list again */ 02890 NextEntry = ListHead->Flink; 02891 while (NextEntry != ListHead) 02892 { 02893 /* Get the IRP and check if the File Object matches */ 02894 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry); 02895 if (Irp->Tail.Overlay.OriginalFileObject == FileObject) 02896 { 02897 /* Keep looping */ 02898 OurIrpsInList = TRUE; 02899 break; 02900 } 02901 02902 /* Go to the next entry */ 02903 NextEntry = NextEntry->Flink; 02904 } 02905 02906 /* Lower the IRQL */ 02907 KeLowerIrql(OldIrql); 02908 } 02909 } 02910 02911 /* Enter SEH for writing back the I/O Status */ 02912 _SEH2_TRY 02913 { 02914 /* Write success */ 02915 IoStatusBlock->Status = STATUS_SUCCESS; 02916 IoStatusBlock->Information = 0; 02917 } 02918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02919 { 02920 /* Ignore exception */ 02921 } 02922 _SEH2_END; 02923 02924 /* Dereference the file object and return success */ 02925 ObDereferenceObject(FileObject); 02926 return STATUS_SUCCESS; 02927 } 02928 02929 /* 02930 * @implemented 02931 */ 02932 NTSTATUS 02933 NTAPI 02934 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes) 02935 { 02936 NTSTATUS Status; 02937 DUMMY_FILE_OBJECT DummyFileObject; 02938 HANDLE Handle; 02939 KPROCESSOR_MODE AccessMode = KeGetPreviousMode(); 02940 OPEN_PACKET OpenPacket; 02941 PAGED_CODE(); 02942 IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName); 02943 02944 /* Setup the Open Packet */ 02945 RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET)); 02946 OpenPacket.Type = IO_TYPE_OPEN_PACKET; 02947 OpenPacket.Size = sizeof(OPEN_PACKET); 02948 OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE; 02949 OpenPacket.ShareAccess = FILE_SHARE_READ | 02950 FILE_SHARE_WRITE | 02951 FILE_SHARE_DELETE; 02952 OpenPacket.Disposition = FILE_OPEN; 02953 OpenPacket.DeleteOnly = TRUE; 02954 OpenPacket.DummyFileObject = &DummyFileObject; 02955 02956 /* Update the operation counts */ 02957 IopUpdateOperationCount(IopOtherTransfer); 02958 02959 /* 02960 * Attempt opening the file. This will call the I/O Parse Routine for 02961 * the File Object (IopParseDevice) which will use the dummy file obejct 02962 * send the IRP to its device object. Note that we have two statuses 02963 * to worry about: the Object Manager's status (in Status) and the I/O 02964 * status, which is in the Open Packet's Final Status, and determined 02965 * by the Parse Check member. 02966 */ 02967 Status = ObOpenObjectByName(ObjectAttributes, 02968 NULL, 02969 AccessMode, 02970 NULL, 02971 DELETE, 02972 &OpenPacket, 02973 &Handle); 02974 if (OpenPacket.ParseCheck != TRUE) return Status; 02975 02976 /* Retrn the Io status */ 02977 return OpenPacket.FinalStatus; 02978 } 02979 02980 /* EOF */ Generated on Sat May 26 2012 04:16:36 for ReactOS by
1.7.6.1
|