ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

file.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.