xref: /reactos/ntoskrnl/io/iomgr/file.c (revision 6363f782)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS Kernel
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            ntoskrnl/io/iomgr/file.c
5c2c66affSColin Finck  * PURPOSE:         Functions that deal with managing the FILE_OBJECT itself.
6c2c66affSColin Finck  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck  *                  Gunnar Dalsnes
8c2c66affSColin Finck  *                  Eric Kohl
9c2c66affSColin Finck  *                  Filip Navara (navaraf@reactos.org)
10890a2936SPierre Schweitzer  *                  Pierre Schweitzer
11c2c66affSColin Finck  */
12c2c66affSColin Finck 
13c2c66affSColin Finck /* INCLUDES *****************************************************************/
14c2c66affSColin Finck 
15c2c66affSColin Finck #include <ntoskrnl.h>
16c2c66affSColin Finck #define NDEBUG
17c2c66affSColin Finck #include <debug.h>
18c2c66affSColin Finck 
19c2c66affSColin Finck extern ERESOURCE IopSecurityResource;
20c2c66affSColin Finck 
21c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
22c2c66affSColin Finck 
23c2c66affSColin Finck VOID
24c2c66affSColin Finck NTAPI
IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState,IN OUT PULONG CreateOptions,IN KPROCESSOR_MODE PreviousMode,IN ULONG Disposition)25c2c66affSColin Finck IopCheckBackupRestorePrivilege(IN PACCESS_STATE AccessState,
26c2c66affSColin Finck                                IN OUT PULONG CreateOptions,
27c2c66affSColin Finck                                IN KPROCESSOR_MODE PreviousMode,
28c2c66affSColin Finck                                IN ULONG Disposition)
29c2c66affSColin Finck {
30c2c66affSColin Finck     ACCESS_MASK DesiredAccess, ReadAccess, WriteAccess;
31c2c66affSColin Finck     PRIVILEGE_SET Privileges;
32c2c66affSColin Finck     BOOLEAN AccessGranted, HaveBackupPriv = FALSE, CheckRestore = FALSE;
33c2c66affSColin Finck     PAGED_CODE();
34c2c66affSColin Finck 
35c2c66affSColin Finck     /* Don't do anything if privileges were checked already */
36c2c66affSColin Finck     if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) return;
37c2c66affSColin Finck 
38c2c66affSColin Finck     /* Check if the file was actually opened for backup purposes */
39c2c66affSColin Finck     if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT)
40c2c66affSColin Finck     {
41c2c66affSColin Finck         /* Set the check flag since were doing it now */
42c2c66affSColin Finck         AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED;
43c2c66affSColin Finck 
44c2c66affSColin Finck         /* Set the access masks required */
45c2c66affSColin Finck         ReadAccess = READ_CONTROL |
46c2c66affSColin Finck                      ACCESS_SYSTEM_SECURITY |
47c2c66affSColin Finck                      FILE_GENERIC_READ |
48c2c66affSColin Finck                      FILE_TRAVERSE;
49c2c66affSColin Finck         WriteAccess = WRITE_DAC |
50c2c66affSColin Finck                       WRITE_OWNER |
51c2c66affSColin Finck                       ACCESS_SYSTEM_SECURITY |
52c2c66affSColin Finck                       FILE_GENERIC_WRITE |
53c2c66affSColin Finck                       FILE_ADD_FILE |
54c2c66affSColin Finck                       FILE_ADD_SUBDIRECTORY |
55c2c66affSColin Finck                       DELETE;
56c2c66affSColin Finck         DesiredAccess = AccessState->RemainingDesiredAccess;
57c2c66affSColin Finck 
58c2c66affSColin Finck         /* Check if desired access was the maximum */
59c2c66affSColin Finck         if (DesiredAccess & MAXIMUM_ALLOWED)
60c2c66affSColin Finck         {
61c2c66affSColin Finck             /* Then add all the access masks required */
62c2c66affSColin Finck             DesiredAccess |= (ReadAccess | WriteAccess);
63c2c66affSColin Finck         }
64c2c66affSColin Finck 
65c2c66affSColin Finck         /* Check if the file already exists */
66c2c66affSColin Finck         if (Disposition & FILE_OPEN)
67c2c66affSColin Finck         {
68c2c66affSColin Finck             /* Check if desired access has the read mask */
69c2c66affSColin Finck             if (ReadAccess & DesiredAccess)
70c2c66affSColin Finck             {
71c2c66affSColin Finck                 /* Setup the privilege check lookup */
72c2c66affSColin Finck                 Privileges.PrivilegeCount = 1;
73c2c66affSColin Finck                 Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
74c2c66affSColin Finck                 Privileges.Privilege[0].Luid = SeBackupPrivilege;
75c2c66affSColin Finck                 Privileges.Privilege[0].Attributes = 0;
76c2c66affSColin Finck                 AccessGranted = SePrivilegeCheck(&Privileges,
77c2c66affSColin Finck                                                  &AccessState->
78c2c66affSColin Finck                                                  SubjectSecurityContext,
79c2c66affSColin Finck                                                  PreviousMode);
80c2c66affSColin Finck                 if (AccessGranted)
81c2c66affSColin Finck                 {
82c2c66affSColin Finck                     /* Remember that backup was allowed */
83c2c66affSColin Finck                     HaveBackupPriv = TRUE;
84c2c66affSColin Finck 
85c2c66affSColin Finck                     /* Append the privileges and update the access state */
86c2c66affSColin Finck                     SeAppendPrivileges(AccessState, &Privileges);
87c2c66affSColin Finck                     AccessState->PreviouslyGrantedAccess |= (DesiredAccess & ReadAccess);
88c2c66affSColin Finck                     AccessState->RemainingDesiredAccess &= ~ReadAccess;
89c2c66affSColin Finck                     DesiredAccess &= ~ReadAccess;
90c2c66affSColin Finck 
91c2c66affSColin Finck                     /* Set backup privilege for the token */
92c2c66affSColin Finck                     AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE;
93c2c66affSColin Finck                 }
94c2c66affSColin Finck             }
95c2c66affSColin Finck         }
96c2c66affSColin Finck         else
97c2c66affSColin Finck         {
98c2c66affSColin Finck             /* Caller is creating the file, check restore privileges later */
99c2c66affSColin Finck             CheckRestore = TRUE;
100c2c66affSColin Finck         }
101c2c66affSColin Finck 
102c2c66affSColin Finck         /* Check if caller wants write access or if it's creating a file */
103c2c66affSColin Finck         if ((WriteAccess & DesiredAccess) || (CheckRestore))
104c2c66affSColin Finck         {
105c2c66affSColin Finck             /* Setup the privilege lookup and do it */
106c2c66affSColin Finck             Privileges.PrivilegeCount = 1;
107c2c66affSColin Finck             Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
108c2c66affSColin Finck             Privileges.Privilege[0].Luid = SeRestorePrivilege;
109c2c66affSColin Finck             Privileges.Privilege[0].Attributes = 0;
110c2c66affSColin Finck             AccessGranted = SePrivilegeCheck(&Privileges,
111c2c66affSColin Finck                                              &AccessState->SubjectSecurityContext,
112c2c66affSColin Finck                                              PreviousMode);
113c2c66affSColin Finck             if (AccessGranted)
114c2c66affSColin Finck             {
115c2c66affSColin Finck                 /* Remember that privilege was given */
116c2c66affSColin Finck                 HaveBackupPriv = TRUE;
117c2c66affSColin Finck 
118c2c66affSColin Finck                 /* Append the privileges and update the access state */
119c2c66affSColin Finck                 SeAppendPrivileges(AccessState, &Privileges);
120c2c66affSColin Finck                 AccessState->PreviouslyGrantedAccess |= (DesiredAccess & WriteAccess);
121c2c66affSColin Finck                 AccessState->RemainingDesiredAccess &= ~WriteAccess;
122c2c66affSColin Finck 
123c2c66affSColin Finck                 /* Set restore privilege for the token */
124c2c66affSColin Finck                 AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE;
125c2c66affSColin Finck             }
126c2c66affSColin Finck         }
127c2c66affSColin Finck 
128c2c66affSColin Finck         /* If we don't have the privilege, remove the option */
129c2c66affSColin Finck         if (!HaveBackupPriv) *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
130c2c66affSColin Finck     }
131c2c66affSColin Finck }
132c2c66affSColin Finck 
133c2c66affSColin Finck NTSTATUS
134c2c66affSColin Finck NTAPI
IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket,IN PDEVICE_OBJECT DeviceObject)135c2c66affSColin Finck IopCheckDeviceAndDriver(IN POPEN_PACKET OpenPacket,
136c2c66affSColin Finck                         IN PDEVICE_OBJECT DeviceObject)
137c2c66affSColin Finck {
138c2c66affSColin Finck     /* Make sure the object is valid */
139c2c66affSColin Finck     if ((IoGetDevObjExtension(DeviceObject)->ExtensionFlags &
140c2c66affSColin Finck         (DOE_UNLOAD_PENDING |
141c2c66affSColin Finck          DOE_DELETE_PENDING |
142c2c66affSColin Finck          DOE_REMOVE_PENDING |
143c2c66affSColin Finck          DOE_REMOVE_PROCESSED)) ||
144c2c66affSColin Finck         (DeviceObject->Flags & DO_DEVICE_INITIALIZING))
145c2c66affSColin Finck     {
146c2c66affSColin Finck         /* It's unloading or initializing, so fail */
147c2c66affSColin Finck         DPRINT1("You are seeing this because the following ROS driver: %wZ\n"
148c2c66affSColin Finck                 " sucks. Please fix it's AddDevice Routine\n",
149c2c66affSColin Finck                 &DeviceObject->DriverObject->DriverName);
150c2c66affSColin Finck         return STATUS_NO_SUCH_DEVICE;
151c2c66affSColin Finck     }
152c2c66affSColin Finck     else if ((DeviceObject->Flags & DO_EXCLUSIVE) &&
153c2c66affSColin Finck              (DeviceObject->ReferenceCount) &&
154c2c66affSColin Finck              !(OpenPacket->RelatedFileObject) &&
155c2c66affSColin Finck              !(OpenPacket->Options & IO_ATTACH_DEVICE))
156c2c66affSColin Finck     {
157c2c66affSColin Finck         return STATUS_ACCESS_DENIED;
158c2c66affSColin Finck     }
159c2c66affSColin Finck 
160c2c66affSColin Finck     else
161c2c66affSColin Finck     {
162c2c66affSColin Finck         /* Increase reference count */
163c2c66affSColin Finck         InterlockedIncrement(&DeviceObject->ReferenceCount);
164c2c66affSColin Finck         return STATUS_SUCCESS;
165c2c66affSColin Finck     }
166c2c66affSColin Finck }
167c2c66affSColin Finck 
168c2c66affSColin Finck VOID
169c2c66affSColin Finck NTAPI
IopDoNameTransmogrify(IN PIRP Irp,IN PFILE_OBJECT FileObject,IN PREPARSE_DATA_BUFFER DataBuffer)170c2c66affSColin Finck IopDoNameTransmogrify(IN PIRP Irp,
171c2c66affSColin Finck                       IN PFILE_OBJECT FileObject,
172c2c66affSColin Finck                       IN PREPARSE_DATA_BUFFER DataBuffer)
173c2c66affSColin Finck {
174c2c66affSColin Finck     PWSTR Buffer;
175c2c66affSColin Finck     USHORT Length;
176c2c66affSColin Finck     USHORT RequiredLength;
177c2c66affSColin Finck     PWSTR NewBuffer;
178c2c66affSColin Finck 
179c2c66affSColin Finck     PAGED_CODE();
180c2c66affSColin Finck 
181c2c66affSColin Finck     ASSERT(Irp->IoStatus.Status == STATUS_REPARSE);
182c2c66affSColin Finck     ASSERT(Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT);
183c2c66affSColin Finck     ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
184c2c66affSColin Finck     ASSERT(DataBuffer != NULL);
185c2c66affSColin Finck     ASSERT(DataBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
186c2c66affSColin Finck     ASSERT(DataBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
187c2c66affSColin Finck     ASSERT(DataBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
188c2c66affSColin Finck 
189c2c66affSColin Finck     /* First of all, validate data */
190c2c66affSColin Finck     if (DataBuffer->ReparseDataLength < REPARSE_DATA_BUFFER_HEADER_SIZE ||
191c2c66affSColin Finck         (DataBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
192c2c66affSColin Finck          DataBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength +
193c2c66affSColin Finck          FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[0])) > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
194c2c66affSColin Finck     {
195c2c66affSColin Finck         Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
196c2c66affSColin Finck     }
197c2c66affSColin Finck 
198c2c66affSColin Finck     /* Everything went right */
199c2c66affSColin Finck     if (NT_SUCCESS(Irp->IoStatus.Status))
200c2c66affSColin Finck     {
201c2c66affSColin Finck         /* Compute buffer & length */
202c2c66affSColin Finck         Buffer = (PWSTR)((ULONG_PTR)DataBuffer->MountPointReparseBuffer.PathBuffer +
203c2c66affSColin Finck                                     DataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
204c2c66affSColin Finck         Length = DataBuffer->MountPointReparseBuffer.SubstituteNameLength;
205c2c66affSColin Finck 
206c2c66affSColin Finck         /* Check we don't overflow */
207c2c66affSColin Finck         if (((ULONG)MAXUSHORT - DataBuffer->Reserved) <= (Length + sizeof(UNICODE_NULL)))
208c2c66affSColin Finck         {
209c2c66affSColin Finck             Irp->IoStatus.Status = STATUS_IO_REPARSE_DATA_INVALID;
210c2c66affSColin Finck         }
211c2c66affSColin Finck         else
212c2c66affSColin Finck         {
213d3a97e22SHermès Bélusca-Maïto             /* Compute how much memory we'll need */
214c2c66affSColin Finck             RequiredLength = DataBuffer->Reserved + Length + sizeof(UNICODE_NULL);
215c2c66affSColin Finck 
216c2c66affSColin Finck             /* Check if FileObject can already hold what we need */
217c2c66affSColin Finck             if (FileObject->FileName.MaximumLength >= RequiredLength)
218c2c66affSColin Finck             {
219c2c66affSColin Finck                 NewBuffer = FileObject->FileName.Buffer;
220c2c66affSColin Finck             }
221c2c66affSColin Finck             else
222c2c66affSColin Finck             {
223c2c66affSColin Finck                 /* Allocate otherwise */
224c2c66affSColin Finck                 NewBuffer = ExAllocatePoolWithTag(PagedPool, RequiredLength, TAG_IO_NAME);
225c2c66affSColin Finck                 if (NewBuffer == NULL)
226c2c66affSColin Finck                 {
227c2c66affSColin Finck                     Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
228c2c66affSColin Finck                 }
229c2c66affSColin Finck             }
230c2c66affSColin Finck         }
231c2c66affSColin Finck     }
232c2c66affSColin Finck 
233c2c66affSColin Finck     /* Everything went right */
234c2c66affSColin Finck     if (NT_SUCCESS(Irp->IoStatus.Status))
235c2c66affSColin Finck     {
236d3a97e22SHermès Bélusca-Maïto         /* Copy the reserved data */
237c2c66affSColin Finck         if (DataBuffer->Reserved)
238c2c66affSColin Finck         {
239c2c66affSColin Finck             RtlMoveMemory((PWSTR)((ULONG_PTR)NewBuffer + Length),
240c2c66affSColin Finck                           (PWSTR)((ULONG_PTR)FileObject->FileName.Buffer + FileObject->FileName.Length - DataBuffer->Reserved),
241c2c66affSColin Finck                           DataBuffer->Reserved);
242c2c66affSColin Finck         }
243c2c66affSColin Finck 
244d3a97e22SHermès Bélusca-Maïto         /* Then the buffer */
245c2c66affSColin Finck         if (Length)
246c2c66affSColin Finck         {
247c2c66affSColin Finck             RtlCopyMemory(NewBuffer, Buffer, Length);
248c2c66affSColin Finck         }
249c2c66affSColin Finck 
250c2c66affSColin Finck         /* And finally replace buffer if new one was allocated */
251c2c66affSColin Finck         FileObject->FileName.Length = RequiredLength - sizeof(UNICODE_NULL);
252c2c66affSColin Finck         if (NewBuffer != FileObject->FileName.Buffer)
253c2c66affSColin Finck         {
254c2c66affSColin Finck             if (FileObject->FileName.Buffer)
255c2c66affSColin Finck             {
256fefb982dSHermès Bélusca-Maïto                 /*
257fefb982dSHermès Bélusca-Maïto                  * Don't use TAG_IO_NAME since the FileObject's FileName
258fefb982dSHermès Bélusca-Maïto                  * may have been re-allocated using a different tag
259fefb982dSHermès Bélusca-Maïto                  * by a filesystem.
260fefb982dSHermès Bélusca-Maïto                  */
261fefb982dSHermès Bélusca-Maïto                 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
262c2c66affSColin Finck             }
263c2c66affSColin Finck 
264c2c66affSColin Finck             FileObject->FileName.Buffer = NewBuffer;
265c2c66affSColin Finck             FileObject->FileName.MaximumLength = RequiredLength;
266c2c66affSColin Finck             FileObject->FileName.Buffer[RequiredLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
267c2c66affSColin Finck         }
268c2c66affSColin Finck     }
269c2c66affSColin Finck 
270c2c66affSColin Finck     /* We don't need them anymore - it was allocated by the driver */
271c2c66affSColin Finck     ExFreePool(DataBuffer);
272c2c66affSColin Finck }
273c2c66affSColin Finck 
274c2c66affSColin Finck NTSTATUS
IopCheckTopDeviceHint(IN OUT PDEVICE_OBJECT * DeviceObject,IN POPEN_PACKET OpenPacket,BOOLEAN DirectOpen)275779d87b4SPierre Schweitzer IopCheckTopDeviceHint(IN OUT PDEVICE_OBJECT * DeviceObject,
276779d87b4SPierre Schweitzer                       IN POPEN_PACKET OpenPacket,
277779d87b4SPierre Schweitzer                       BOOLEAN DirectOpen)
278779d87b4SPierre Schweitzer {
279779d87b4SPierre Schweitzer     PDEVICE_OBJECT LocalDevice;
280779d87b4SPierre Schweitzer     DEVICE_TYPE DeviceType;
281779d87b4SPierre Schweitzer 
282779d87b4SPierre Schweitzer     LocalDevice = *DeviceObject;
283779d87b4SPierre Schweitzer 
284779d87b4SPierre Schweitzer     /* Direct open is not allowed */
285779d87b4SPierre Schweitzer     if (DirectOpen)
286779d87b4SPierre Schweitzer     {
287779d87b4SPierre Schweitzer         return STATUS_INVALID_PARAMETER;
288779d87b4SPierre Schweitzer     }
289779d87b4SPierre Schweitzer 
290779d87b4SPierre Schweitzer     /* Validate we have a file system device */
291779d87b4SPierre Schweitzer     DeviceType = LocalDevice->DeviceType;
292779d87b4SPierre Schweitzer     if (DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
293779d87b4SPierre Schweitzer         DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
294779d87b4SPierre Schweitzer         DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM &&
295779d87b4SPierre Schweitzer         DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM &&
296779d87b4SPierre Schweitzer         DeviceType != FILE_DEVICE_DFS_FILE_SYSTEM)
297779d87b4SPierre Schweitzer     {
298779d87b4SPierre Schweitzer         return STATUS_INVALID_PARAMETER;
299779d87b4SPierre Schweitzer     }
300779d87b4SPierre Schweitzer 
301779d87b4SPierre Schweitzer     /* Verify the hint and if it's OK, return it */
302779d87b4SPierre Schweitzer     if (IopVerifyDeviceObjectOnStack(LocalDevice, OpenPacket->TopDeviceObjectHint))
303779d87b4SPierre Schweitzer     {
304779d87b4SPierre Schweitzer         *DeviceObject = OpenPacket->TopDeviceObjectHint;
305779d87b4SPierre Schweitzer         return STATUS_SUCCESS;
306779d87b4SPierre Schweitzer     }
307779d87b4SPierre Schweitzer 
308779d87b4SPierre Schweitzer     /* Failure case here */
309779d87b4SPierre Schweitzer     /* If we thought was had come through a mount point,
310779d87b4SPierre Schweitzer      * actually update we didn't and return the error
311779d87b4SPierre Schweitzer      */
312779d87b4SPierre Schweitzer     if (OpenPacket->TraversedMountPoint)
313779d87b4SPierre Schweitzer     {
314779d87b4SPierre Schweitzer         OpenPacket->TraversedMountPoint = FALSE;
315779d87b4SPierre Schweitzer         return STATUS_MOUNT_POINT_NOT_RESOLVED;
316779d87b4SPierre Schweitzer     }
317779d87b4SPierre Schweitzer 
318779d87b4SPierre Schweitzer     /* Otherwise, just return the fact the hint is invalid */
319779d87b4SPierre Schweitzer     return STATUS_INVALID_DEVICE_OBJECT_PARAMETER;
320779d87b4SPierre Schweitzer }
321779d87b4SPierre Schweitzer 
322779d87b4SPierre Schweitzer NTSTATUS
323c2c66affSColin Finck NTAPI
IopParseDevice(IN PVOID ParseObject,IN PVOID ObjectType,IN OUT PACCESS_STATE AccessState,IN KPROCESSOR_MODE AccessMode,IN ULONG Attributes,IN OUT PUNICODE_STRING CompleteName,IN OUT PUNICODE_STRING RemainingName,IN OUT PVOID Context,IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,OUT PVOID * Object)324c2c66affSColin Finck IopParseDevice(IN PVOID ParseObject,
325c2c66affSColin Finck                IN PVOID ObjectType,
326c2c66affSColin Finck                IN OUT PACCESS_STATE AccessState,
327c2c66affSColin Finck                IN KPROCESSOR_MODE AccessMode,
328c2c66affSColin Finck                IN ULONG Attributes,
329c2c66affSColin Finck                IN OUT PUNICODE_STRING CompleteName,
330c2c66affSColin Finck                IN OUT PUNICODE_STRING RemainingName,
331c2c66affSColin Finck                IN OUT PVOID Context,
332c2c66affSColin Finck                IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
333c2c66affSColin Finck                OUT PVOID *Object)
334c2c66affSColin Finck {
335c2c66affSColin Finck     POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;
336c2c66affSColin Finck     PDEVICE_OBJECT OriginalDeviceObject = (PDEVICE_OBJECT)ParseObject;
337c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject, OwnerDevice;
338c2c66affSColin Finck     NTSTATUS Status;
339c2c66affSColin Finck     PFILE_OBJECT FileObject;
340c2c66affSColin Finck     PVPB Vpb = NULL;
341c2c66affSColin Finck     PIRP Irp;
342ca9fd861STimo Kreuzer     PIO_STACK_LOCATION StackLoc;
343c2c66affSColin Finck     IO_SECURITY_CONTEXT SecurityContext;
344c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
345c2c66affSColin Finck     BOOLEAN DirectOpen = FALSE, OpenCancelled, UseDummyFile;
346c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
347c2c66affSColin Finck     KIRQL OldIrql;
348c2c66affSColin Finck     PDUMMY_FILE_OBJECT LocalFileObject;
349c2c66affSColin Finck     PFILE_BASIC_INFORMATION FileBasicInfo;
350c2c66affSColin Finck     ULONG ReturnLength;
351c2c66affSColin Finck     KPROCESSOR_MODE CheckMode;
352c2c66affSColin Finck     BOOLEAN VolumeOpen = FALSE;
353c2c66affSColin Finck     ACCESS_MASK DesiredAccess, GrantedAccess;
354c2c66affSColin Finck     BOOLEAN AccessGranted, LockHeld = FALSE;
355c2c66affSColin Finck     PPRIVILEGE_SET Privileges = NULL;
356c2c66affSColin Finck     UNICODE_STRING FileString;
357c2c66affSColin Finck     USHORT Attempt;
358c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "ParseObject: %p. RemainingName: %wZ\n",
359c2c66affSColin Finck             ParseObject, RemainingName);
360c2c66affSColin Finck 
361c2c66affSColin Finck     for (Attempt = 0; Attempt < IOP_MAX_REPARSE_TRAVERSAL; ++Attempt)
362c2c66affSColin Finck     {
363c2c66affSColin Finck         /* Assume failure */
364c2c66affSColin Finck         *Object = NULL;
365c2c66affSColin Finck 
366c2c66affSColin Finck         /* Validate the open packet */
367c2c66affSColin Finck         if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
368c2c66affSColin Finck 
369c2c66affSColin Finck         /* Valide reparse point in case we traversed a mountpoint */
370c2c66affSColin Finck         if (OpenPacket->TraversedMountPoint)
371c2c66affSColin Finck         {
372c2c66affSColin Finck             /* This is a reparse point we understand */
373c2c66affSColin Finck             ASSERT(OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT);
374c2c66affSColin Finck 
375c2c66affSColin Finck             /* Make sure we're dealing with correct DO */
376c2c66affSColin Finck             if (OriginalDeviceObject->DeviceType != FILE_DEVICE_DISK &&
377c2c66affSColin Finck                 OriginalDeviceObject->DeviceType != FILE_DEVICE_CD_ROM &&
378c2c66affSColin Finck                 OriginalDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK &&
379c2c66affSColin Finck                 OriginalDeviceObject->DeviceType != FILE_DEVICE_TAPE)
380c2c66affSColin Finck             {
381c2c66affSColin Finck                 OpenPacket->FinalStatus = STATUS_IO_REPARSE_DATA_INVALID;
382c2c66affSColin Finck                 return STATUS_IO_REPARSE_DATA_INVALID;
383c2c66affSColin Finck             }
384c2c66affSColin Finck         }
385c2c66affSColin Finck 
386c2c66affSColin Finck         /* Check if we have a related file object */
387c2c66affSColin Finck         if (OpenPacket->RelatedFileObject)
388c2c66affSColin Finck         {
389c2c66affSColin Finck             /* Use the related file object's device object */
390c2c66affSColin Finck             OriginalDeviceObject = OpenPacket->RelatedFileObject->DeviceObject;
391c2c66affSColin Finck         }
392c2c66affSColin Finck 
393c2c66affSColin Finck         /* Validate device status */
394c2c66affSColin Finck         Status = IopCheckDeviceAndDriver(OpenPacket, OriginalDeviceObject);
395c2c66affSColin Finck         if (!NT_SUCCESS(Status))
396c2c66affSColin Finck         {
397c2c66affSColin Finck             /* We failed, return status */
398c2c66affSColin Finck             OpenPacket->FinalStatus = Status;
399c2c66affSColin Finck             return Status;
400c2c66affSColin Finck         }
401c2c66affSColin Finck 
402c2c66affSColin Finck         /* Map the generic mask and set the new mapping in the access state */
403c2c66affSColin Finck         RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
404c2c66affSColin Finck                           &IoFileObjectType->TypeInfo.GenericMapping);
405c2c66affSColin Finck         RtlMapGenericMask(&AccessState->OriginalDesiredAccess,
406c2c66affSColin Finck                           &IoFileObjectType->TypeInfo.GenericMapping);
407c2c66affSColin Finck         SeSetAccessStateGenericMapping(AccessState,
408c2c66affSColin Finck                                        &IoFileObjectType->TypeInfo.GenericMapping);
409c2c66affSColin Finck         DesiredAccess = AccessState->RemainingDesiredAccess;
410c2c66affSColin Finck 
411c2c66affSColin Finck         /* Check what kind of access checks to do */
412c2c66affSColin Finck         if ((AccessMode != KernelMode) ||
413c2c66affSColin Finck             (OpenPacket->Options & IO_FORCE_ACCESS_CHECK))
414c2c66affSColin Finck         {
415c2c66affSColin Finck             /* Call is from user-mode or kernel is forcing checks */
416c2c66affSColin Finck             CheckMode = UserMode;
417c2c66affSColin Finck         }
418c2c66affSColin Finck         else
419c2c66affSColin Finck         {
420c2c66affSColin Finck             /* Call is from the kernel */
421c2c66affSColin Finck             CheckMode = KernelMode;
422c2c66affSColin Finck         }
423c2c66affSColin Finck 
424c2c66affSColin Finck         /* Check privilege for backup or restore operation */
425c2c66affSColin Finck         IopCheckBackupRestorePrivilege(AccessState,
426c2c66affSColin Finck                                        &OpenPacket->CreateOptions,
427c2c66affSColin Finck                                        CheckMode,
428c2c66affSColin Finck                                        OpenPacket->Disposition);
429c2c66affSColin Finck 
430c2c66affSColin Finck         /* Check if we are re-parsing */
431c2c66affSColin Finck         if (((OpenPacket->Override) && !(RemainingName->Length)) ||
432c2c66affSColin Finck             (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED))
433c2c66affSColin Finck         {
434c2c66affSColin Finck             /* Get granted access from the last call */
435c2c66affSColin Finck             DesiredAccess |= AccessState->PreviouslyGrantedAccess;
436c2c66affSColin Finck         }
437c2c66affSColin Finck 
438c2c66affSColin Finck         /* Check if this is a volume open */
439c2c66affSColin Finck         if ((OpenPacket->RelatedFileObject) &&
440c2c66affSColin Finck             (OpenPacket->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
441c2c66affSColin Finck             !(RemainingName->Length))
442c2c66affSColin Finck         {
443c2c66affSColin Finck             /* It is */
444c2c66affSColin Finck             VolumeOpen = TRUE;
445c2c66affSColin Finck         }
446c2c66affSColin Finck 
447c2c66affSColin Finck         /* Now check if we need access checks */
448c2c66affSColin Finck         if (((AccessMode != KernelMode) ||
449c2c66affSColin Finck              (OpenPacket->Options & IO_FORCE_ACCESS_CHECK)) &&
450c2c66affSColin Finck             (!(OpenPacket->RelatedFileObject) || (VolumeOpen)) &&
451c2c66affSColin Finck             !(OpenPacket->Override))
452c2c66affSColin Finck         {
453c2c66affSColin Finck             KeEnterCriticalRegion();
454c2c66affSColin Finck             ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
455c2c66affSColin Finck 
456c2c66affSColin Finck             /* Check if a device object is being parsed  */
457c2c66affSColin Finck             if (!RemainingName->Length)
458c2c66affSColin Finck             {
459c2c66affSColin Finck                 /* Lock the subject context */
460c2c66affSColin Finck                 SeLockSubjectContext(&AccessState->SubjectSecurityContext);
461c2c66affSColin Finck                 LockHeld = TRUE;
462c2c66affSColin Finck 
463c2c66affSColin Finck                 /* Do access check */
464c2c66affSColin Finck                 AccessGranted = SeAccessCheck(OriginalDeviceObject->
465c2c66affSColin Finck                                               SecurityDescriptor,
466c2c66affSColin Finck                                               &AccessState->SubjectSecurityContext,
467c2c66affSColin Finck                                               LockHeld,
468c2c66affSColin Finck                                               DesiredAccess,
469c2c66affSColin Finck                                               0,
470c2c66affSColin Finck                                               &Privileges,
471c2c66affSColin Finck                                               &IoFileObjectType->
472c2c66affSColin Finck                                               TypeInfo.GenericMapping,
473c2c66affSColin Finck                                               UserMode,
474c2c66affSColin Finck                                               &GrantedAccess,
475c2c66affSColin Finck                                               &Status);
476c2c66affSColin Finck                 if (Privileges)
477c2c66affSColin Finck                 {
478c2c66affSColin Finck                     /* Append and free the privileges */
479c2c66affSColin Finck                     SeAppendPrivileges(AccessState, Privileges);
480c2c66affSColin Finck                     SeFreePrivileges(Privileges);
481c2c66affSColin Finck                 }
482c2c66affSColin Finck 
483c2c66affSColin Finck                 /* Check if we got access */
484c2c66affSColin Finck                 if (AccessGranted)
485c2c66affSColin Finck                 {
486c2c66affSColin Finck                     /* Update access state */
487c2c66affSColin Finck                     AccessState->PreviouslyGrantedAccess |= GrantedAccess;
488890a2936SPierre Schweitzer                     AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
489c2c66affSColin Finck                                                              MAXIMUM_ALLOWED);
490c2c66affSColin Finck                     OpenPacket->Override= TRUE;
491c2c66affSColin Finck                 }
492c2c66affSColin Finck 
493c2c66affSColin Finck                 FileString.Length = 8;
494c2c66affSColin Finck                 FileString.MaximumLength = 8;
495c2c66affSColin Finck                 FileString.Buffer = L"File";
496c2c66affSColin Finck 
497c2c66affSColin Finck                 /* Do Audit/Alarm for open operation */
498c2c66affSColin Finck                 SeOpenObjectAuditAlarm(&FileString,
499c2c66affSColin Finck                                        OriginalDeviceObject,
500c2c66affSColin Finck                                        CompleteName,
501c2c66affSColin Finck                                        OriginalDeviceObject->SecurityDescriptor,
502c2c66affSColin Finck                                        AccessState,
503c2c66affSColin Finck                                        FALSE,
504c2c66affSColin Finck                                        AccessGranted,
505c2c66affSColin Finck                                        UserMode,
506c2c66affSColin Finck                                        &AccessState->GenerateOnClose);
507c2c66affSColin Finck             }
508c2c66affSColin Finck             else
509c2c66affSColin Finck             {
510c2c66affSColin Finck                 /* Check if we need to do traverse validation */
511c2c66affSColin Finck                 if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ||
512c2c66affSColin Finck                     ((OriginalDeviceObject->DeviceType == FILE_DEVICE_DISK) ||
513c2c66affSColin Finck                      (OriginalDeviceObject->DeviceType == FILE_DEVICE_CD_ROM)))
514c2c66affSColin Finck                 {
515c2c66affSColin Finck                     /* Check if this is a restricted token */
516c2c66affSColin Finck                     if (!(AccessState->Flags & TOKEN_IS_RESTRICTED))
517c2c66affSColin Finck                     {
518c2c66affSColin Finck                         /* Do the FAST traverse check */
519c2c66affSColin Finck                         AccessGranted = SeFastTraverseCheck(OriginalDeviceObject->SecurityDescriptor,
520c2c66affSColin Finck                                                             AccessState,
521c2c66affSColin Finck                                                             FILE_TRAVERSE,
522c2c66affSColin Finck                                                             UserMode);
523c2c66affSColin Finck                     }
524c2c66affSColin Finck                     else
525c2c66affSColin Finck                     {
526c2c66affSColin Finck                         /* Fail */
527c2c66affSColin Finck                         AccessGranted = FALSE;
528c2c66affSColin Finck                     }
529c2c66affSColin Finck 
530c2c66affSColin Finck                     /* Check if we failed to get access */
531c2c66affSColin Finck                     if (!AccessGranted)
532c2c66affSColin Finck                     {
533c2c66affSColin Finck                         /* Lock the subject context */
534c2c66affSColin Finck                         SeLockSubjectContext(&AccessState->SubjectSecurityContext);
535c2c66affSColin Finck                         LockHeld = TRUE;
536c2c66affSColin Finck 
537c2c66affSColin Finck                         /* Do access check */
538c2c66affSColin Finck                         AccessGranted = SeAccessCheck(OriginalDeviceObject->
539c2c66affSColin Finck                                                       SecurityDescriptor,
540c2c66affSColin Finck                                                       &AccessState->SubjectSecurityContext,
541c2c66affSColin Finck                                                       LockHeld,
542c2c66affSColin Finck                                                       FILE_TRAVERSE,
543c2c66affSColin Finck                                                       0,
544c2c66affSColin Finck                                                       &Privileges,
545c2c66affSColin Finck                                                       &IoFileObjectType->
546c2c66affSColin Finck                                                       TypeInfo.GenericMapping,
547c2c66affSColin Finck                                                       UserMode,
548c2c66affSColin Finck                                                       &GrantedAccess,
549c2c66affSColin Finck                                                       &Status);
550c2c66affSColin Finck                         if (Privileges)
551c2c66affSColin Finck                         {
552c2c66affSColin Finck                             /* Append and free the privileges */
553c2c66affSColin Finck                             SeAppendPrivileges(AccessState, Privileges);
554c2c66affSColin Finck                             SeFreePrivileges(Privileges);
555c2c66affSColin Finck                         }
556c2c66affSColin Finck                     }
557c2c66affSColin Finck 
558c2c66affSColin Finck                     /* FIXME: Do Audit/Alarm for traverse check */
559c2c66affSColin Finck                 }
560c2c66affSColin Finck                 else
561c2c66affSColin Finck                 {
562c2c66affSColin Finck                     /* Access automatically granted */
563c2c66affSColin Finck                     AccessGranted = TRUE;
564c2c66affSColin Finck                 }
565c2c66affSColin Finck             }
566c2c66affSColin Finck 
567c2c66affSColin Finck             ExReleaseResourceLite(&IopSecurityResource);
568c2c66affSColin Finck             KeLeaveCriticalRegion();
569c2c66affSColin Finck 
570c2c66affSColin Finck             /* Check if we hold the lock */
571c2c66affSColin Finck             if (LockHeld)
572c2c66affSColin Finck             {
573c2c66affSColin Finck                 /* Release it */
574c2c66affSColin Finck                 SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
575c2c66affSColin Finck             }
576c2c66affSColin Finck 
577c2c66affSColin Finck             /* Check if access failed */
578c2c66affSColin Finck             if (!AccessGranted)
579c2c66affSColin Finck             {
580c2c66affSColin Finck                 /* Dereference the device and fail */
581c2c66affSColin Finck                 DPRINT1("Traverse access failed!\n");
582c2c66affSColin Finck                 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
583c2c66affSColin Finck                 return STATUS_ACCESS_DENIED;
584c2c66affSColin Finck             }
585c2c66affSColin Finck         }
586c2c66affSColin Finck 
587c2c66affSColin Finck         /* Check if we can simply use a dummy file */
588c2c66affSColin Finck         UseDummyFile = ((OpenPacket->QueryOnly) || (OpenPacket->DeleteOnly));
589c2c66affSColin Finck 
590c2c66affSColin Finck         /* Check if this is a direct open */
591c2c66affSColin Finck         if (!(RemainingName->Length) &&
592c2c66affSColin Finck             !(OpenPacket->RelatedFileObject) &&
593c2c66affSColin Finck             ((DesiredAccess & ~(SYNCHRONIZE |
594c2c66affSColin Finck                                 FILE_READ_ATTRIBUTES |
595c2c66affSColin Finck                                 READ_CONTROL |
596c2c66affSColin Finck                                 ACCESS_SYSTEM_SECURITY |
597c2c66affSColin Finck                                 WRITE_OWNER |
598c2c66affSColin Finck                                 WRITE_DAC)) == 0) &&
599c2c66affSColin Finck             !(UseDummyFile))
600c2c66affSColin Finck         {
601c2c66affSColin Finck             /* Remember this for later */
602c2c66affSColin Finck             DirectOpen = TRUE;
603c2c66affSColin Finck         }
604c2c66affSColin Finck 
605c2c66affSColin Finck         /* Check if we have a related FO that wasn't a direct open */
606c2c66affSColin Finck         if ((OpenPacket->RelatedFileObject) &&
607c2c66affSColin Finck             !(OpenPacket->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))
608c2c66affSColin Finck         {
609c2c66affSColin Finck             /* The device object is the one we were given */
610c2c66affSColin Finck             DeviceObject = ParseObject;
611c2c66affSColin Finck 
612c2c66affSColin Finck             /* Check if the related FO had a VPB */
613c2c66affSColin Finck             if (OpenPacket->RelatedFileObject->Vpb)
614c2c66affSColin Finck             {
615c2c66affSColin Finck                 /* Yes, remember it */
616c2c66affSColin Finck                 Vpb = OpenPacket->RelatedFileObject->Vpb;
617c2c66affSColin Finck 
618c2c66affSColin Finck                 /* Reference it */
619c2c66affSColin Finck                 InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
620c2c66affSColin Finck 
621c2c66affSColin Finck                 /* Check if we were given a specific top level device to use */
622c2c66affSColin Finck                 if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
623c2c66affSColin Finck                 {
624c2c66affSColin Finck                     DeviceObject = Vpb->DeviceObject;
625c2c66affSColin Finck                 }
626c2c66affSColin Finck             }
627c2c66affSColin Finck         }
628c2c66affSColin Finck         else
629c2c66affSColin Finck         {
630c2c66affSColin Finck             /* Check if it has a VPB */
631c2c66affSColin Finck             if ((OriginalDeviceObject->Vpb) && !(DirectOpen))
632c2c66affSColin Finck             {
633c2c66affSColin Finck                 /* Check if the VPB is mounted, and mount it */
634c2c66affSColin Finck                 Vpb = IopCheckVpbMounted(OpenPacket,
635c2c66affSColin Finck                                          OriginalDeviceObject,
636c2c66affSColin Finck                                          RemainingName,
637c2c66affSColin Finck                                          &Status);
638c2c66affSColin Finck                 if (!Vpb) return Status;
639c2c66affSColin Finck 
640c2c66affSColin Finck                 /* Get the VPB's device object */
641c2c66affSColin Finck                 DeviceObject = Vpb->DeviceObject;
642c2c66affSColin Finck             }
643c2c66affSColin Finck             else
644c2c66affSColin Finck             {
645c2c66affSColin Finck                 /* The device object is the one we were given */
646c2c66affSColin Finck                 DeviceObject = OriginalDeviceObject;
647c2c66affSColin Finck             }
648c2c66affSColin Finck 
649c2c66affSColin Finck             /* If we weren't given a specific top level device, look for an attached device */
650c2c66affSColin Finck             if (!(OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT) &&
651c2c66affSColin Finck                 DeviceObject->AttachedDevice)
652c2c66affSColin Finck             {
653c2c66affSColin Finck                 /* Get the attached device */
654c2c66affSColin Finck                 DeviceObject = IoGetAttachedDevice(DeviceObject);
655c2c66affSColin Finck             }
656c2c66affSColin Finck         }
657c2c66affSColin Finck 
6580b713d4fSPierre Schweitzer         /* If we have a top level device hint, verify it */
659c2c66affSColin Finck         if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
660c2c66affSColin Finck         {
6610b713d4fSPierre Schweitzer             Status = IopCheckTopDeviceHint(&DeviceObject, OpenPacket, DirectOpen);
6620b713d4fSPierre Schweitzer             if (!NT_SUCCESS(Status))
6630b713d4fSPierre Schweitzer             {
6640b713d4fSPierre Schweitzer                 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
6650b713d4fSPierre Schweitzer                 if (Vpb) IopDereferenceVpbAndFree(Vpb);
6660b713d4fSPierre Schweitzer                 return Status;
6670b713d4fSPierre Schweitzer             }
668c2c66affSColin Finck         }
669c2c66affSColin Finck 
670c2c66affSColin Finck         /* If we traversed a mount point, reset the information */
671c2c66affSColin Finck         if (OpenPacket->TraversedMountPoint)
672c2c66affSColin Finck         {
673c2c66affSColin Finck             OpenPacket->TraversedMountPoint = FALSE;
674c2c66affSColin Finck         }
675c2c66affSColin Finck 
676c2c66affSColin Finck         /* Check if this is a secure FSD */
677c2c66affSColin Finck         if ((DeviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
678c2c66affSColin Finck             ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
679c2c66affSColin Finck             (!VolumeOpen))
680c2c66affSColin Finck         {
6816d0c07c4SPierre Schweitzer             Privileges = NULL;
6826d0c07c4SPierre Schweitzer             GrantedAccess = 0;
6836d0c07c4SPierre Schweitzer 
6846d0c07c4SPierre Schweitzer             KeEnterCriticalRegion();
6856d0c07c4SPierre Schweitzer             ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
6866d0c07c4SPierre Schweitzer 
6876d0c07c4SPierre Schweitzer             /* Lock the subject context */
6886d0c07c4SPierre Schweitzer             SeLockSubjectContext(&AccessState->SubjectSecurityContext);
6896d0c07c4SPierre Schweitzer 
6906d0c07c4SPierre Schweitzer             /* Do access check */
6916d0c07c4SPierre Schweitzer             AccessGranted = SeAccessCheck(OriginalDeviceObject->SecurityDescriptor,
6926d0c07c4SPierre Schweitzer                                           &AccessState->SubjectSecurityContext,
6936d0c07c4SPierre Schweitzer                                           TRUE,
6946d0c07c4SPierre Schweitzer                                           DesiredAccess,
6956d0c07c4SPierre Schweitzer                                           0,
6966d0c07c4SPierre Schweitzer                                           &Privileges,
6976d0c07c4SPierre Schweitzer                                           &IoFileObjectType->TypeInfo.GenericMapping,
6986d0c07c4SPierre Schweitzer                                           UserMode,
6996d0c07c4SPierre Schweitzer                                           &GrantedAccess,
7006d0c07c4SPierre Schweitzer                                           &Status);
7016d0c07c4SPierre Schweitzer             if (Privileges != NULL)
7026d0c07c4SPierre Schweitzer             {
7036d0c07c4SPierre Schweitzer                 /* Append and free the privileges */
7046d0c07c4SPierre Schweitzer                 SeAppendPrivileges(AccessState, Privileges);
7056d0c07c4SPierre Schweitzer                 SeFreePrivileges(Privileges);
7066d0c07c4SPierre Schweitzer             }
7076d0c07c4SPierre Schweitzer 
7086d0c07c4SPierre Schweitzer             /* Check if we got access */
7096d0c07c4SPierre Schweitzer             if (GrantedAccess)
7106d0c07c4SPierre Schweitzer             {
7116d0c07c4SPierre Schweitzer                 AccessState->PreviouslyGrantedAccess |= GrantedAccess;
7126d0c07c4SPierre Schweitzer                 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
7136d0c07c4SPierre Schweitzer             }
7146d0c07c4SPierre Schweitzer 
7156d0c07c4SPierre Schweitzer             FileString.Length = 8;
7166d0c07c4SPierre Schweitzer             FileString.MaximumLength = 8;
7176d0c07c4SPierre Schweitzer             FileString.Buffer = L"File";
7186d0c07c4SPierre Schweitzer 
7196d0c07c4SPierre Schweitzer             /* Do Audit/Alarm for open operation
7206d0c07c4SPierre Schweitzer              * NOTA: we audit target device object
7216d0c07c4SPierre Schweitzer              */
7226d0c07c4SPierre Schweitzer             SeOpenObjectAuditAlarm(&FileString,
7236d0c07c4SPierre Schweitzer                                    DeviceObject,
7246d0c07c4SPierre Schweitzer                                    CompleteName,
7256d0c07c4SPierre Schweitzer                                    OriginalDeviceObject->SecurityDescriptor,
7266d0c07c4SPierre Schweitzer                                    AccessState,
7276d0c07c4SPierre Schweitzer                                    FALSE,
7286d0c07c4SPierre Schweitzer                                    AccessGranted,
7296d0c07c4SPierre Schweitzer                                    UserMode,
7306d0c07c4SPierre Schweitzer                                    &AccessState->GenerateOnClose);
7316d0c07c4SPierre Schweitzer 
7326d0c07c4SPierre Schweitzer             SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
7336d0c07c4SPierre Schweitzer 
7346d0c07c4SPierre Schweitzer             ExReleaseResourceLite(&IopSecurityResource);
7356d0c07c4SPierre Schweitzer             KeLeaveCriticalRegion();
7366d0c07c4SPierre Schweitzer 
7376d0c07c4SPierre Schweitzer             /* Check if access failed */
7386d0c07c4SPierre Schweitzer             if (!AccessGranted)
7396d0c07c4SPierre Schweitzer             {
7406d0c07c4SPierre Schweitzer                 /* Dereference the device and fail */
7416d0c07c4SPierre Schweitzer                 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
7426d0c07c4SPierre Schweitzer                 if (Vpb) IopDereferenceVpbAndFree(Vpb);
7436d0c07c4SPierre Schweitzer                 return STATUS_ACCESS_DENIED;
7446d0c07c4SPierre Schweitzer             }
745c2c66affSColin Finck         }
746c2c66affSColin Finck 
747c2c66affSColin Finck         /* Allocate the IRP */
748c2c66affSColin Finck         Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
749c2c66affSColin Finck         if (!Irp)
750c2c66affSColin Finck         {
751c2c66affSColin Finck             /* Dereference the device and VPB, then fail */
752c2c66affSColin Finck             IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
753c2c66affSColin Finck             if (Vpb) IopDereferenceVpbAndFree(Vpb);
754c2c66affSColin Finck             return STATUS_INSUFFICIENT_RESOURCES;
755c2c66affSColin Finck         }
756c2c66affSColin Finck 
757c2c66affSColin Finck         /* Now set the IRP data */
758c2c66affSColin Finck         Irp->RequestorMode = AccessMode;
759c2c66affSColin Finck         Irp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API | IRP_DEFER_IO_COMPLETION;
760c2c66affSColin Finck         Irp->Tail.Overlay.Thread = PsGetCurrentThread();
761c2c66affSColin Finck         Irp->UserIosb = &IoStatusBlock;
762c2c66affSColin Finck         Irp->MdlAddress = NULL;
763c2c66affSColin Finck         Irp->PendingReturned = FALSE;
764c2c66affSColin Finck         Irp->UserEvent = NULL;
765c2c66affSColin Finck         Irp->Cancel = FALSE;
766c2c66affSColin Finck         Irp->CancelRoutine = NULL;
767c2c66affSColin Finck         Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
768c2c66affSColin Finck 
769c2c66affSColin Finck         /* Setup the security context */
770c2c66affSColin Finck         SecurityContext.SecurityQos = SecurityQos;
771c2c66affSColin Finck         SecurityContext.AccessState = AccessState;
772c2c66affSColin Finck         SecurityContext.DesiredAccess = AccessState->RemainingDesiredAccess;
773c2c66affSColin Finck         SecurityContext.FullCreateOptions = OpenPacket->CreateOptions;
774c2c66affSColin Finck 
775c2c66affSColin Finck         /* Get the I/O Stack location */
776ca9fd861STimo Kreuzer         StackLoc = IoGetNextIrpStackLocation(Irp);
777c2c66affSColin Finck         StackLoc->Control = 0;
778c2c66affSColin Finck 
779c2c66affSColin Finck         /* Check what kind of file this is */
780c2c66affSColin Finck         switch (OpenPacket->CreateFileType)
781c2c66affSColin Finck         {
782c2c66affSColin Finck             /* Normal file */
783c2c66affSColin Finck             case CreateFileTypeNone:
784c2c66affSColin Finck 
785c2c66affSColin Finck                 /* Set the major function and EA Length */
786c2c66affSColin Finck                 StackLoc->MajorFunction = IRP_MJ_CREATE;
787c2c66affSColin Finck                 StackLoc->Parameters.Create.EaLength = OpenPacket->EaLength;
788c2c66affSColin Finck 
789c2c66affSColin Finck                 /* Set the flags */
790c2c66affSColin Finck                 StackLoc->Flags = (UCHAR)OpenPacket->Options;
791c2c66affSColin Finck                 StackLoc->Flags |= !(Attributes & OBJ_CASE_INSENSITIVE) ? SL_CASE_SENSITIVE: 0;
792c2c66affSColin Finck                 break;
793c2c66affSColin Finck 
794c2c66affSColin Finck             /* Named pipe */
795c2c66affSColin Finck             case CreateFileTypeNamedPipe:
796c2c66affSColin Finck 
797c2c66affSColin Finck                 /* Set the named pipe MJ and set the parameters */
798c2c66affSColin Finck                 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
799c2c66affSColin Finck                 StackLoc->Parameters.CreatePipe.Parameters = OpenPacket->ExtraCreateParameters;
800c2c66affSColin Finck                 break;
801c2c66affSColin Finck 
802c2c66affSColin Finck             /* Mailslot */
803c2c66affSColin Finck             case CreateFileTypeMailslot:
804c2c66affSColin Finck 
805c2c66affSColin Finck                 /* Set the mailslot MJ and set the parameters */
806c2c66affSColin Finck                 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
807c2c66affSColin Finck                 StackLoc->Parameters.CreateMailslot.Parameters = OpenPacket->ExtraCreateParameters;
808c2c66affSColin Finck                 break;
809c2c66affSColin Finck         }
810c2c66affSColin Finck 
811c2c66affSColin Finck         /* Set the common data */
812c2c66affSColin Finck         Irp->Overlay.AllocationSize = OpenPacket->AllocationSize;
813c2c66affSColin Finck         Irp->AssociatedIrp.SystemBuffer = OpenPacket->EaBuffer;
814c2c66affSColin Finck         StackLoc->Parameters.Create.Options = (OpenPacket->Disposition << 24) |
815c2c66affSColin Finck                                               (OpenPacket->CreateOptions &
816c2c66affSColin Finck                                                0xFFFFFF);
817c2c66affSColin Finck         StackLoc->Parameters.Create.FileAttributes = OpenPacket->FileAttributes;
818c2c66affSColin Finck         StackLoc->Parameters.Create.ShareAccess = OpenPacket->ShareAccess;
819c2c66affSColin Finck         StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
820c2c66affSColin Finck 
821c2c66affSColin Finck         /* Check if we really need to create an object */
822c2c66affSColin Finck         if (!UseDummyFile)
823c2c66affSColin Finck         {
824c2c66affSColin Finck             ULONG ObjectSize = sizeof(FILE_OBJECT);
825c2c66affSColin Finck 
826c2c66affSColin Finck             /* Tag on space for a file object extension */
827c2c66affSColin Finck             if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION)
828c2c66affSColin Finck                 ObjectSize += sizeof(FILE_OBJECT_EXTENSION);
829c2c66affSColin Finck 
830c2c66affSColin Finck             /* Create the actual file object */
831c2c66affSColin Finck             InitializeObjectAttributes(&ObjectAttributes,
832c2c66affSColin Finck                                        NULL,
833c2c66affSColin Finck                                        Attributes,
834c2c66affSColin Finck                                        NULL,
835c2c66affSColin Finck                                        NULL);
836c2c66affSColin Finck             Status = ObCreateObject(KernelMode,
837c2c66affSColin Finck                                     IoFileObjectType,
838c2c66affSColin Finck                                     &ObjectAttributes,
839c2c66affSColin Finck                                     AccessMode,
840c2c66affSColin Finck                                     NULL,
841c2c66affSColin Finck                                     ObjectSize,
842c2c66affSColin Finck                                     0,
843c2c66affSColin Finck                                     0,
844c2c66affSColin Finck                                     (PVOID*)&FileObject);
845c2c66affSColin Finck             if (!NT_SUCCESS(Status))
846c2c66affSColin Finck             {
847c2c66affSColin Finck                 /* Create failed, free the IRP */
848c2c66affSColin Finck                 IoFreeIrp(Irp);
849c2c66affSColin Finck 
850c2c66affSColin Finck                 /* Dereference the device and VPB */
851c2c66affSColin Finck                 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
852c2c66affSColin Finck                 if (Vpb) IopDereferenceVpbAndFree(Vpb);
853c2c66affSColin Finck 
854c2c66affSColin Finck                 /* We failed, return status */
855c2c66affSColin Finck                 OpenPacket->FinalStatus = Status;
856c2c66affSColin Finck                 return Status;
857c2c66affSColin Finck             }
858c2c66affSColin Finck 
859c2c66affSColin Finck             /* Clear the file object */
86082cf6c2bSOleg Dubinskiy             RtlZeroMemory(FileObject, ObjectSize);
861c2c66affSColin Finck 
862c2c66affSColin Finck             /* Check if this is Synch I/O */
863c2c66affSColin Finck             if (OpenPacket->CreateOptions &
864c2c66affSColin Finck                 (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))
865c2c66affSColin Finck             {
866c2c66affSColin Finck                 /* Set the synch flag */
867c2c66affSColin Finck                 FileObject->Flags |= FO_SYNCHRONOUS_IO;
868c2c66affSColin Finck 
869c2c66affSColin Finck                 /* Check if it's also alertable */
870c2c66affSColin Finck                 if (OpenPacket->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
871c2c66affSColin Finck                 {
872c2c66affSColin Finck                     /* It is, set the alertable flag */
873c2c66affSColin Finck                     FileObject->Flags |= FO_ALERTABLE_IO;
874c2c66affSColin Finck                 }
875c2c66affSColin Finck             }
876c2c66affSColin Finck 
877c2c66affSColin Finck             /* Check if this is synch I/O */
878c2c66affSColin Finck             if (FileObject->Flags & FO_SYNCHRONOUS_IO)
879c2c66affSColin Finck             {
880c2c66affSColin Finck                 /* Initialize the event */
881c2c66affSColin Finck                 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, FALSE);
882c2c66affSColin Finck             }
883c2c66affSColin Finck 
884c2c66affSColin Finck             /* Check if the caller requested no intermediate buffering */
885c2c66affSColin Finck             if (OpenPacket->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)
886c2c66affSColin Finck             {
887c2c66affSColin Finck                 /* Set the correct flag for the FSD to read */
888c2c66affSColin Finck                 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
889c2c66affSColin Finck             }
890c2c66affSColin Finck 
891c2c66affSColin Finck             /* Check if the caller requested write through support */
892c2c66affSColin Finck             if (OpenPacket->CreateOptions & FILE_WRITE_THROUGH)
893c2c66affSColin Finck             {
894c2c66affSColin Finck                 /* Set the correct flag for the FSD to read */
895c2c66affSColin Finck                 FileObject->Flags |= FO_WRITE_THROUGH;
896c2c66affSColin Finck             }
897c2c66affSColin Finck 
898c2c66affSColin Finck             /* Check if the caller says the file will be only read sequentially */
899c2c66affSColin Finck             if (OpenPacket->CreateOptions & FILE_SEQUENTIAL_ONLY)
900c2c66affSColin Finck             {
901c2c66affSColin Finck                 /* Set the correct flag for the FSD to read */
902c2c66affSColin Finck                 FileObject->Flags |= FO_SEQUENTIAL_ONLY;
903c2c66affSColin Finck             }
904c2c66affSColin Finck 
905c2c66affSColin Finck             /* Check if the caller believes the file will be only read randomly */
906c2c66affSColin Finck             if (OpenPacket->CreateOptions & FILE_RANDOM_ACCESS)
907c2c66affSColin Finck             {
908c2c66affSColin Finck                 /* Set the correct flag for the FSD to read */
909c2c66affSColin Finck                 FileObject->Flags |= FO_RANDOM_ACCESS;
910c2c66affSColin Finck             }
911c2c66affSColin Finck 
912c2c66affSColin Finck             /* Check if we were asked to setup a file object extension */
913c2c66affSColin Finck             if (OpenPacket->InternalFlags & IOP_CREATE_FILE_OBJECT_EXTENSION)
914c2c66affSColin Finck             {
915c2c66affSColin Finck                 PFILE_OBJECT_EXTENSION FileObjectExtension;
916c2c66affSColin Finck 
917c2c66affSColin Finck                 /* Make sure the file object knows it has an extension */
918c2c66affSColin Finck                 FileObject->Flags |= FO_FILE_OBJECT_HAS_EXTENSION;
919c2c66affSColin Finck 
92082cf6c2bSOleg Dubinskiy                 /* Initialize file object extension */
921c2c66affSColin Finck                 FileObjectExtension = (PFILE_OBJECT_EXTENSION)(FileObject + 1);
922c2c66affSColin Finck                 FileObject->FileObjectExtension = FileObjectExtension;
923c2c66affSColin Finck 
924c2c66affSColin Finck                 /* Add the top level device which we'll send the request to */
925c2c66affSColin Finck                 if (OpenPacket->InternalFlags & IOP_USE_TOP_LEVEL_DEVICE_HINT)
926c2c66affSColin Finck                 {
927c2c66affSColin Finck                     FileObjectExtension->TopDeviceObjectHint = DeviceObject;
928c2c66affSColin Finck                 }
929c2c66affSColin Finck             }
930c2c66affSColin Finck         }
931c2c66affSColin Finck         else
932c2c66affSColin Finck         {
933c2c66affSColin Finck             /* Use the dummy object instead */
934c2c66affSColin Finck             LocalFileObject = OpenPacket->LocalFileObject;
935c2c66affSColin Finck             RtlZeroMemory(LocalFileObject, sizeof(DUMMY_FILE_OBJECT));
936c2c66affSColin Finck 
937c2c66affSColin Finck             /* Set it up */
938c2c66affSColin Finck             FileObject = (PFILE_OBJECT)&LocalFileObject->ObjectHeader.Body;
939c2c66affSColin Finck             LocalFileObject->ObjectHeader.Type = IoFileObjectType;
940c2c66affSColin Finck             LocalFileObject->ObjectHeader.PointerCount = 1;
941c2c66affSColin Finck         }
942c2c66affSColin Finck 
943c2c66affSColin Finck         /* Setup the file header */
944c2c66affSColin Finck         FileObject->Type = IO_TYPE_FILE;
945c2c66affSColin Finck         FileObject->Size = sizeof(FILE_OBJECT);
946c2c66affSColin Finck         FileObject->RelatedFileObject = OpenPacket->RelatedFileObject;
947c2c66affSColin Finck         FileObject->DeviceObject = OriginalDeviceObject;
948c2c66affSColin Finck 
949c2c66affSColin Finck         /* Check if this is a direct device open */
950c2c66affSColin Finck         if (DirectOpen) FileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
951c2c66affSColin Finck 
952c2c66affSColin Finck         /* Check if the caller wants case sensitivity */
953c2c66affSColin Finck         if (!(Attributes & OBJ_CASE_INSENSITIVE))
954c2c66affSColin Finck         {
955c2c66affSColin Finck             /* Tell the driver about it */
956c2c66affSColin Finck             FileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
957c2c66affSColin Finck         }
958c2c66affSColin Finck 
959c2c66affSColin Finck         /* Now set the file object */
960c2c66affSColin Finck         Irp->Tail.Overlay.OriginalFileObject = FileObject;
961c2c66affSColin Finck         StackLoc->FileObject = FileObject;
962c2c66affSColin Finck 
963c2c66affSColin Finck         /* Check if the file object has a name */
964c2c66affSColin Finck         if (RemainingName->Length)
965c2c66affSColin Finck         {
966c2c66affSColin Finck             /* Setup the unicode string */
967d3a97e22SHermès Bélusca-Maïto             FileObject->FileName.MaximumLength = RemainingName->Length + sizeof(WCHAR);
968c2c66affSColin Finck             FileObject->FileName.Buffer = ExAllocatePoolWithTag(PagedPool,
969d3a97e22SHermès Bélusca-Maïto                                                                 FileObject->FileName.MaximumLength,
970c2c66affSColin Finck                                                                 TAG_IO_NAME);
971c2c66affSColin Finck             if (!FileObject->FileName.Buffer)
972c2c66affSColin Finck             {
973c2c66affSColin Finck                 /* Failed to allocate the name, free the IRP */
974c2c66affSColin Finck                 IoFreeIrp(Irp);
975c2c66affSColin Finck 
976c2c66affSColin Finck                 /* Dereference the device object and VPB */
977c2c66affSColin Finck                 IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
978c2c66affSColin Finck                 if (Vpb) IopDereferenceVpbAndFree(Vpb);
979c2c66affSColin Finck 
980c2c66affSColin Finck                 /* Clear the FO and dereference it */
981c2c66affSColin Finck                 FileObject->DeviceObject = NULL;
982c2c66affSColin Finck                 if (!UseDummyFile) ObDereferenceObject(FileObject);
983c2c66affSColin Finck 
984c2c66affSColin Finck                 /* Fail */
985c2c66affSColin Finck                 return STATUS_INSUFFICIENT_RESOURCES;
986c2c66affSColin Finck             }
987c2c66affSColin Finck         }
988c2c66affSColin Finck 
989c2c66affSColin Finck         /* Copy the name */
990c2c66affSColin Finck         RtlCopyUnicodeString(&FileObject->FileName, RemainingName);
991c2c66affSColin Finck 
992c2c66affSColin Finck         /* Initialize the File Object event and set the FO */
993c2c66affSColin Finck         KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
994c2c66affSColin Finck         OpenPacket->FileObject = FileObject;
995c2c66affSColin Finck 
996c2c66affSColin Finck         /* Queue the IRP and call the driver */
997c2c66affSColin Finck         IopQueueIrpToThread(Irp);
998c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
999c2c66affSColin Finck         if (Status == STATUS_PENDING)
1000c2c66affSColin Finck         {
1001c2c66affSColin Finck             /* Wait for the driver to complete the create */
1002c2c66affSColin Finck             KeWaitForSingleObject(&FileObject->Event,
1003c2c66affSColin Finck                                   Executive,
1004c2c66affSColin Finck                                   KernelMode,
1005c2c66affSColin Finck                                   FALSE,
1006c2c66affSColin Finck                                   NULL);
1007c2c66affSColin Finck 
1008c2c66affSColin Finck             /* Get the new status */
1009c2c66affSColin Finck             Status = IoStatusBlock.Status;
1010c2c66affSColin Finck         }
1011c2c66affSColin Finck         else
1012c2c66affSColin Finck         {
1013c2c66affSColin Finck             /* We'll have to complete it ourselves */
1014c2c66affSColin Finck             ASSERT(!Irp->PendingReturned);
1015c2c66affSColin Finck             ASSERT(!Irp->MdlAddress);
1016c2c66affSColin Finck 
1017c2c66affSColin Finck             /* Handle name change if required */
1018c2c66affSColin Finck             if (Status == STATUS_REPARSE)
1019c2c66affSColin Finck             {
1020c2c66affSColin Finck                 /* Check this is a mount point */
1021c2c66affSColin Finck                 if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)
1022c2c66affSColin Finck                 {
1023c2c66affSColin Finck                     PREPARSE_DATA_BUFFER ReparseData;
1024c2c66affSColin Finck 
1025c2c66affSColin Finck                     /* Reparse point attributes were passed by the driver in the auxiliary buffer */
1026c2c66affSColin Finck                     ASSERT(Irp->Tail.Overlay.AuxiliaryBuffer != NULL);
1027c2c66affSColin Finck                     ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer;
1028c2c66affSColin Finck 
1029c2c66affSColin Finck                     ASSERT(ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT);
1030c2c66affSColin Finck                     ASSERT(ReparseData->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1031c2c66affSColin Finck                     ASSERT(ReparseData->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1032c2c66affSColin Finck 
1033c2c66affSColin Finck                     IopDoNameTransmogrify(Irp, FileObject, ReparseData);
1034c2c66affSColin Finck                 }
1035c2c66affSColin Finck             }
1036c2c66affSColin Finck 
1037c2c66affSColin Finck             /* Completion happens at APC_LEVEL */
1038c2c66affSColin Finck             KeRaiseIrql(APC_LEVEL, &OldIrql);
1039c2c66affSColin Finck 
1040c2c66affSColin Finck             /* Get the new I/O Status block ourselves */
1041c2c66affSColin Finck             IoStatusBlock = Irp->IoStatus;
1042c2c66affSColin Finck             Status = IoStatusBlock.Status;
1043c2c66affSColin Finck 
1044c2c66affSColin Finck             /* Manually signal the even, we can't have any waiters */
1045c2c66affSColin Finck             FileObject->Event.Header.SignalState = 1;
1046c2c66affSColin Finck 
1047c2c66affSColin Finck             /* Now that we've signaled the events, de-associate the IRP */
1048c2c66affSColin Finck             IopUnQueueIrpFromThread(Irp);
1049c2c66affSColin Finck 
1050c2c66affSColin Finck             /* Check if the IRP had an input buffer */
1051c2c66affSColin Finck             if ((Irp->Flags & IRP_BUFFERED_IO) &&
1052c2c66affSColin Finck                 (Irp->Flags & IRP_DEALLOCATE_BUFFER))
1053c2c66affSColin Finck             {
1054c2c66affSColin Finck                 /* Free it. A driver might've tacked one on */
1055c2c66affSColin Finck                 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
1056c2c66affSColin Finck             }
1057c2c66affSColin Finck 
1058c2c66affSColin Finck             /* Free the IRP and bring the IRQL back down */
1059c2c66affSColin Finck             IoFreeIrp(Irp);
1060c2c66affSColin Finck             KeLowerIrql(OldIrql);
1061c2c66affSColin Finck         }
1062c2c66affSColin Finck 
1063c2c66affSColin Finck         /* Copy the I/O Status */
1064c2c66affSColin Finck         OpenPacket->Information = IoStatusBlock.Information;
1065c2c66affSColin Finck 
1066c2c66affSColin Finck         /* The driver failed to create the file */
1067c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1068c2c66affSColin Finck         {
1069fefb982dSHermès Bélusca-Maïto             /* Check if we have a name and if so, free it */
1070c2c66affSColin Finck             if (FileObject->FileName.Length)
1071c2c66affSColin Finck             {
1072fefb982dSHermès Bélusca-Maïto                 /*
1073fefb982dSHermès Bélusca-Maïto                  * Don't use TAG_IO_NAME since the FileObject's FileName
1074fefb982dSHermès Bélusca-Maïto                  * may have been re-allocated using a different tag
1075fefb982dSHermès Bélusca-Maïto                  * by a filesystem.
1076fefb982dSHermès Bélusca-Maïto                  */
1077fefb982dSHermès Bélusca-Maïto                 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1078fefb982dSHermès Bélusca-Maïto                 FileObject->FileName.Buffer = NULL;
1079c2c66affSColin Finck                 FileObject->FileName.Length = 0;
1080c2c66affSColin Finck             }
1081c2c66affSColin Finck 
1082c2c66affSColin Finck             /* Clear its device object */
1083c2c66affSColin Finck             FileObject->DeviceObject = NULL;
1084c2c66affSColin Finck 
1085c2c66affSColin Finck             /* Save this now because the FO might go away */
1086c2c66affSColin Finck             OpenCancelled = FileObject->Flags & FO_FILE_OPEN_CANCELLED ?
1087c2c66affSColin Finck                             TRUE : FALSE;
1088c2c66affSColin Finck 
1089c2c66affSColin Finck             /* Clear the file object in the open packet */
1090c2c66affSColin Finck             OpenPacket->FileObject = NULL;
1091c2c66affSColin Finck 
1092c2c66affSColin Finck             /* Dereference the file object */
1093c2c66affSColin Finck             if (!UseDummyFile) ObDereferenceObject(FileObject);
1094c2c66affSColin Finck 
1095c2c66affSColin Finck             /* Dereference the device object */
1096c2c66affSColin Finck             IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
1097c2c66affSColin Finck 
1098c2c66affSColin Finck             /* Unless the driver cancelled the open, dereference the VPB */
1099c2c66affSColin Finck             if (!(OpenCancelled) && (Vpb)) IopDereferenceVpbAndFree(Vpb);
1100c2c66affSColin Finck 
1101c2c66affSColin Finck             /* Set the status and return */
1102c2c66affSColin Finck             OpenPacket->FinalStatus = Status;
1103c2c66affSColin Finck             return Status;
1104c2c66affSColin Finck         }
1105c2c66affSColin Finck         else if (Status == STATUS_REPARSE)
1106c2c66affSColin Finck         {
1107c2c66affSColin Finck             if (OpenPacket->Information == IO_REPARSE ||
1108c2c66affSColin Finck                 OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
1109c2c66affSColin Finck             {
1110c2c66affSColin Finck                 /* Update CompleteName with reparse info which got updated in IopDoNameTransmogrify() */
1111c2c66affSColin Finck                 if (CompleteName->MaximumLength < FileObject->FileName.Length)
1112c2c66affSColin Finck                 {
1113c2c66affSColin Finck                     PWSTR NewCompleteName;
1114c2c66affSColin Finck 
1115c2c66affSColin Finck                     /* Allocate a new buffer for the string */
1116c2c66affSColin Finck                     NewCompleteName = ExAllocatePoolWithTag(PagedPool, FileObject->FileName.Length, TAG_IO_NAME);
1117c2c66affSColin Finck                     if (NewCompleteName == NULL)
1118c2c66affSColin Finck                     {
1119c2c66affSColin Finck                         OpenPacket->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
1120c2c66affSColin Finck                         return STATUS_INSUFFICIENT_RESOURCES;
1121c2c66affSColin Finck                     }
1122c2c66affSColin Finck 
1123c2c66affSColin Finck                     /* Release the old one */
1124c2c66affSColin Finck                     if (CompleteName->Buffer != NULL)
1125c2c66affSColin Finck                     {
1126fefb982dSHermès Bélusca-Maïto                         /*
1127fefb982dSHermès Bélusca-Maïto                          * Don't use TAG_IO_NAME since the FileObject's FileName
1128fefb982dSHermès Bélusca-Maïto                          * may have been re-allocated using a different tag
1129fefb982dSHermès Bélusca-Maïto                          * by a filesystem.
1130fefb982dSHermès Bélusca-Maïto                          */
1131c2c66affSColin Finck                         ExFreePoolWithTag(CompleteName->Buffer, 0);
1132c2c66affSColin Finck                     }
1133c2c66affSColin Finck 
1134c2c66affSColin Finck                     /* And setup the new one */
1135c2c66affSColin Finck                     CompleteName->Buffer = NewCompleteName;
1136c2c66affSColin Finck                     CompleteName->MaximumLength = FileObject->FileName.Length;
1137c2c66affSColin Finck                 }
1138c2c66affSColin Finck 
1139c2c66affSColin Finck                 /* Copy our new complete name */
1140c2c66affSColin Finck                 RtlCopyUnicodeString(CompleteName, &FileObject->FileName);
1141c2c66affSColin Finck 
1142c2c66affSColin Finck                 if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
1143c2c66affSColin Finck                 {
1144c2c66affSColin Finck                     OpenPacket->RelatedFileObject = NULL;
1145c2c66affSColin Finck                 }
1146c2c66affSColin Finck             }
1147c2c66affSColin Finck 
1148fefb982dSHermès Bélusca-Maïto             /* Check if we have a name and if so, free it */
1149c2c66affSColin Finck             if (FileObject->FileName.Length)
1150c2c66affSColin Finck             {
1151fefb982dSHermès Bélusca-Maïto                 /*
1152fefb982dSHermès Bélusca-Maïto                  * Don't use TAG_IO_NAME since the FileObject's FileName
1153fefb982dSHermès Bélusca-Maïto                  * may have been re-allocated using a different tag
1154fefb982dSHermès Bélusca-Maïto                  * by a filesystem.
1155fefb982dSHermès Bélusca-Maïto                  */
1156c2c66affSColin Finck                 ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1157fefb982dSHermès Bélusca-Maïto                 FileObject->FileName.Buffer = NULL;
1158c2c66affSColin Finck                 FileObject->FileName.Length = 0;
1159c2c66affSColin Finck             }
1160c2c66affSColin Finck 
1161c2c66affSColin Finck             /* Clear its device object */
1162c2c66affSColin Finck             FileObject->DeviceObject = NULL;
1163c2c66affSColin Finck 
1164c2c66affSColin Finck             /* Clear the file object in the open packet */
1165c2c66affSColin Finck             OpenPacket->FileObject = NULL;
1166c2c66affSColin Finck 
1167c2c66affSColin Finck             /* Dereference the file object */
1168c2c66affSColin Finck             if (!UseDummyFile) ObDereferenceObject(FileObject);
1169c2c66affSColin Finck 
1170c2c66affSColin Finck             /* Dereference the device object */
1171c2c66affSColin Finck             IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
1172c2c66affSColin Finck 
1173c2c66affSColin Finck             /* Unless the driver cancelled the open, dereference the VPB */
1174c2c66affSColin Finck             if (Vpb != NULL) IopDereferenceVpbAndFree(Vpb);
1175c2c66affSColin Finck 
1176c2c66affSColin Finck             if (OpenPacket->Information != IO_REMOUNT)
1177c2c66affSColin Finck             {
1178c2c66affSColin Finck                 OpenPacket->RelatedFileObject = NULL;
1179c2c66affSColin Finck 
1180c2c66affSColin Finck                 /* Inform we traversed a mount point for later attempt */
1181c2c66affSColin Finck                 if (OpenPacket->Information == IO_REPARSE_TAG_MOUNT_POINT)
1182c2c66affSColin Finck                 {
1183c2c66affSColin Finck                     OpenPacket->TraversedMountPoint = 1;
1184c2c66affSColin Finck                 }
1185c2c66affSColin Finck 
1186c2c66affSColin Finck                 /* In case we override checks, but got this on volume open, fail hard */
1187c2c66affSColin Finck                 if (OpenPacket->Override)
1188c2c66affSColin Finck                 {
1189c2c66affSColin Finck                     KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
1190c2c66affSColin Finck                                  (ULONG_PTR)OriginalDeviceObject,
1191c2c66affSColin Finck                                  (ULONG_PTR)DeviceObject,
1192c2c66affSColin Finck                                  (ULONG_PTR)CompleteName,
1193c2c66affSColin Finck                                  OpenPacket->Information);
1194c2c66affSColin Finck                 }
1195c2c66affSColin Finck 
1196c2c66affSColin Finck                 /* Return to IO/OB so that information can be upgraded */
1197c2c66affSColin Finck                 return STATUS_REPARSE;
1198c2c66affSColin Finck             }
1199c2c66affSColin Finck 
1200c2c66affSColin Finck             /* Loop again and reattempt an opening */
1201c2c66affSColin Finck             continue;
1202c2c66affSColin Finck         }
1203c2c66affSColin Finck 
1204c2c66affSColin Finck         break;
1205c2c66affSColin Finck     }
1206c2c66affSColin Finck 
1207c2c66affSColin Finck     if (Attempt == IOP_MAX_REPARSE_TRAVERSAL)
1208c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     /* Get the owner of the File Object */
1211c2c66affSColin Finck     OwnerDevice = IoGetRelatedDeviceObject(FileObject);
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     /*
1214c2c66affSColin Finck      * It's possible that the device to whom we sent the IRP to
1215c2c66affSColin Finck      * isn't actually the device that ended opening the file object
1216c2c66affSColin Finck      * internally.
1217c2c66affSColin Finck      */
1218c2c66affSColin Finck     if (OwnerDevice != DeviceObject)
1219c2c66affSColin Finck     {
1220c2c66affSColin Finck         /* We have to de-reference the VPB we had associated */
1221c2c66affSColin Finck         if (Vpb) IopDereferenceVpbAndFree(Vpb);
1222c2c66affSColin Finck 
1223c2c66affSColin Finck         /* And re-associate with the actual one */
1224c2c66affSColin Finck         Vpb = FileObject->Vpb;
1225c2c66affSColin Finck         if (Vpb) InterlockedIncrement((PLONG)&Vpb->ReferenceCount);
1226c2c66affSColin Finck     }
1227c2c66affSColin Finck 
1228c2c66affSColin Finck     /* Make sure we are not using a dummy */
1229c2c66affSColin Finck     if (!UseDummyFile)
1230c2c66affSColin Finck     {
1231c2c66affSColin Finck         /* Check if this was a volume open */
1232c2c66affSColin Finck         if ((!(FileObject->RelatedFileObject) ||
1233c2c66affSColin Finck               (FileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN)) &&
1234c2c66affSColin Finck             !(FileObject->FileName.Length))
1235c2c66affSColin Finck         {
1236c2c66affSColin Finck             /* All signs point to it, but make sure it was actually an FSD */
1237c2c66affSColin Finck             if ((OwnerDevice->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) ||
1238c2c66affSColin Finck                 (OwnerDevice->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||
1239c2c66affSColin Finck                 (OwnerDevice->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) ||
1240c2c66affSColin Finck                 (OwnerDevice->DeviceType == FILE_DEVICE_FILE_SYSTEM))
1241c2c66affSColin Finck             {
1242c2c66affSColin Finck                 /* The owner device is an FSD, so this is a volume open for real */
1243c2c66affSColin Finck                 FileObject->Flags |= FO_VOLUME_OPEN;
1244c2c66affSColin Finck             }
1245c2c66affSColin Finck         }
1246c2c66affSColin Finck 
1247c2c66affSColin Finck         /* Reference the object and set the parse check */
1248c2c66affSColin Finck         ObReferenceObject(FileObject);
1249c2c66affSColin Finck         *Object = FileObject;
1250c2c66affSColin Finck         OpenPacket->FinalStatus = IoStatusBlock.Status;
1251c2c66affSColin Finck         OpenPacket->ParseCheck = TRUE;
1252c2c66affSColin Finck         return OpenPacket->FinalStatus;
1253c2c66affSColin Finck     }
1254c2c66affSColin Finck     else
1255c2c66affSColin Finck     {
1256c2c66affSColin Finck         /* Check if this was a query */
1257c2c66affSColin Finck         if (OpenPacket->QueryOnly)
1258c2c66affSColin Finck         {
1259c2c66affSColin Finck             /* Check if the caller wants basic info only */
1260c2c66affSColin Finck             if (!OpenPacket->FullAttributes)
1261c2c66affSColin Finck             {
1262c2c66affSColin Finck                 /* Allocate the buffer */
1263c2c66affSColin Finck                 FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool,
1264c2c66affSColin Finck                                                       sizeof(*FileBasicInfo),
1265c2c66affSColin Finck                                                       TAG_IO);
1266c2c66affSColin Finck                 if (FileBasicInfo)
1267c2c66affSColin Finck                 {
1268c2c66affSColin Finck                     /* Do the query */
1269c2c66affSColin Finck                     Status = IoQueryFileInformation(FileObject,
1270c2c66affSColin Finck                                                     FileBasicInformation,
1271c2c66affSColin Finck                                                     sizeof(*FileBasicInfo),
1272c2c66affSColin Finck                                                     FileBasicInfo,
1273c2c66affSColin Finck                                                     &ReturnLength);
1274c2c66affSColin Finck                     if (NT_SUCCESS(Status))
1275c2c66affSColin Finck                     {
1276c2c66affSColin Finck                         /* Copy the data */
1277c2c66affSColin Finck                         RtlCopyMemory(OpenPacket->BasicInformation,
1278c2c66affSColin Finck                                       FileBasicInfo,
1279c2c66affSColin Finck                                       ReturnLength);
1280c2c66affSColin Finck                     }
1281c2c66affSColin Finck 
1282c2c66affSColin Finck                     /* Free our buffer */
1283c2c66affSColin Finck                     ExFreePoolWithTag(FileBasicInfo, TAG_IO);
1284c2c66affSColin Finck                 }
1285c2c66affSColin Finck                 else
1286c2c66affSColin Finck                 {
1287c2c66affSColin Finck                     /* Fail */
1288c2c66affSColin Finck                     Status = STATUS_INSUFFICIENT_RESOURCES;
1289c2c66affSColin Finck                 }
1290c2c66affSColin Finck             }
1291c2c66affSColin Finck             else
1292c2c66affSColin Finck             {
1293c2c66affSColin Finck                 /* This is a full query */
1294c2c66affSColin Finck                 Status = IoQueryFileInformation(
1295c2c66affSColin Finck                     FileObject,
1296c2c66affSColin Finck                     FileNetworkOpenInformation,
1297c2c66affSColin Finck                     sizeof(FILE_NETWORK_OPEN_INFORMATION),
1298c2c66affSColin Finck                     OpenPacket->NetworkInformation,
1299c2c66affSColin Finck                     &ReturnLength);
1300c2c66affSColin Finck                 if (!NT_SUCCESS(Status)) ASSERT(Status != STATUS_NOT_IMPLEMENTED);
1301c2c66affSColin Finck             }
1302c2c66affSColin Finck         }
1303c2c66affSColin Finck 
1304c2c66affSColin Finck         /* Delete the file object */
1305c2c66affSColin Finck         IopDeleteFile(FileObject);
1306c2c66affSColin Finck 
1307c2c66affSColin Finck         /* Clear out the file */
1308c2c66affSColin Finck         OpenPacket->FileObject = NULL;
1309c2c66affSColin Finck 
1310c2c66affSColin Finck         /* Set and return status */
1311c2c66affSColin Finck         OpenPacket->FinalStatus = Status;
1312c2c66affSColin Finck         OpenPacket->ParseCheck = TRUE;
1313c2c66affSColin Finck         return Status;
1314c2c66affSColin Finck     }
1315c2c66affSColin Finck }
1316c2c66affSColin Finck 
1317c2c66affSColin Finck NTSTATUS
1318c2c66affSColin Finck NTAPI
IopParseFile(IN PVOID ParseObject,IN PVOID ObjectType,IN OUT PACCESS_STATE AccessState,IN KPROCESSOR_MODE AccessMode,IN ULONG Attributes,IN OUT PUNICODE_STRING CompleteName,IN OUT PUNICODE_STRING RemainingName,IN OUT PVOID Context OPTIONAL,IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,OUT PVOID * Object)1319c2c66affSColin Finck IopParseFile(IN PVOID ParseObject,
1320c2c66affSColin Finck              IN PVOID ObjectType,
1321c2c66affSColin Finck              IN OUT PACCESS_STATE AccessState,
1322c2c66affSColin Finck              IN KPROCESSOR_MODE AccessMode,
1323c2c66affSColin Finck              IN ULONG Attributes,
1324c2c66affSColin Finck              IN OUT PUNICODE_STRING CompleteName,
1325c2c66affSColin Finck              IN OUT PUNICODE_STRING RemainingName,
1326c2c66affSColin Finck              IN OUT PVOID Context OPTIONAL,
1327c2c66affSColin Finck              IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
1328c2c66affSColin Finck              OUT PVOID *Object)
1329c2c66affSColin Finck {
1330c2c66affSColin Finck     PVOID DeviceObject;
1331c2c66affSColin Finck     POPEN_PACKET OpenPacket = (POPEN_PACKET)Context;
1332c2c66affSColin Finck 
1333c2c66affSColin Finck     /* Validate the open packet */
1334c2c66affSColin Finck     if (!IopValidateOpenPacket(OpenPacket)) return STATUS_OBJECT_TYPE_MISMATCH;
1335c2c66affSColin Finck 
1336c2c66affSColin Finck     /* Get the device object */
1337c2c66affSColin Finck     DeviceObject = IoGetRelatedDeviceObject(ParseObject);
1338c2c66affSColin Finck     OpenPacket->RelatedFileObject = ParseObject;
1339c2c66affSColin Finck 
1340c2c66affSColin Finck     /* Call the main routine */
1341c2c66affSColin Finck     return IopParseDevice(DeviceObject,
1342c2c66affSColin Finck                           ObjectType,
1343c2c66affSColin Finck                           AccessState,
1344c2c66affSColin Finck                           AccessMode,
1345c2c66affSColin Finck                           Attributes,
1346c2c66affSColin Finck                           CompleteName,
1347c2c66affSColin Finck                           RemainingName,
1348c2c66affSColin Finck                           OpenPacket,
1349c2c66affSColin Finck                           SecurityQos,
1350c2c66affSColin Finck                           Object);
1351c2c66affSColin Finck }
1352c2c66affSColin Finck 
1353c2c66affSColin Finck VOID
1354c2c66affSColin Finck NTAPI
IopDeleteFile(IN PVOID ObjectBody)1355c2c66affSColin Finck IopDeleteFile(IN PVOID ObjectBody)
1356c2c66affSColin Finck {
1357c2c66affSColin Finck     PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
1358c2c66affSColin Finck     PIRP Irp;
1359c2c66affSColin Finck     PIO_STACK_LOCATION StackPtr;
1360c2c66affSColin Finck     NTSTATUS Status;
1361c2c66affSColin Finck     KEVENT Event;
1362c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject;
1363c2c66affSColin Finck     BOOLEAN DereferenceDone = FALSE;
1364c2c66affSColin Finck     PVPB Vpb;
1365c2c66affSColin Finck     KIRQL OldIrql;
1366c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1367c2c66affSColin Finck 
1368c2c66affSColin Finck     /* Check if the file has a device object */
1369c2c66affSColin Finck     if (FileObject->DeviceObject)
1370c2c66affSColin Finck     {
1371c2c66affSColin Finck         /* Check if this is a direct open or not */
1372c2c66affSColin Finck         if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1373c2c66affSColin Finck         {
1374c2c66affSColin Finck             /* Get the attached device */
1375c2c66affSColin Finck             DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1376c2c66affSColin Finck         }
1377c2c66affSColin Finck         else
1378c2c66affSColin Finck         {
1379c2c66affSColin Finck             /* Use the file object's device object */
1380c2c66affSColin Finck             DeviceObject = IoGetRelatedDeviceObject(FileObject);
1381c2c66affSColin Finck         }
1382c2c66affSColin Finck 
1383c2c66affSColin Finck         /* Sanity check */
1384c2c66affSColin Finck         ASSERT(!(FileObject->Flags & FO_SYNCHRONOUS_IO) ||
1385c2c66affSColin Finck                (InterlockedExchange((PLONG)&FileObject->Busy, TRUE) == FALSE));
1386c2c66affSColin Finck 
1387c2c66affSColin Finck         /* Check if the handle wasn't created yet */
1388c2c66affSColin Finck         if (!(FileObject->Flags & FO_HANDLE_CREATED))
1389c2c66affSColin Finck         {
1390c2c66affSColin Finck             /* Send the cleanup IRP */
1391c2c66affSColin Finck             IopCloseFile(NULL, ObjectBody, 0, 1, 1);
1392c2c66affSColin Finck         }
1393c2c66affSColin Finck 
1394c2c66affSColin Finck         /* Clear and set up Events */
1395c2c66affSColin Finck         KeClearEvent(&FileObject->Event);
1396c2c66affSColin Finck         KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1397c2c66affSColin Finck 
1398c2c66affSColin Finck         /* Allocate an IRP */
1399c2c66affSColin Finck         Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
1400c2c66affSColin Finck 
1401c2c66affSColin Finck         /* Set it up */
1402c2c66affSColin Finck         Irp->UserEvent = &Event;
1403c2c66affSColin Finck         Irp->UserIosb = &Irp->IoStatus;
1404c2c66affSColin Finck         Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1405c2c66affSColin Finck         Irp->Tail.Overlay.OriginalFileObject = FileObject;
1406c2c66affSColin Finck         Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
1407c2c66affSColin Finck 
1408c2c66affSColin Finck         /* Set up Stack Pointer Data */
1409c2c66affSColin Finck         StackPtr = IoGetNextIrpStackLocation(Irp);
1410c2c66affSColin Finck         StackPtr->MajorFunction = IRP_MJ_CLOSE;
1411c2c66affSColin Finck         StackPtr->FileObject = FileObject;
1412c2c66affSColin Finck 
1413c2c66affSColin Finck         /* Queue the IRP */
1414c2c66affSColin Finck         IopQueueIrpToThread(Irp);
1415c2c66affSColin Finck 
1416c2c66affSColin Finck         /* Get the VPB and check if this isn't a direct open */
1417c2c66affSColin Finck         Vpb = FileObject->Vpb;
1418c2c66affSColin Finck         if ((Vpb) && !(FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
1419c2c66affSColin Finck         {
1420c2c66affSColin Finck             /* Dereference the VPB before the close */
1421c2c66affSColin Finck             InterlockedDecrement((PLONG)&Vpb->ReferenceCount);
1422c2c66affSColin Finck         }
1423c2c66affSColin Finck 
1424c2c66affSColin Finck         /* Check if the FS will never disappear by itself */
1425c2c66affSColin Finck         if (FileObject->DeviceObject->Flags & DO_NEVER_LAST_DEVICE)
1426c2c66affSColin Finck         {
1427c2c66affSColin Finck             /* Dereference it */
1428c2c66affSColin Finck             InterlockedDecrement(&FileObject->DeviceObject->ReferenceCount);
1429c2c66affSColin Finck             DereferenceDone = TRUE;
1430c2c66affSColin Finck         }
1431c2c66affSColin Finck 
1432c2c66affSColin Finck         /* Call the FS Driver */
1433c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
1434c2c66affSColin Finck         if (Status == STATUS_PENDING)
1435c2c66affSColin Finck         {
1436c2c66affSColin Finck             /* Wait for completion */
1437c2c66affSColin Finck             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1438c2c66affSColin Finck         }
1439c2c66affSColin Finck 
1440c2c66affSColin Finck         /* De-queue the IRP */
1441c2c66affSColin Finck         KeRaiseIrql(APC_LEVEL, &OldIrql);
1442c2c66affSColin Finck         IopUnQueueIrpFromThread(Irp);
1443c2c66affSColin Finck         KeLowerIrql(OldIrql);
1444c2c66affSColin Finck 
1445c2c66affSColin Finck         /* Free the IRP */
1446c2c66affSColin Finck         IoFreeIrp(Irp);
1447c2c66affSColin Finck 
1448c2c66affSColin Finck         /* Clear the file name */
1449c2c66affSColin Finck         if (FileObject->FileName.Buffer)
1450c2c66affSColin Finck         {
1451fefb982dSHermès Bélusca-Maïto             /*
1452fefb982dSHermès Bélusca-Maïto              * Don't use TAG_IO_NAME since the FileObject's FileName
1453fefb982dSHermès Bélusca-Maïto              * may have been re-allocated using a different tag
1454fefb982dSHermès Bélusca-Maïto              * by a filesystem.
1455fefb982dSHermès Bélusca-Maïto              */
1456fefb982dSHermès Bélusca-Maïto             ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
1457c2c66affSColin Finck             FileObject->FileName.Buffer = NULL;
1458c2c66affSColin Finck         }
1459c2c66affSColin Finck 
1460c2c66affSColin Finck         /* Check if the FO had a completion port */
1461c2c66affSColin Finck         if (FileObject->CompletionContext)
1462c2c66affSColin Finck         {
1463c2c66affSColin Finck             /* Free it */
1464c2c66affSColin Finck             ObDereferenceObject(FileObject->CompletionContext->Port);
1465c2c66affSColin Finck             ExFreePool(FileObject->CompletionContext);
1466c2c66affSColin Finck         }
1467c2c66affSColin Finck 
1468c2c66affSColin Finck         /* Check if the FO had extension */
1469c2c66affSColin Finck         if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)
1470c2c66affSColin Finck         {
1471c2c66affSColin Finck             /* Release filter context structure if any */
1472c2c66affSColin Finck             FsRtlPTeardownPerFileObjectContexts(FileObject);
1473c2c66affSColin Finck         }
1474c2c66affSColin Finck 
1475c2c66affSColin Finck         /* Check if dereference has been done yet */
1476c2c66affSColin Finck         if (!DereferenceDone)
1477c2c66affSColin Finck         {
1478c2c66affSColin Finck             /* Dereference device object */
1479c2c66affSColin Finck             IopDereferenceDeviceObject(FileObject->DeviceObject, FALSE);
1480c2c66affSColin Finck         }
1481c2c66affSColin Finck     }
1482c2c66affSColin Finck }
1483c2c66affSColin Finck 
1484c2c66affSColin Finck PDEVICE_OBJECT
1485c2c66affSColin Finck NTAPI
IopGetDeviceAttachmentBase(IN PDEVICE_OBJECT DeviceObject)1486c2c66affSColin Finck IopGetDeviceAttachmentBase(IN PDEVICE_OBJECT DeviceObject)
1487c2c66affSColin Finck {
1488c2c66affSColin Finck     PDEVICE_OBJECT PDO = DeviceObject;
1489c2c66affSColin Finck 
1490c2c66affSColin Finck     /* Go down the stack to attempt to get the PDO */
1491c2c66affSColin Finck     for (; ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo != NULL;
1492c2c66affSColin Finck            PDO = ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo);
1493c2c66affSColin Finck 
1494c2c66affSColin Finck     return PDO;
1495c2c66affSColin Finck }
1496c2c66affSColin Finck 
1497c2c66affSColin Finck PDEVICE_OBJECT
1498c2c66affSColin Finck NTAPI
IopGetDevicePDO(IN PDEVICE_OBJECT DeviceObject)1499c2c66affSColin Finck IopGetDevicePDO(IN PDEVICE_OBJECT DeviceObject)
1500c2c66affSColin Finck {
1501c2c66affSColin Finck     KIRQL OldIrql;
1502c2c66affSColin Finck     PDEVICE_OBJECT PDO;
1503c2c66affSColin Finck 
1504c2c66affSColin Finck     ASSERT(DeviceObject != NULL);
1505c2c66affSColin Finck 
1506c2c66affSColin Finck     OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
1507c2c66affSColin Finck     /* Get the base DO */
1508c2c66affSColin Finck     PDO = IopGetDeviceAttachmentBase(DeviceObject);
1509c2c66affSColin Finck     /* Check whether that's really a PDO and if so, keep it */
1510c2c66affSColin Finck     if ((PDO->Flags & DO_BUS_ENUMERATED_DEVICE) != DO_BUS_ENUMERATED_DEVICE)
1511c2c66affSColin Finck     {
1512c2c66affSColin Finck         PDO = NULL;
1513c2c66affSColin Finck     }
1514c2c66affSColin Finck     else
1515c2c66affSColin Finck     {
1516c2c66affSColin Finck         ObReferenceObject(PDO);
1517c2c66affSColin Finck     }
1518c2c66affSColin Finck     KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
1519c2c66affSColin Finck 
1520c2c66affSColin Finck     return PDO;
1521c2c66affSColin Finck }
1522c2c66affSColin Finck 
1523c2c66affSColin Finck NTSTATUS
1524c2c66affSColin Finck NTAPI
IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject,IN PSECURITY_INFORMATION SecurityInformation,IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN POOL_TYPE PoolType,IN PGENERIC_MAPPING GenericMapping)1525c2c66affSColin Finck IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject,
1526c2c66affSColin Finck                                IN PSECURITY_INFORMATION SecurityInformation,
1527c2c66affSColin Finck                                IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1528c2c66affSColin Finck                                IN POOL_TYPE PoolType,
1529c2c66affSColin Finck                                IN PGENERIC_MAPPING GenericMapping)
1530c2c66affSColin Finck {
1531c2c66affSColin Finck     NTSTATUS Status;
1532c2c66affSColin Finck     PSECURITY_DESCRIPTOR OldSecurityDescriptor, CachedSecurityDescriptor, NewSecurityDescriptor;
1533c2c66affSColin Finck 
1534c2c66affSColin Finck     PAGED_CODE();
1535c2c66affSColin Finck 
1536c2c66affSColin Finck     /* Keep attempting till we find our old SD or fail */
1537c2c66affSColin Finck     while (TRUE)
1538c2c66affSColin Finck     {
1539c2c66affSColin Finck         KeEnterCriticalRegion();
1540c2c66affSColin Finck         ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
1541c2c66affSColin Finck 
1542c2c66affSColin Finck         /* Get our old SD and reference it */
1543c2c66affSColin Finck         OldSecurityDescriptor = DeviceObject->SecurityDescriptor;
1544c2c66affSColin Finck         if (OldSecurityDescriptor != NULL)
1545c2c66affSColin Finck         {
1546c2c66affSColin Finck             ObReferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1547c2c66affSColin Finck         }
1548c2c66affSColin Finck 
1549c2c66affSColin Finck         ExReleaseResourceLite(&IopSecurityResource);
1550c2c66affSColin Finck         KeLeaveCriticalRegion();
1551c2c66affSColin Finck 
1552c2c66affSColin Finck         /* Set the SD information */
1553c2c66affSColin Finck         NewSecurityDescriptor = OldSecurityDescriptor;
1554c2c66affSColin Finck         Status = SeSetSecurityDescriptorInfo(NULL, SecurityInformation,
1555c2c66affSColin Finck                                              SecurityDescriptor, &NewSecurityDescriptor,
1556c2c66affSColin Finck                                              PoolType, GenericMapping);
1557c2c66affSColin Finck 
1558c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1559c2c66affSColin Finck         {
1560c2c66affSColin Finck             if (OldSecurityDescriptor != NULL)
1561c2c66affSColin Finck             {
1562c2c66affSColin Finck                 ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1563c2c66affSColin Finck             }
1564c2c66affSColin Finck 
1565c2c66affSColin Finck             break;
1566c2c66affSColin Finck         }
1567c2c66affSColin Finck 
1568c2c66affSColin Finck         /* Add the new DS to the internal cache */
1569c2c66affSColin Finck         Status = ObLogSecurityDescriptor(NewSecurityDescriptor,
1570c2c66affSColin Finck                                          &CachedSecurityDescriptor, 1);
1571c2c66affSColin Finck         ExFreePool(NewSecurityDescriptor);
1572c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1573c2c66affSColin Finck         {
1574c2c66affSColin Finck             ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1575c2c66affSColin Finck             break;
1576c2c66affSColin Finck         }
1577c2c66affSColin Finck 
1578c2c66affSColin Finck         KeEnterCriticalRegion();
1579c2c66affSColin Finck         ExAcquireResourceExclusiveLite(&IopSecurityResource, TRUE);
1580c2c66affSColin Finck         /* Check if someone changed it in our back */
1581c2c66affSColin Finck         if (DeviceObject->SecurityDescriptor == OldSecurityDescriptor)
1582c2c66affSColin Finck         {
1583c2c66affSColin Finck             /* We're clear, do the swap */
1584c2c66affSColin Finck             DeviceObject->SecurityDescriptor = CachedSecurityDescriptor;
1585c2c66affSColin Finck             ExReleaseResourceLite(&IopSecurityResource);
1586c2c66affSColin Finck             KeLeaveCriticalRegion();
1587c2c66affSColin Finck 
1588c2c66affSColin Finck             /* And dereference old SD (twice - us + not in use) */
1589c2c66affSColin Finck             ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 2);
1590c2c66affSColin Finck 
1591c2c66affSColin Finck             break;
1592c2c66affSColin Finck         }
1593c2c66affSColin Finck         ExReleaseResourceLite(&IopSecurityResource);
1594c2c66affSColin Finck         KeLeaveCriticalRegion();
1595c2c66affSColin Finck 
1596c2c66affSColin Finck         /* If so, try again */
1597c2c66affSColin Finck         ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
1598c2c66affSColin Finck         ObDereferenceSecurityDescriptor(CachedSecurityDescriptor, 1);
1599c2c66affSColin Finck     }
1600c2c66affSColin Finck 
1601c2c66affSColin Finck     return Status;
1602c2c66affSColin Finck }
1603c2c66affSColin Finck 
1604c2c66affSColin Finck NTSTATUS
1605c2c66affSColin Finck NTAPI
IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject,IN PDEVICE_OBJECT PhysicalDeviceObject,IN PSECURITY_INFORMATION SecurityInformation,IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN POOL_TYPE PoolType,IN PGENERIC_MAPPING GenericMapping)1606c2c66affSColin Finck IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject,
1607c2c66affSColin Finck                                 IN PDEVICE_OBJECT PhysicalDeviceObject,
1608c2c66affSColin Finck                                 IN PSECURITY_INFORMATION SecurityInformation,
1609c2c66affSColin Finck                                 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1610c2c66affSColin Finck                                 IN POOL_TYPE PoolType,
1611c2c66affSColin Finck                                 IN PGENERIC_MAPPING GenericMapping)
1612c2c66affSColin Finck {
1613c2c66affSColin Finck     PDEVICE_OBJECT CurrentDO = PhysicalDeviceObject, NextDevice;
1614c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS, TmpStatus;
1615c2c66affSColin Finck 
1616c2c66affSColin Finck     PAGED_CODE();
1617c2c66affSColin Finck 
1618c2c66affSColin Finck     ASSERT(PhysicalDeviceObject != NULL);
1619c2c66affSColin Finck 
1620c2c66affSColin Finck     /* We always reference the DO we're working on */
1621c2c66affSColin Finck     ObReferenceObject(CurrentDO);
1622c2c66affSColin Finck 
1623c2c66affSColin Finck     /* Go up from PDO to latest DO */
1624c2c66affSColin Finck     do
1625c2c66affSColin Finck     {
1626c2c66affSColin Finck         /* Attempt to set the new SD on it */
1627c2c66affSColin Finck         TmpStatus = IopSetDeviceSecurityDescriptor(CurrentDO, SecurityInformation,
1628c2c66affSColin Finck                                                    SecurityDescriptor, PoolType,
1629c2c66affSColin Finck                                                    GenericMapping);
1630c2c66affSColin Finck         /* Was our last one? Remember that status then */
1631c2c66affSColin Finck         if (CurrentDO == UpperDeviceObject)
1632c2c66affSColin Finck         {
1633c2c66affSColin Finck             Status = TmpStatus;
1634c2c66affSColin Finck         }
1635c2c66affSColin Finck 
1636c2c66affSColin Finck         /* Try to move to the next DO (and thus, reference it) */
1637c2c66affSColin Finck         NextDevice = CurrentDO->AttachedDevice;
1638c2c66affSColin Finck         if (NextDevice)
1639c2c66affSColin Finck         {
1640c2c66affSColin Finck             ObReferenceObject(NextDevice);
1641c2c66affSColin Finck         }
1642c2c66affSColin Finck 
1643c2c66affSColin Finck         /* Dereference current DO and move to the next one */
1644c2c66affSColin Finck         ObDereferenceObject(CurrentDO);
1645c2c66affSColin Finck         CurrentDO = NextDevice;
1646c2c66affSColin Finck     }
1647c2c66affSColin Finck     while (CurrentDO != NULL);
1648c2c66affSColin Finck 
1649c2c66affSColin Finck     return Status;
1650c2c66affSColin Finck }
1651c2c66affSColin Finck 
1652c2c66affSColin Finck NTSTATUS
1653c2c66affSColin Finck NTAPI
IopGetSetSecurityObject(IN PVOID ObjectBody,IN SECURITY_OPERATION_CODE OperationCode,IN PSECURITY_INFORMATION SecurityInformation,IN PSECURITY_DESCRIPTOR SecurityDescriptor,IN OUT PULONG BufferLength,IN OUT PSECURITY_DESCRIPTOR * OldSecurityDescriptor,IN POOL_TYPE PoolType,IN OUT PGENERIC_MAPPING GenericMapping)1654c2c66affSColin Finck IopGetSetSecurityObject(IN PVOID ObjectBody,
1655c2c66affSColin Finck                         IN SECURITY_OPERATION_CODE OperationCode,
1656c2c66affSColin Finck                         IN PSECURITY_INFORMATION SecurityInformation,
1657c2c66affSColin Finck                         IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1658c2c66affSColin Finck                         IN OUT PULONG BufferLength,
1659c2c66affSColin Finck                         IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
1660c2c66affSColin Finck                         IN POOL_TYPE PoolType,
1661c2c66affSColin Finck                         IN OUT PGENERIC_MAPPING GenericMapping)
1662c2c66affSColin Finck {
1663c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
1664c2c66affSColin Finck     PIO_STACK_LOCATION StackPtr;
1665c2c66affSColin Finck     PFILE_OBJECT FileObject;
1666c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject;
1667c2c66affSColin Finck     PIRP Irp;
1668c2c66affSColin Finck     BOOLEAN LocalEvent = FALSE;
1669c2c66affSColin Finck     KEVENT Event;
1670c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
1671c2c66affSColin Finck     PAGED_CODE();
1672c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1673c2c66affSColin Finck 
1674c2c66affSColin Finck     /* Check if this is a device or file */
1675c2c66affSColin Finck     if (((PFILE_OBJECT)ObjectBody)->Type == IO_TYPE_DEVICE)
1676c2c66affSColin Finck     {
1677c2c66affSColin Finck         /* It's a device */
1678c2c66affSColin Finck         DeviceObject = (PDEVICE_OBJECT)ObjectBody;
1679c2c66affSColin Finck         FileObject = NULL;
1680c2c66affSColin Finck     }
1681c2c66affSColin Finck     else
1682c2c66affSColin Finck     {
1683c2c66affSColin Finck         /* It's a file */
1684c2c66affSColin Finck         FileObject = (PFILE_OBJECT)ObjectBody;
1685c2c66affSColin Finck 
1686c2c66affSColin Finck         /* Check if this is a direct open */
1687c2c66affSColin Finck         if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
1688c2c66affSColin Finck         {
1689c2c66affSColin Finck             /* Get the Device Object */
1690c2c66affSColin Finck             DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
1691c2c66affSColin Finck         }
1692c2c66affSColin Finck         else
1693c2c66affSColin Finck         {
1694c2c66affSColin Finck             /* Otherwise, use the direct device*/
1695c2c66affSColin Finck             DeviceObject = FileObject->DeviceObject;
1696c2c66affSColin Finck         }
1697c2c66affSColin Finck     }
1698c2c66affSColin Finck 
1699c2c66affSColin Finck     /* Check if the request was for a device object */
1700c2c66affSColin Finck     if (!(FileObject) ||
1701c2c66affSColin Finck         (!(FileObject->FileName.Length) && !(FileObject->RelatedFileObject)) ||
1702c2c66affSColin Finck         (FileObject->Flags & FO_DIRECT_DEVICE_OPEN))
1703c2c66affSColin Finck     {
1704c2c66affSColin Finck         /* Check what kind of request this was */
1705c2c66affSColin Finck         if (OperationCode == QuerySecurityDescriptor)
1706c2c66affSColin Finck         {
1707c2c66affSColin Finck             return SeQuerySecurityDescriptorInfo(SecurityInformation,
1708c2c66affSColin Finck                                                  SecurityDescriptor,
1709c2c66affSColin Finck                                                  BufferLength,
1710c2c66affSColin Finck                                                  &DeviceObject->SecurityDescriptor);
1711c2c66affSColin Finck         }
1712c2c66affSColin Finck         else if (OperationCode == DeleteSecurityDescriptor)
1713c2c66affSColin Finck         {
1714c2c66affSColin Finck             /* Simply return success */
1715c2c66affSColin Finck             return STATUS_SUCCESS;
1716c2c66affSColin Finck         }
1717c2c66affSColin Finck         else if (OperationCode == AssignSecurityDescriptor)
1718c2c66affSColin Finck         {
1719c2c66affSColin Finck             Status = STATUS_SUCCESS;
1720c2c66affSColin Finck 
1721c2c66affSColin Finck             /* Make absolutely sure this is a device object */
1722c2c66affSColin Finck             if (!(FileObject) || !(FileObject->Flags & FO_STREAM_FILE))
1723c2c66affSColin Finck             {
1724c2c66affSColin Finck                 PSECURITY_DESCRIPTOR CachedSecurityDescriptor;
1725c2c66affSColin Finck 
1726c2c66affSColin Finck                 /* Add the security descriptor in cache */
1727c2c66affSColin Finck                 Status = ObLogSecurityDescriptor(SecurityDescriptor, &CachedSecurityDescriptor, 1);
1728c2c66affSColin Finck                 if (NT_SUCCESS(Status))
1729c2c66affSColin Finck                 {
1730c2c66affSColin Finck                     KeEnterCriticalRegion();
1731c2c66affSColin Finck                     ExAcquireResourceExclusiveLite(&IopSecurityResource, TRUE);
1732c2c66affSColin Finck 
1733c2c66affSColin Finck                     /* Assign the Security Descriptor */
1734c2c66affSColin Finck                     DeviceObject->SecurityDescriptor = CachedSecurityDescriptor;
1735c2c66affSColin Finck 
1736c2c66affSColin Finck                     ExReleaseResourceLite(&IopSecurityResource);
1737c2c66affSColin Finck                     KeLeaveCriticalRegion();
1738c2c66affSColin Finck                 }
1739c2c66affSColin Finck             }
1740c2c66affSColin Finck 
1741c2c66affSColin Finck             /* Return status */
1742c2c66affSColin Finck             return Status;
1743c2c66affSColin Finck         }
1744c2c66affSColin Finck         else if (OperationCode == SetSecurityDescriptor)
1745c2c66affSColin Finck         {
1746c2c66affSColin Finck             /* Get the Physical Device Object if any */
1747c2c66affSColin Finck             PDEVICE_OBJECT PDO = IopGetDevicePDO(DeviceObject);
1748c2c66affSColin Finck 
1749c2c66affSColin Finck             if (PDO != NULL)
1750c2c66affSColin Finck             {
1751c2c66affSColin Finck                 /* Apply the new SD to any DO in the path from PDO to current DO */
1752c2c66affSColin Finck                 Status = IopSetDeviceSecurityDescriptors(DeviceObject, PDO,
1753c2c66affSColin Finck                                                          SecurityInformation,
1754c2c66affSColin Finck                                                          SecurityDescriptor,
1755c2c66affSColin Finck                                                          PoolType, GenericMapping);
1756c2c66affSColin Finck                 ObDereferenceObject(PDO);
1757c2c66affSColin Finck             }
1758c2c66affSColin Finck             else
1759c2c66affSColin Finck             {
1760c2c66affSColin Finck                 /* Otherwise, just set for ourselves */
1761c2c66affSColin Finck                 Status = IopSetDeviceSecurityDescriptor(DeviceObject,
1762c2c66affSColin Finck                                                         SecurityInformation,
1763c2c66affSColin Finck                                                         SecurityDescriptor,
1764c2c66affSColin Finck                                                         PoolType, GenericMapping);
1765c2c66affSColin Finck             }
1766c2c66affSColin Finck 
1767c2c66affSColin Finck             return STATUS_SUCCESS;
1768c2c66affSColin Finck         }
1769c2c66affSColin Finck 
1770c2c66affSColin Finck         /* Shouldn't happen */
1771c2c66affSColin Finck         return STATUS_SUCCESS;
1772c2c66affSColin Finck     }
1773c2c66affSColin Finck     else if (OperationCode == DeleteSecurityDescriptor)
1774c2c66affSColin Finck     {
1775c2c66affSColin Finck         /* Same as for devices, do nothing */
1776c2c66affSColin Finck         return STATUS_SUCCESS;
1777c2c66affSColin Finck     }
1778c2c66affSColin Finck 
1779c2c66affSColin Finck     /* At this point, we know we're a file. Reference it */
1780c2c66affSColin Finck     ObReferenceObject(FileObject);
1781c2c66affSColin Finck 
1782c2c66affSColin Finck     /* Check if we should use Sync IO or not */
1783c2c66affSColin Finck     if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1784c2c66affSColin Finck     {
1785c2c66affSColin Finck         /* Lock the file object */
17868fbc4880SThomas Faber         Status = IopLockFileObject(FileObject, ExGetPreviousMode());
17878fbc4880SThomas Faber         if (Status != STATUS_SUCCESS)
17888fbc4880SThomas Faber         {
17898fbc4880SThomas Faber             ObDereferenceObject(FileObject);
17908fbc4880SThomas Faber             return Status;
17918fbc4880SThomas Faber         }
1792c2c66affSColin Finck     }
1793c2c66affSColin Finck     else
1794c2c66affSColin Finck     {
1795c2c66affSColin Finck         /* Use local event */
1796c2c66affSColin Finck         KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
1797c2c66affSColin Finck         LocalEvent = TRUE;
1798c2c66affSColin Finck     }
1799c2c66affSColin Finck 
1800c2c66affSColin Finck     /* Clear the File Object event */
1801c2c66affSColin Finck     KeClearEvent(&FileObject->Event);
1802c2c66affSColin Finck 
1803c2c66affSColin Finck     /* Get the device object */
1804c2c66affSColin Finck     DeviceObject = IoGetRelatedDeviceObject(FileObject);
1805c2c66affSColin Finck 
1806c2c66affSColin Finck     /* Allocate the IRP */
1807c2c66affSColin Finck     Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1808c2c66affSColin Finck     if (!Irp) return IopCleanupFailedIrp(FileObject, NULL, NULL);
1809c2c66affSColin Finck 
1810c2c66affSColin Finck     /* Set the IRP */
1811c2c66affSColin Finck     Irp->Tail.Overlay.OriginalFileObject = FileObject;
1812c2c66affSColin Finck     Irp->Tail.Overlay.Thread = PsGetCurrentThread();
1813c2c66affSColin Finck     Irp->RequestorMode = ExGetPreviousMode();
1814c2c66affSColin Finck     Irp->UserIosb = &IoStatusBlock;
1815c2c66affSColin Finck     Irp->UserEvent = (LocalEvent) ? &Event : NULL;
1816c2c66affSColin Finck     Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
1817c2c66affSColin Finck     Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     /* Set Stack Parameters */
1820c2c66affSColin Finck     StackPtr = IoGetNextIrpStackLocation(Irp);
1821c2c66affSColin Finck     StackPtr->FileObject = FileObject;
1822c2c66affSColin Finck 
1823c2c66affSColin Finck     /* Check if this is a query or set */
1824c2c66affSColin Finck     if (OperationCode == QuerySecurityDescriptor)
1825c2c66affSColin Finck     {
1826c2c66affSColin Finck         /* Set the major function and parameters */
1827c2c66affSColin Finck         StackPtr->MajorFunction = IRP_MJ_QUERY_SECURITY;
1828c2c66affSColin Finck         StackPtr->Parameters.QuerySecurity.SecurityInformation =
1829c2c66affSColin Finck             *SecurityInformation;
1830c2c66affSColin Finck         StackPtr->Parameters.QuerySecurity.Length = *BufferLength;
1831c2c66affSColin Finck         Irp->UserBuffer = SecurityDescriptor;
1832c2c66affSColin Finck     }
1833c2c66affSColin Finck     else
1834c2c66affSColin Finck     {
1835c2c66affSColin Finck         /* Set the major function and parameters for a set */
1836c2c66affSColin Finck         StackPtr->MajorFunction = IRP_MJ_SET_SECURITY;
1837c2c66affSColin Finck         StackPtr->Parameters.SetSecurity.SecurityInformation =
1838c2c66affSColin Finck             *SecurityInformation;
1839c2c66affSColin Finck         StackPtr->Parameters.SetSecurity.SecurityDescriptor =
1840c2c66affSColin Finck             SecurityDescriptor;
1841c2c66affSColin Finck     }
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     /* Queue the IRP */
1844c2c66affSColin Finck     IopQueueIrpToThread(Irp);
1845c2c66affSColin Finck 
1846c2c66affSColin Finck     /* Update operation counts */
1847c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
1848c2c66affSColin Finck 
1849c2c66affSColin Finck     /* Call the Driver */
1850c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
1851c2c66affSColin Finck 
1852c2c66affSColin Finck     /* Check if this was async I/O */
1853c2c66affSColin Finck     if (LocalEvent)
1854c2c66affSColin Finck     {
1855c2c66affSColin Finck         /* Check if the IRP is pending completion */
1856c2c66affSColin Finck         if (Status == STATUS_PENDING)
1857c2c66affSColin Finck         {
1858c2c66affSColin Finck             /* Wait on the local event */
1859c2c66affSColin Finck             KeWaitForSingleObject(&Event,
1860c2c66affSColin Finck                                   Executive,
1861c2c66affSColin Finck                                   KernelMode,
1862c2c66affSColin Finck                                   FALSE,
1863c2c66affSColin Finck                                   NULL);
1864c2c66affSColin Finck             Status = IoStatusBlock.Status;
1865c2c66affSColin Finck         }
1866c2c66affSColin Finck     }
1867c2c66affSColin Finck     else
1868c2c66affSColin Finck     {
1869c2c66affSColin Finck         /* Check if the IRP is pending completion */
1870c2c66affSColin Finck         if (Status == STATUS_PENDING)
1871c2c66affSColin Finck         {
1872c2c66affSColin Finck             /* Wait on the file object */
1873c2c66affSColin Finck             KeWaitForSingleObject(&FileObject->Event,
1874c2c66affSColin Finck                                   Executive,
1875c2c66affSColin Finck                                   KernelMode,
1876c2c66affSColin Finck                                   FALSE,
1877c2c66affSColin Finck                                   NULL);
1878c2c66affSColin Finck             Status = FileObject->FinalStatus;
1879c2c66affSColin Finck         }
1880c2c66affSColin Finck 
1881c2c66affSColin Finck         /* Release the lock */
1882c2c66affSColin Finck         IopUnlockFileObject(FileObject);
1883c2c66affSColin Finck     }
1884c2c66affSColin Finck 
1885c2c66affSColin Finck     /* This Driver doesn't implement Security, so try to give it a default */
1886c2c66affSColin Finck     if (Status == STATUS_INVALID_DEVICE_REQUEST)
1887c2c66affSColin Finck     {
1888c2c66affSColin Finck         /* Was this a query? */
1889c2c66affSColin Finck         if (OperationCode == QuerySecurityDescriptor)
1890c2c66affSColin Finck         {
1891c2c66affSColin Finck             /* Set a World Security Descriptor */
1892c2c66affSColin Finck             Status = SeSetWorldSecurityDescriptor(*SecurityInformation,
1893c2c66affSColin Finck                                                   SecurityDescriptor,
1894c2c66affSColin Finck                                                   BufferLength);
1895c2c66affSColin Finck         }
1896c2c66affSColin Finck         else
1897c2c66affSColin Finck         {
1898c2c66affSColin Finck             /* It wasn't a query, so just fake success */
1899c2c66affSColin Finck             Status = STATUS_SUCCESS;
1900c2c66affSColin Finck         }
1901c2c66affSColin Finck     }
1902c2c66affSColin Finck     else if (OperationCode == QuerySecurityDescriptor)
1903c2c66affSColin Finck     {
1904c2c66affSColin Finck         /* Callers usually expect the normalized form */
1905c2c66affSColin Finck         if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_BUFFER_TOO_SMALL;
1906c2c66affSColin Finck 
1907c2c66affSColin Finck         _SEH2_TRY
1908c2c66affSColin Finck         {
1909c2c66affSColin Finck             /* Return length */
1910c2c66affSColin Finck             *BufferLength = (ULONG)IoStatusBlock.Information;
1911c2c66affSColin Finck         }
1912c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1913c2c66affSColin Finck         {
1914c2c66affSColin Finck             /* Get the exception code */
1915c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
1916c2c66affSColin Finck         }
1917c2c66affSColin Finck         _SEH2_END;
1918c2c66affSColin Finck     }
1919c2c66affSColin Finck 
1920c2c66affSColin Finck     /* Return Status */
1921c2c66affSColin Finck     return Status;
1922c2c66affSColin Finck }
1923c2c66affSColin Finck 
1924c2c66affSColin Finck NTSTATUS
1925c2c66affSColin Finck NTAPI
IopQueryName(IN PVOID ObjectBody,IN BOOLEAN HasName,OUT POBJECT_NAME_INFORMATION ObjectNameInfo,IN ULONG Length,OUT PULONG ReturnLength,IN KPROCESSOR_MODE PreviousMode)1926abfddca8SPierre Schweitzer IopQueryName(IN PVOID ObjectBody,
1927abfddca8SPierre Schweitzer              IN BOOLEAN HasName,
1928abfddca8SPierre Schweitzer              OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
1929abfddca8SPierre Schweitzer              IN ULONG Length,
1930abfddca8SPierre Schweitzer              OUT PULONG ReturnLength,
1931abfddca8SPierre Schweitzer              IN KPROCESSOR_MODE PreviousMode)
1932abfddca8SPierre Schweitzer {
1933abfddca8SPierre Schweitzer     return IopQueryNameInternal(ObjectBody,
1934abfddca8SPierre Schweitzer                                 HasName,
1935abfddca8SPierre Schweitzer                                 FALSE,
1936abfddca8SPierre Schweitzer                                 ObjectNameInfo,
1937abfddca8SPierre Schweitzer                                 Length,
1938abfddca8SPierre Schweitzer                                 ReturnLength,
1939abfddca8SPierre Schweitzer                                 PreviousMode);
1940abfddca8SPierre Schweitzer }
1941abfddca8SPierre Schweitzer 
1942abfddca8SPierre Schweitzer NTSTATUS
1943abfddca8SPierre Schweitzer NTAPI
IopQueryNameInternal(IN PVOID ObjectBody,IN BOOLEAN HasName,IN BOOLEAN QueryDosName,OUT POBJECT_NAME_INFORMATION ObjectNameInfo,IN ULONG Length,OUT PULONG ReturnLength,IN KPROCESSOR_MODE PreviousMode)19441348f62fSPierre Schweitzer IopQueryNameInternal(IN PVOID ObjectBody,
1945c2c66affSColin Finck                      IN BOOLEAN HasName,
1946abfddca8SPierre Schweitzer                      IN BOOLEAN QueryDosName,
1947c2c66affSColin Finck                      OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
1948c2c66affSColin Finck                      IN ULONG Length,
1949c2c66affSColin Finck                      OUT PULONG ReturnLength,
1950c2c66affSColin Finck                      IN KPROCESSOR_MODE PreviousMode)
1951c2c66affSColin Finck {
1952c2c66affSColin Finck     POBJECT_NAME_INFORMATION LocalInfo;
1953c2c66affSColin Finck     PFILE_NAME_INFORMATION LocalFileInfo;
1954c2c66affSColin Finck     PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
1955c2c66affSColin Finck     ULONG LocalReturnLength, FileLength;
1956c2c66affSColin Finck     BOOLEAN LengthMismatch = FALSE;
1957c2c66affSColin Finck     NTSTATUS Status;
1958c2c66affSColin Finck     PWCHAR p;
19598c6c5a92SPierre Schweitzer     PDEVICE_OBJECT DeviceObject;
19608c6c5a92SPierre Schweitzer     BOOLEAN NoObCall;
19618c6c5a92SPierre Schweitzer 
1962c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
1963c2c66affSColin Finck 
1964c2c66affSColin Finck     /* Validate length */
1965c2c66affSColin Finck     if (Length < sizeof(OBJECT_NAME_INFORMATION))
1966c2c66affSColin Finck     {
1967c2c66affSColin Finck         /* Wrong length, fail */
1968c2c66affSColin Finck         *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
1969c2c66affSColin Finck         return STATUS_INFO_LENGTH_MISMATCH;
1970c2c66affSColin Finck     }
1971c2c66affSColin Finck 
1972c2c66affSColin Finck     /* Allocate Buffer */
1973c2c66affSColin Finck     LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO);
1974c2c66affSColin Finck     if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES;
1975c2c66affSColin Finck 
19768c6c5a92SPierre Schweitzer     /* Query DOS name if the caller asked to */
19778c6c5a92SPierre Schweitzer     NoObCall = FALSE;
19788c6c5a92SPierre Schweitzer     if (QueryDosName)
19798c6c5a92SPierre Schweitzer     {
19808c6c5a92SPierre Schweitzer         DeviceObject = FileObject->DeviceObject;
19818c6c5a92SPierre Schweitzer 
19828c6c5a92SPierre Schweitzer         /* In case of a network file system, don't call mountmgr */
19838c6c5a92SPierre Schweitzer         if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM)
19848c6c5a92SPierre Schweitzer         {
19858c6c5a92SPierre Schweitzer             /* We'll store separator and terminator */
19868c6c5a92SPierre Schweitzer             LocalReturnLength = sizeof(OBJECT_NAME_INFORMATION) + 2 * sizeof(WCHAR);
19878c6c5a92SPierre Schweitzer             if (Length < LocalReturnLength)
19888c6c5a92SPierre Schweitzer             {
19898c6c5a92SPierre Schweitzer                 Status = STATUS_BUFFER_OVERFLOW;
19908c6c5a92SPierre Schweitzer             }
19918c6c5a92SPierre Schweitzer             else
19928c6c5a92SPierre Schweitzer             {
19938c6c5a92SPierre Schweitzer                 LocalInfo->Name.Length = sizeof(WCHAR);
19948c6c5a92SPierre Schweitzer                 LocalInfo->Name.MaximumLength = sizeof(WCHAR);
19958c6c5a92SPierre Schweitzer                 LocalInfo->Name.Buffer = (PVOID)((ULONG_PTR)LocalInfo + sizeof(OBJECT_NAME_INFORMATION));
19968c6c5a92SPierre Schweitzer                 LocalInfo->Name.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
19978c6c5a92SPierre Schweitzer                 Status = STATUS_SUCCESS;
19988c6c5a92SPierre Schweitzer             }
19998c6c5a92SPierre Schweitzer         }
20008c6c5a92SPierre Schweitzer         /* Otherwise, call mountmgr to get DOS name */
20018c6c5a92SPierre Schweitzer         else
20028c6c5a92SPierre Schweitzer         {
20038c6c5a92SPierre Schweitzer             Status = IoVolumeDeviceToDosName(DeviceObject, &LocalInfo->Name);
20048c6c5a92SPierre Schweitzer             LocalReturnLength = LocalInfo->Name.Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR);
20058c6c5a92SPierre Schweitzer         }
20068c6c5a92SPierre Schweitzer     }
20078c6c5a92SPierre Schweitzer 
20088c6c5a92SPierre Schweitzer     /* Fall back if querying DOS name failed or if caller never wanted it ;-) */
20098c6c5a92SPierre Schweitzer     if (!QueryDosName || !NT_SUCCESS(Status))
20108c6c5a92SPierre Schweitzer     {
2011c2c66affSColin Finck         /* Query the name */
2012c2c66affSColin Finck         Status = ObQueryNameString(FileObject->DeviceObject,
2013c2c66affSColin Finck                                    LocalInfo,
2014c2c66affSColin Finck                                    Length,
2015c2c66affSColin Finck                                    &LocalReturnLength);
20168c6c5a92SPierre Schweitzer     }
20178c6c5a92SPierre Schweitzer     else
20188c6c5a92SPierre Schweitzer     {
20198c6c5a92SPierre Schweitzer         NoObCall = TRUE;
20208c6c5a92SPierre Schweitzer     }
20218c6c5a92SPierre Schweitzer 
2022c2c66affSColin Finck     if (!NT_SUCCESS(Status) && (Status != STATUS_INFO_LENGTH_MISMATCH))
2023c2c66affSColin Finck     {
2024c2c66affSColin Finck         /* Free the buffer and fail */
2025c2c66affSColin Finck         ExFreePoolWithTag(LocalInfo, TAG_IO);
2026c2c66affSColin Finck         return Status;
2027c2c66affSColin Finck     }
2028c2c66affSColin Finck 
20298c6c5a92SPierre Schweitzer     /* Get buffer pointer */
20308c6c5a92SPierre Schweitzer     p = (PWCHAR)(ObjectNameInfo + 1);
20318c6c5a92SPierre Schweitzer 
2032d8f22735SPierre Schweitzer     _SEH2_TRY
2033d8f22735SPierre Schweitzer     {
2034c2c66affSColin Finck         /* Copy the information */
20358c6c5a92SPierre Schweitzer         if (QueryDosName && NoObCall)
20368c6c5a92SPierre Schweitzer         {
20378c6c5a92SPierre Schweitzer             ASSERT(PreviousMode == KernelMode);
20388c6c5a92SPierre Schweitzer 
20398c6c5a92SPierre Schweitzer             /* Copy structure first */
20408c6c5a92SPierre Schweitzer             RtlCopyMemory(ObjectNameInfo,
20418c6c5a92SPierre Schweitzer                           LocalInfo,
20428c6c5a92SPierre Schweitzer                           (Length >= LocalReturnLength ? sizeof(OBJECT_NAME_INFORMATION) : Length));
20438c6c5a92SPierre Schweitzer             /* Name then */
20448c6c5a92SPierre Schweitzer             RtlCopyMemory(p, LocalInfo->Name.Buffer,
20458c6c5a92SPierre Schweitzer                           (Length >= LocalReturnLength ? LocalInfo->Name.Length : Length - sizeof(OBJECT_NAME_INFORMATION)));
20468c6c5a92SPierre Schweitzer 
20478c6c5a92SPierre Schweitzer             if (FileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM)
20488c6c5a92SPierre Schweitzer             {
20498c6c5a92SPierre Schweitzer                 ExFreePool(LocalInfo->Name.Buffer);
20508c6c5a92SPierre Schweitzer             }
20518c6c5a92SPierre Schweitzer         }
20528c6c5a92SPierre Schweitzer         else
20538c6c5a92SPierre Schweitzer         {
2054c2c66affSColin Finck             RtlCopyMemory(ObjectNameInfo,
2055c2c66affSColin Finck                           LocalInfo,
2056c2c66affSColin Finck                           (LocalReturnLength > Length) ?
2057c2c66affSColin Finck                           Length : LocalReturnLength);
20588c6c5a92SPierre Schweitzer         }
2059c2c66affSColin Finck 
2060c2c66affSColin Finck         /* Set buffer pointer */
2061c2c66affSColin Finck         ObjectNameInfo->Name.Buffer = p;
2062c2c66affSColin Finck 
2063c2c66affSColin Finck         /* Advance in buffer */
2064c2c66affSColin Finck         p += (LocalInfo->Name.Length / sizeof(WCHAR));
2065c2c66affSColin Finck 
2066c2c66affSColin Finck         /* Check if this already filled our buffer */
2067c2c66affSColin Finck         if (LocalReturnLength > Length)
2068c2c66affSColin Finck         {
2069c2c66affSColin Finck             /* Set the length mismatch to true, so that we can return
2070c2c66affSColin Finck              * the proper buffer size to the caller later
2071c2c66affSColin Finck              */
2072c2c66affSColin Finck             LengthMismatch = TRUE;
2073c2c66affSColin Finck 
2074c2c66affSColin Finck             /* Save the initial buffer length value */
2075c2c66affSColin Finck             *ReturnLength = LocalReturnLength;
2076c2c66affSColin Finck         }
2077c2c66affSColin Finck 
2078c2c66affSColin Finck         /* Now get the file name buffer and check the length needed */
2079c2c66affSColin Finck         LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo;
2080c2c66affSColin Finck         FileLength = Length -
2081c2c66affSColin Finck                      LocalReturnLength +
2082c2c66affSColin Finck                      FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2083c2c66affSColin Finck 
2084c2c66affSColin Finck         /* Query the File name */
2085a1401a75SPierre Schweitzer         if (PreviousMode == KernelMode &&
2086a1401a75SPierre Schweitzer             BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
2087a1401a75SPierre Schweitzer         {
2088a1401a75SPierre Schweitzer             Status = IopGetFileInformation(FileObject,
2089a1401a75SPierre Schweitzer                                            LengthMismatch ? Length : FileLength,
2090a1401a75SPierre Schweitzer                                            FileNameInformation,
2091a1401a75SPierre Schweitzer                                            LocalFileInfo,
2092a1401a75SPierre Schweitzer                                            &LocalReturnLength);
2093a1401a75SPierre Schweitzer         }
2094a1401a75SPierre Schweitzer         else
2095a1401a75SPierre Schweitzer         {
2096c2c66affSColin Finck             Status = IoQueryFileInformation(FileObject,
2097c2c66affSColin Finck                                             FileNameInformation,
2098c2c66affSColin Finck                                             LengthMismatch ? Length : FileLength,
2099c2c66affSColin Finck                                             LocalFileInfo,
2100c2c66affSColin Finck                                             &LocalReturnLength);
2101a1401a75SPierre Schweitzer         }
2102c2c66affSColin Finck         if (NT_ERROR(Status))
2103c2c66affSColin Finck         {
2104769157f6SPierre Schweitzer             /* Allow status that would mean it's not implemented in the storage stack */
2105769157f6SPierre Schweitzer             if (Status != STATUS_INVALID_PARAMETER && Status != STATUS_INVALID_DEVICE_REQUEST &&
2106769157f6SPierre Schweitzer                 Status != STATUS_NOT_IMPLEMENTED && Status != STATUS_INVALID_INFO_CLASS)
2107769157f6SPierre Schweitzer             {
2108d8f22735SPierre Schweitzer                 _SEH2_LEAVE;
2109c2c66affSColin Finck             }
2110c2c66affSColin Finck 
2111*6363f782SHermès Bélusca-Maïto             /* In such case, zero the output and reset the status */
2112769157f6SPierre Schweitzer             LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2113769157f6SPierre Schweitzer             LocalFileInfo->FileNameLength = 0;
2114769157f6SPierre Schweitzer             LocalFileInfo->FileName[0] = OBJ_NAME_PATH_SEPARATOR;
2115*6363f782SHermès Bélusca-Maïto             Status = STATUS_SUCCESS;
2116769157f6SPierre Schweitzer         }
2117769157f6SPierre Schweitzer         else
2118769157f6SPierre Schweitzer         {
2119769157f6SPierre Schweitzer             /* We'll at least return the name length */
2120769157f6SPierre Schweitzer             if (LocalReturnLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName))
2121769157f6SPierre Schweitzer             {
2122769157f6SPierre Schweitzer                 LocalReturnLength = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2123769157f6SPierre Schweitzer             }
2124769157f6SPierre Schweitzer         }
2125769157f6SPierre Schweitzer 
2126c2c66affSColin Finck         /* If the provided buffer is too small, return the required size */
2127c2c66affSColin Finck         if (LengthMismatch)
2128c2c66affSColin Finck         {
2129c2c66affSColin Finck             /* Add the required length */
2130c2c66affSColin Finck             *ReturnLength += LocalFileInfo->FileNameLength;
2131c2c66affSColin Finck 
2132c2c66affSColin Finck             /* Free the allocated buffer and return failure */
2133d8f22735SPierre Schweitzer             Status = STATUS_BUFFER_OVERFLOW;
2134d8f22735SPierre Schweitzer             _SEH2_LEAVE;
2135c2c66affSColin Finck         }
2136c2c66affSColin Finck 
2137c2c66affSColin Finck         /* Now calculate the new lengths left */
2138c2c66affSColin Finck         FileLength = LocalReturnLength -
2139c2c66affSColin Finck                      FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
2140c2c66affSColin Finck         LocalReturnLength = (ULONG)((ULONG_PTR)p -
2141c2c66affSColin Finck                                     (ULONG_PTR)ObjectNameInfo +
2142c2c66affSColin Finck                                     LocalFileInfo->FileNameLength);
2143c2c66affSColin Finck 
214446bda8a4SPierre Schweitzer         /* Don't copy the name if it's not valid */
214546bda8a4SPierre Schweitzer         if (LocalFileInfo->FileName[0] != OBJ_NAME_PATH_SEPARATOR)
214646bda8a4SPierre Schweitzer         {
214746bda8a4SPierre Schweitzer             /* Free the allocated buffer and return failure */
2148d8f22735SPierre Schweitzer             Status = STATUS_OBJECT_PATH_INVALID;
2149d8f22735SPierre Schweitzer             _SEH2_LEAVE;
215046bda8a4SPierre Schweitzer         }
215146bda8a4SPierre Schweitzer 
2152c2c66affSColin Finck         /* Write the Name and null-terminate it */
2153c2c66affSColin Finck         RtlCopyMemory(p, LocalFileInfo->FileName, FileLength);
2154c2c66affSColin Finck         p += (FileLength / sizeof(WCHAR));
2155c2c66affSColin Finck         *p = UNICODE_NULL;
2156c2c66affSColin Finck         LocalReturnLength += sizeof(UNICODE_NULL);
2157c2c66affSColin Finck 
2158c2c66affSColin Finck         /* Return the length needed */
2159c2c66affSColin Finck         *ReturnLength = LocalReturnLength;
2160c2c66affSColin Finck 
2161c2c66affSColin Finck         /* Setup the length and maximum length */
2162c2c66affSColin Finck         FileLength = (ULONG)((ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo);
2163c2c66affSColin Finck         ObjectNameInfo->Name.Length = (USHORT)FileLength -
2164c2c66affSColin Finck                                               sizeof(OBJECT_NAME_INFORMATION);
2165c2c66affSColin Finck         ObjectNameInfo->Name.MaximumLength = (USHORT)ObjectNameInfo->Name.Length +
2166c2c66affSColin Finck                                                      sizeof(UNICODE_NULL);
2167d8f22735SPierre Schweitzer     }
2168d8f22735SPierre Schweitzer     _SEH2_FINALLY
2169d8f22735SPierre Schweitzer     {
2170c2c66affSColin Finck         /* Free buffer and return */
2171c2c66affSColin Finck         ExFreePoolWithTag(LocalInfo, TAG_IO);
2172d8f22735SPierre Schweitzer     } _SEH2_END;
2173d8f22735SPierre Schweitzer 
2174c2c66affSColin Finck     return Status;
2175c2c66affSColin Finck }
2176c2c66affSColin Finck 
2177c2c66affSColin Finck VOID
2178c2c66affSColin Finck NTAPI
IopCloseFile(IN PEPROCESS Process OPTIONAL,IN PVOID ObjectBody,IN ACCESS_MASK GrantedAccess,IN ULONG HandleCount,IN ULONG SystemHandleCount)2179c2c66affSColin Finck IopCloseFile(IN PEPROCESS Process OPTIONAL,
2180c2c66affSColin Finck              IN PVOID ObjectBody,
2181c2c66affSColin Finck              IN ACCESS_MASK GrantedAccess,
2182c2c66affSColin Finck              IN ULONG HandleCount,
2183c2c66affSColin Finck              IN ULONG SystemHandleCount)
2184c2c66affSColin Finck {
2185c2c66affSColin Finck     PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
2186c2c66affSColin Finck     KEVENT Event;
2187c2c66affSColin Finck     PIRP Irp;
2188c2c66affSColin Finck     PIO_STACK_LOCATION StackPtr;
2189c2c66affSColin Finck     NTSTATUS Status;
2190c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject;
2191c2c66affSColin Finck     KIRQL OldIrql;
21925472c1dbSPierre Schweitzer     IO_STATUS_BLOCK IoStatusBlock;
2193c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
2194c2c66affSColin Finck 
2195c2c66affSColin Finck     /* If this isn't the last handle for the current process, quit */
2196c2c66affSColin Finck     if (HandleCount != 1) return;
2197c2c66affSColin Finck 
2198c2c66affSColin Finck     /* Check if the file is locked and has more then one handle opened */
2199c2c66affSColin Finck     if ((FileObject->LockOperation) && (SystemHandleCount != 1))
2200c2c66affSColin Finck     {
22015472c1dbSPierre Schweitzer         /* Check if this is a direct open or not */
22025472c1dbSPierre Schweitzer         if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN))
22035472c1dbSPierre Schweitzer         {
22045472c1dbSPierre Schweitzer             /* Get the attached device */
22055472c1dbSPierre Schweitzer             DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
22065472c1dbSPierre Schweitzer         }
22075472c1dbSPierre Schweitzer         else
22085472c1dbSPierre Schweitzer         {
22095472c1dbSPierre Schweitzer             /* Get the FO's device */
22105472c1dbSPierre Schweitzer             DeviceObject = IoGetRelatedDeviceObject(FileObject);
22115472c1dbSPierre Schweitzer         }
22125472c1dbSPierre Schweitzer 
22135472c1dbSPierre Schweitzer         /* Check if this is a sync FO and lock it */
22145472c1dbSPierre Schweitzer         if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
22155472c1dbSPierre Schweitzer         {
22168fbc4880SThomas Faber             (VOID)IopLockFileObject(FileObject, KernelMode);
22175472c1dbSPierre Schweitzer         }
22185472c1dbSPierre Schweitzer 
22195472c1dbSPierre Schweitzer         /* Go the FastIO path if possible, otherwise fall back to IRP */
22205472c1dbSPierre Schweitzer         if (DeviceObject->DriverObject->FastIoDispatch == NULL ||
22215472c1dbSPierre Schweitzer             DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL ||
22225472c1dbSPierre Schweitzer             !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject))
22235472c1dbSPierre Schweitzer         {
22245472c1dbSPierre Schweitzer             /* Clear and set up Events */
22255472c1dbSPierre Schweitzer             KeClearEvent(&FileObject->Event);
22265472c1dbSPierre Schweitzer             KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
22275472c1dbSPierre Schweitzer 
22285472c1dbSPierre Schweitzer             /* Allocate an IRP */
22295472c1dbSPierre Schweitzer             Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
22305472c1dbSPierre Schweitzer 
22315472c1dbSPierre Schweitzer             /* Set it up */
22325472c1dbSPierre Schweitzer             Irp->UserEvent = &Event;
22335472c1dbSPierre Schweitzer             Irp->UserIosb = &Irp->IoStatus;
22345472c1dbSPierre Schweitzer             Irp->Tail.Overlay.Thread = PsGetCurrentThread();
22355472c1dbSPierre Schweitzer             Irp->Tail.Overlay.OriginalFileObject = FileObject;
22365472c1dbSPierre Schweitzer             Irp->RequestorMode = KernelMode;
22375472c1dbSPierre Schweitzer             Irp->Flags = IRP_SYNCHRONOUS_API;
22385472c1dbSPierre Schweitzer             Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
2239207ff944SPierre Schweitzer             ObReferenceObject(FileObject);
22405472c1dbSPierre Schweitzer 
22415472c1dbSPierre Schweitzer             /* Set up Stack Pointer Data */
22425472c1dbSPierre Schweitzer             StackPtr = IoGetNextIrpStackLocation(Irp);
22435472c1dbSPierre Schweitzer             StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
22445472c1dbSPierre Schweitzer             StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL;
22455472c1dbSPierre Schweitzer             StackPtr->FileObject = FileObject;
22465472c1dbSPierre Schweitzer 
22475472c1dbSPierre Schweitzer             /* Queue the IRP */
22485472c1dbSPierre Schweitzer             IopQueueIrpToThread(Irp);
22495472c1dbSPierre Schweitzer 
22505472c1dbSPierre Schweitzer             /* Call the FS Driver */
22515472c1dbSPierre Schweitzer             Status = IoCallDriver(DeviceObject, Irp);
22525472c1dbSPierre Schweitzer             if (Status == STATUS_PENDING)
22535472c1dbSPierre Schweitzer             {
22545472c1dbSPierre Schweitzer                 /* Wait for completion */
22555472c1dbSPierre Schweitzer                 KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
22565472c1dbSPierre Schweitzer             }
22575472c1dbSPierre Schweitzer 
22585472c1dbSPierre Schweitzer             /* IO will unqueue & free for us */
22595472c1dbSPierre Schweitzer         }
22605472c1dbSPierre Schweitzer 
22615472c1dbSPierre Schweitzer         /* Release the lock if we were holding it */
22625472c1dbSPierre Schweitzer         if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
22635472c1dbSPierre Schweitzer         {
22645472c1dbSPierre Schweitzer             IopUnlockFileObject(FileObject);
22655472c1dbSPierre Schweitzer         }
2266c2c66affSColin Finck     }
2267c2c66affSColin Finck 
2268c2c66affSColin Finck     /* Make sure this is the last handle */
2269c2c66affSColin Finck     if (SystemHandleCount != 1) return;
2270c2c66affSColin Finck 
2271c2c66affSColin Finck     /* Check if this is a direct open or not */
2272c2c66affSColin Finck     if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
2273c2c66affSColin Finck     {
2274c2c66affSColin Finck         /* Get the attached device */
2275c2c66affSColin Finck         DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
2276c2c66affSColin Finck     }
2277c2c66affSColin Finck     else
2278c2c66affSColin Finck     {
2279c2c66affSColin Finck         /* Get the FO's device */
2280c2c66affSColin Finck         DeviceObject = IoGetRelatedDeviceObject(FileObject);
2281c2c66affSColin Finck     }
2282c2c66affSColin Finck 
2283c2c66affSColin Finck     /* Set the handle created flag */
2284c2c66affSColin Finck     FileObject->Flags |= FO_HANDLE_CREATED;
2285c2c66affSColin Finck 
2286c2c66affSColin Finck     /* Check if this is a sync FO and lock it */
2287cf25432eSPierre Schweitzer     if (Process != NULL &&
2288cf25432eSPierre Schweitzer         BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
2289cf25432eSPierre Schweitzer     {
22908fbc4880SThomas Faber         (VOID)IopLockFileObject(FileObject, KernelMode);
2291cf25432eSPierre Schweitzer     }
2292c2c66affSColin Finck 
2293c2c66affSColin Finck     /* Clear and set up Events */
2294c2c66affSColin Finck     KeClearEvent(&FileObject->Event);
2295c2c66affSColin Finck     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
2296c2c66affSColin Finck 
2297c2c66affSColin Finck     /* Allocate an IRP */
2298c2c66affSColin Finck     Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
2299c2c66affSColin Finck 
2300c2c66affSColin Finck     /* Set it up */
2301c2c66affSColin Finck     Irp->UserEvent = &Event;
2302c2c66affSColin Finck     Irp->UserIosb = &Irp->IoStatus;
2303c2c66affSColin Finck     Irp->Tail.Overlay.Thread = PsGetCurrentThread();
2304c2c66affSColin Finck     Irp->Tail.Overlay.OriginalFileObject = FileObject;
2305c2c66affSColin Finck     Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
2306c2c66affSColin Finck     Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
2307c2c66affSColin Finck 
2308c2c66affSColin Finck     /* Set up Stack Pointer Data */
2309c2c66affSColin Finck     StackPtr = IoGetNextIrpStackLocation(Irp);
2310c2c66affSColin Finck     StackPtr->MajorFunction = IRP_MJ_CLEANUP;
2311c2c66affSColin Finck     StackPtr->FileObject = FileObject;
2312c2c66affSColin Finck 
2313c2c66affSColin Finck     /* Queue the IRP */
2314c2c66affSColin Finck     IopQueueIrpToThread(Irp);
2315c2c66affSColin Finck 
2316c2c66affSColin Finck     /* Update operation counts */
2317c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
2318c2c66affSColin Finck 
2319c2c66affSColin Finck     /* Call the FS Driver */
2320c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
2321c2c66affSColin Finck     if (Status == STATUS_PENDING)
2322c2c66affSColin Finck     {
2323c2c66affSColin Finck         /* Wait for completion */
2324c2c66affSColin Finck         KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
2325c2c66affSColin Finck     }
2326c2c66affSColin Finck 
2327c2c66affSColin Finck     /* Unqueue the IRP */
2328c2c66affSColin Finck     KeRaiseIrql(APC_LEVEL, &OldIrql);
2329c2c66affSColin Finck     IopUnQueueIrpFromThread(Irp);
2330c2c66affSColin Finck     KeLowerIrql(OldIrql);
2331c2c66affSColin Finck 
2332c2c66affSColin Finck     /* Free the IRP */
2333c2c66affSColin Finck     IoFreeIrp(Irp);
2334c2c66affSColin Finck 
2335c2c66affSColin Finck     /* Release the lock if we were holding it */
2336cf25432eSPierre Schweitzer     if (Process != NULL &&
2337cf25432eSPierre Schweitzer         BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
2338cf25432eSPierre Schweitzer     {
2339cf25432eSPierre Schweitzer         IopUnlockFileObject(FileObject);
2340cf25432eSPierre Schweitzer     }
2341c2c66affSColin Finck }
2342c2c66affSColin Finck 
2343c2c66affSColin Finck NTSTATUS
2344c2c66affSColin Finck NTAPI
IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,IN FILE_INFORMATION_CLASS FileInformationClass,IN ULONG FileInformationSize,OUT PVOID FileInformation)2345c2c66affSColin Finck IopQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
2346c2c66affSColin Finck                        IN FILE_INFORMATION_CLASS FileInformationClass,
2347c2c66affSColin Finck                        IN ULONG FileInformationSize,
2348c2c66affSColin Finck                        OUT PVOID FileInformation)
2349c2c66affSColin Finck {
2350c2c66affSColin Finck     NTSTATUS Status;
2351c2c66affSColin Finck     KPROCESSOR_MODE AccessMode = ExGetPreviousMode();
2352c2c66affSColin Finck     DUMMY_FILE_OBJECT LocalFileObject;
2353c2c66affSColin Finck     FILE_NETWORK_OPEN_INFORMATION NetworkOpenInfo;
2354c2c66affSColin Finck     HANDLE Handle;
2355c2c66affSColin Finck     OPEN_PACKET OpenPacket;
2356c2c66affSColin Finck     BOOLEAN IsBasic;
2357c2c66affSColin Finck     PAGED_CODE();
2358c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "Class: %lx\n", FileInformationClass);
2359c2c66affSColin Finck 
2360c2c66affSColin Finck     /* Check if the caller was user mode */
2361c2c66affSColin Finck     if (AccessMode != KernelMode)
2362c2c66affSColin Finck     {
2363c2c66affSColin Finck         /* Protect probe in SEH */
2364c2c66affSColin Finck         _SEH2_TRY
2365c2c66affSColin Finck         {
2366c2c66affSColin Finck             /* Probe the buffer */
2367c2c66affSColin Finck             ProbeForWrite(FileInformation, FileInformationSize, sizeof(ULONG));
2368c2c66affSColin Finck         }
2369c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2370c2c66affSColin Finck         {
2371c2c66affSColin Finck             /* Return the exception code */
2372c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
2373c2c66affSColin Finck         }
2374c2c66affSColin Finck         _SEH2_END;
2375c2c66affSColin Finck     }
2376c2c66affSColin Finck 
2377c2c66affSColin Finck     /* Check if this is a basic or full request */
2378c2c66affSColin Finck     IsBasic = (FileInformationSize == sizeof(FILE_BASIC_INFORMATION));
2379c2c66affSColin Finck 
2380c2c66affSColin Finck     /* Setup the Open Packet */
2381c2c66affSColin Finck     RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
2382c2c66affSColin Finck     OpenPacket.Type = IO_TYPE_OPEN_PACKET;
2383c2c66affSColin Finck     OpenPacket.Size = sizeof(OPEN_PACKET);
2384c2c66affSColin Finck     OpenPacket.CreateOptions = FILE_OPEN_REPARSE_POINT;
2385c2c66affSColin Finck     OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
2386c2c66affSColin Finck     OpenPacket.Disposition = FILE_OPEN;
2387c2c66affSColin Finck     OpenPacket.BasicInformation = IsBasic ? FileInformation : NULL;
2388c2c66affSColin Finck     OpenPacket.NetworkInformation = IsBasic ? &NetworkOpenInfo :
2389c2c66affSColin Finck                                     (AccessMode != KernelMode) ?
2390c2c66affSColin Finck                                     &NetworkOpenInfo : FileInformation;
2391c2c66affSColin Finck     OpenPacket.QueryOnly = TRUE;
2392c2c66affSColin Finck     OpenPacket.FullAttributes = IsBasic ? FALSE : TRUE;
2393c2c66affSColin Finck     OpenPacket.LocalFileObject = &LocalFileObject;
2394c2c66affSColin Finck 
2395c2c66affSColin Finck     /* Update the operation count */
2396c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
2397c2c66affSColin Finck 
2398c2c66affSColin Finck     /*
2399c2c66affSColin Finck      * Attempt opening the file. This will call the I/O Parse Routine for
2400c2c66affSColin Finck      * the File Object (IopParseDevice) which will use the dummy file obejct
2401c2c66affSColin Finck      * send the IRP to its device object. Note that we have two statuses
2402c2c66affSColin Finck      * to worry about: the Object Manager's status (in Status) and the I/O
2403c2c66affSColin Finck      * status, which is in the Open Packet's Final Status, and determined
2404c2c66affSColin Finck      * by the Parse Check member.
2405c2c66affSColin Finck      */
2406c2c66affSColin Finck     Status = ObOpenObjectByName(ObjectAttributes,
2407c2c66affSColin Finck                                 NULL,
2408c2c66affSColin Finck                                 AccessMode,
2409c2c66affSColin Finck                                 NULL,
2410c2c66affSColin Finck                                 FILE_READ_ATTRIBUTES,
2411c2c66affSColin Finck                                 &OpenPacket,
2412c2c66affSColin Finck                                 &Handle);
2413c2c66affSColin Finck     if (OpenPacket.ParseCheck == FALSE)
2414c2c66affSColin Finck     {
2415c2c66affSColin Finck         /* Parse failed */
2416c2c66affSColin Finck         DPRINT("IopQueryAttributesFile failed for '%wZ' with 0x%lx\n",
2417c2c66affSColin Finck                ObjectAttributes->ObjectName, Status);
2418c2c66affSColin Finck         return Status;
2419c2c66affSColin Finck     }
2420c2c66affSColin Finck     else
2421c2c66affSColin Finck     {
2422c2c66affSColin Finck         /* Use the Io status */
2423c2c66affSColin Finck         Status = OpenPacket.FinalStatus;
2424c2c66affSColin Finck     }
2425c2c66affSColin Finck 
2426c2c66affSColin Finck     /* Check if we were succesful and this was user mode and a full query */
2427c2c66affSColin Finck     if ((NT_SUCCESS(Status)) && (AccessMode != KernelMode) && !(IsBasic))
2428c2c66affSColin Finck     {
2429c2c66affSColin Finck         /* Enter SEH for copy */
2430c2c66affSColin Finck         _SEH2_TRY
2431c2c66affSColin Finck         {
2432c2c66affSColin Finck             /* Copy the buffer back */
2433c2c66affSColin Finck             RtlCopyMemory(FileInformation,
2434c2c66affSColin Finck                           &NetworkOpenInfo,
2435c2c66affSColin Finck                           FileInformationSize);
2436c2c66affSColin Finck         }
2437c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2438c2c66affSColin Finck         {
2439c2c66affSColin Finck             /* Get exception code */
2440c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
2441c2c66affSColin Finck         }
2442c2c66affSColin Finck         _SEH2_END;
2443c2c66affSColin Finck     }
2444c2c66affSColin Finck 
2445c2c66affSColin Finck     /* Return status */
2446c2c66affSColin Finck     return Status;
2447c2c66affSColin Finck }
2448c2c66affSColin Finck 
24498fbc4880SThomas Faber NTSTATUS
24508fbc4880SThomas Faber NTAPI
IopAcquireFileObjectLock(_In_ PFILE_OBJECT FileObject,_In_ KPROCESSOR_MODE WaitMode,_In_ BOOLEAN Alertable,_Out_ PBOOLEAN LockFailed)24518fbc4880SThomas Faber IopAcquireFileObjectLock(
24528fbc4880SThomas Faber     _In_ PFILE_OBJECT FileObject,
24538fbc4880SThomas Faber     _In_ KPROCESSOR_MODE WaitMode,
24548fbc4880SThomas Faber     _In_ BOOLEAN Alertable,
24558fbc4880SThomas Faber     _Out_ PBOOLEAN LockFailed)
24568fbc4880SThomas Faber {
24578fbc4880SThomas Faber     NTSTATUS Status;
24588fbc4880SThomas Faber 
24598fbc4880SThomas Faber     PAGED_CODE();
24608fbc4880SThomas Faber 
24618fbc4880SThomas Faber     InterlockedIncrement((PLONG)&FileObject->Waiters);
24628fbc4880SThomas Faber 
24638fbc4880SThomas Faber     Status = STATUS_SUCCESS;
24648fbc4880SThomas Faber     do
24658fbc4880SThomas Faber     {
24668fbc4880SThomas Faber         if (!InterlockedExchange((PLONG)&FileObject->Busy, TRUE))
24678fbc4880SThomas Faber         {
24688fbc4880SThomas Faber             break;
24698fbc4880SThomas Faber         }
24708fbc4880SThomas Faber         Status = KeWaitForSingleObject(&FileObject->Lock,
24718fbc4880SThomas Faber                                        Executive,
24728fbc4880SThomas Faber                                        WaitMode,
24738fbc4880SThomas Faber                                        Alertable,
24748fbc4880SThomas Faber                                        NULL);
24758fbc4880SThomas Faber     } while (Status == STATUS_SUCCESS);
24768fbc4880SThomas Faber 
24778fbc4880SThomas Faber     InterlockedDecrement((PLONG)&FileObject->Waiters);
24788fbc4880SThomas Faber     if (Status == STATUS_SUCCESS)
24798fbc4880SThomas Faber     {
24808fbc4880SThomas Faber         ObReferenceObject(FileObject);
24818fbc4880SThomas Faber         *LockFailed = FALSE;
24828fbc4880SThomas Faber     }
24838fbc4880SThomas Faber     else
24848fbc4880SThomas Faber     {
24858fbc4880SThomas Faber         if (!FileObject->Busy && FileObject->Waiters)
24868fbc4880SThomas Faber         {
24878fbc4880SThomas Faber             KeSetEvent(&FileObject->Lock, IO_NO_INCREMENT, FALSE);
24888fbc4880SThomas Faber         }
24898fbc4880SThomas Faber         *LockFailed = TRUE;
24908fbc4880SThomas Faber     }
24918fbc4880SThomas Faber 
24928fbc4880SThomas Faber     return Status;
24938fbc4880SThomas Faber }
24948fbc4880SThomas Faber 
2495c2c66affSColin Finck PVOID
2496c2c66affSColin Finck NTAPI
IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)2497c2c66affSColin Finck IoGetFileObjectFilterContext(IN PFILE_OBJECT FileObject)
2498c2c66affSColin Finck {
24992a182931SPierre Schweitzer     if (BooleanFlagOn(FileObject->Flags, FO_FILE_OBJECT_HAS_EXTENSION))
2500c2c66affSColin Finck     {
2501a43fb5e0SPierre Schweitzer         PFILE_OBJECT_EXTENSION FileObjectExtension;
2502a43fb5e0SPierre Schweitzer 
2503a43fb5e0SPierre Schweitzer         FileObjectExtension = FileObject->FileObjectExtension;
2504a43fb5e0SPierre Schweitzer         return FileObjectExtension->FilterContext;
2505c2c66affSColin Finck     }
2506c2c66affSColin Finck 
2507c2c66affSColin Finck     return NULL;
2508c2c66affSColin Finck }
2509c2c66affSColin Finck 
2510c2c66affSColin Finck NTSTATUS
2511c2c66affSColin Finck NTAPI
IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject,IN PVOID FilterContext,IN BOOLEAN Define)2512c2c66affSColin Finck IoChangeFileObjectFilterContext(IN PFILE_OBJECT FileObject,
2513c2c66affSColin Finck                                 IN PVOID FilterContext,
2514c2c66affSColin Finck                                 IN BOOLEAN Define)
2515c2c66affSColin Finck {
25165f0d02ebSPierre Schweitzer     ULONG_PTR Success;
25175f0d02ebSPierre Schweitzer     PFILE_OBJECT_EXTENSION FileObjectExtension;
25185f0d02ebSPierre Schweitzer 
25192a182931SPierre Schweitzer     if (!BooleanFlagOn(FileObject->Flags, FO_FILE_OBJECT_HAS_EXTENSION))
2520c2c66affSColin Finck     {
2521c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
2522c2c66affSColin Finck     }
2523c2c66affSColin Finck 
25245f0d02ebSPierre Schweitzer     FileObjectExtension = FileObject->FileObjectExtension;
25255f0d02ebSPierre Schweitzer     if (Define)
25265f0d02ebSPierre Schweitzer     {
25275f0d02ebSPierre Schweitzer         /* If define, just set the new value if not value is set
25285f0d02ebSPierre Schweitzer          * Success will only contain old value. It is valid if it is NULL
25295f0d02ebSPierre Schweitzer          */
25302a182931SPierre Schweitzer         Success = (ULONG_PTR)InterlockedCompareExchangePointer(&FileObjectExtension->FilterContext, FilterContext, NULL);
25315f0d02ebSPierre Schweitzer     }
25325f0d02ebSPierre Schweitzer     else
25335f0d02ebSPierre Schweitzer     {
25345f0d02ebSPierre Schweitzer         /* If not define, we want to reset filter context.
25355f0d02ebSPierre Schweitzer          * We will remove value (provided by the caller) and set NULL instead.
25365f0d02ebSPierre Schweitzer          * This will only success if caller provides correct previous value.
25375f0d02ebSPierre Schweitzer          * To catch whether it worked, we substract previous value to expect value:
25385f0d02ebSPierre Schweitzer          * If it matches (and thus, we reset), Success will contain 0
25395f0d02ebSPierre Schweitzer          * Otherwise, it will contain a non-zero value.
25405f0d02ebSPierre Schweitzer          */
25412a182931SPierre Schweitzer         Success = (ULONG_PTR)InterlockedCompareExchangePointer(&FileObjectExtension->FilterContext, NULL, FilterContext) - (ULONG_PTR)FilterContext;
25425f0d02ebSPierre Schweitzer     }
2543c2c66affSColin Finck 
25445f0d02ebSPierre Schweitzer     /* If success isn't 0, it means we failed somewhere (set or unset) */
25455f0d02ebSPierre Schweitzer     if (Success != 0)
25465f0d02ebSPierre Schweitzer     {
25475f0d02ebSPierre Schweitzer         return STATUS_ALREADY_COMMITTED;
25485f0d02ebSPierre Schweitzer     }
25495f0d02ebSPierre Schweitzer 
25505f0d02ebSPierre Schweitzer     return STATUS_SUCCESS;
2551c2c66affSColin Finck }
2552c2c66affSColin Finck 
2553c2c66affSColin Finck NTSTATUS
2554c2c66affSColin Finck NTAPI
IopCreateFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PLARGE_INTEGER AllocationSize OPTIONAL,IN ULONG FileAttributes,IN ULONG ShareAccess,IN ULONG Disposition,IN ULONG CreateOptions,IN PVOID EaBuffer OPTIONAL,IN ULONG EaLength,IN CREATE_FILE_TYPE CreateFileType,IN PVOID ExtraCreateParameters OPTIONAL,IN ULONG Options,IN ULONG Flags,IN PDEVICE_OBJECT DeviceObject OPTIONAL)2555c2c66affSColin Finck IopCreateFile(OUT PHANDLE FileHandle,
2556c2c66affSColin Finck               IN ACCESS_MASK DesiredAccess,
2557c2c66affSColin Finck               IN POBJECT_ATTRIBUTES ObjectAttributes,
2558c2c66affSColin Finck               OUT PIO_STATUS_BLOCK IoStatusBlock,
2559c2c66affSColin Finck               IN PLARGE_INTEGER AllocationSize OPTIONAL,
2560c2c66affSColin Finck               IN ULONG FileAttributes,
2561c2c66affSColin Finck               IN ULONG ShareAccess,
2562c2c66affSColin Finck               IN ULONG Disposition,
2563c2c66affSColin Finck               IN ULONG CreateOptions,
2564c2c66affSColin Finck               IN PVOID EaBuffer OPTIONAL,
2565c2c66affSColin Finck               IN ULONG EaLength,
2566c2c66affSColin Finck               IN CREATE_FILE_TYPE CreateFileType,
2567c2c66affSColin Finck               IN PVOID ExtraCreateParameters OPTIONAL,
2568c2c66affSColin Finck               IN ULONG Options,
2569c2c66affSColin Finck               IN ULONG Flags,
2570c2c66affSColin Finck               IN PDEVICE_OBJECT DeviceObject OPTIONAL)
2571c2c66affSColin Finck {
2572c2c66affSColin Finck     KPROCESSOR_MODE AccessMode;
2573c2c66affSColin Finck     HANDLE LocalHandle = 0;
2574c2c66affSColin Finck     LARGE_INTEGER SafeAllocationSize;
2575c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
2576c2c66affSColin Finck     PNAMED_PIPE_CREATE_PARAMETERS NamedPipeCreateParameters;
2577c2c66affSColin Finck     POPEN_PACKET OpenPacket;
2578c2c66affSColin Finck     ULONG EaErrorOffset;
2579c2c66affSColin Finck     PAGED_CODE();
2580c2c66affSColin Finck 
2581c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
2582c2c66affSColin Finck 
2583c2c66affSColin Finck 
2584c2c66affSColin Finck     /* Check if we have no parameter checking to do */
2585c2c66affSColin Finck     if (Options & IO_NO_PARAMETER_CHECKING)
2586c2c66affSColin Finck     {
2587c2c66affSColin Finck         /* Then force kernel-mode access to avoid checks */
2588c2c66affSColin Finck         AccessMode = KernelMode;
2589c2c66affSColin Finck     }
2590c2c66affSColin Finck     else
2591c2c66affSColin Finck     {
2592c2c66affSColin Finck         /* Otherwise, use the actual mode */
2593c2c66affSColin Finck         AccessMode = ExGetPreviousMode();
2594c2c66affSColin Finck     }
2595c2c66affSColin Finck 
2596c2c66affSColin Finck     /* Check if we need to do parameter checking */
2597c2c66affSColin Finck     if ((AccessMode != KernelMode) || (Options & IO_CHECK_CREATE_PARAMETERS))
2598c2c66affSColin Finck     {
2599c2c66affSColin Finck         /* Validate parameters */
2600c2c66affSColin Finck         if (FileAttributes & ~FILE_ATTRIBUTE_VALID_FLAGS)
2601c2c66affSColin Finck         {
2602c2c66affSColin Finck             DPRINT1("File Create 'FileAttributes' Parameter contains invalid flags!\n");
2603c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2604c2c66affSColin Finck         }
2605c2c66affSColin Finck 
2606c2c66affSColin Finck         if (ShareAccess & ~FILE_SHARE_VALID_FLAGS)
2607c2c66affSColin Finck         {
2608c2c66affSColin Finck             DPRINT1("File Create 'ShareAccess' Parameter contains invalid flags!\n");
2609c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2610c2c66affSColin Finck         }
2611c2c66affSColin Finck 
2612c2c66affSColin Finck         if (Disposition > FILE_MAXIMUM_DISPOSITION)
2613c2c66affSColin Finck         {
2614c2c66affSColin Finck             DPRINT1("File Create 'Disposition' Parameter is out of range!\n");
2615c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2616c2c66affSColin Finck         }
2617c2c66affSColin Finck 
2618c2c66affSColin Finck         if (CreateOptions & ~FILE_VALID_OPTION_FLAGS)
2619c2c66affSColin Finck         {
2620c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' parameter contains invalid flags!\n");
2621c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2622c2c66affSColin Finck         }
2623c2c66affSColin Finck 
2624c2c66affSColin Finck         if ((CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) &&
2625c2c66affSColin Finck             (!(DesiredAccess & SYNCHRONIZE)))
2626c2c66affSColin Finck         {
2627c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' parameter FILE_SYNCHRONOUS_IO_* requested, but 'DesiredAccess' does not have SYNCHRONIZE!\n");
2628c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2629c2c66affSColin Finck         }
2630c2c66affSColin Finck 
2631c2c66affSColin Finck         if ((CreateOptions & FILE_DELETE_ON_CLOSE) && (!(DesiredAccess & DELETE)))
2632c2c66affSColin Finck         {
2633c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' parameter FILE_DELETE_ON_CLOSE requested, but 'DesiredAccess' does not have DELETE!\n");
2634c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2635c2c66affSColin Finck         }
2636c2c66affSColin Finck 
2637c2c66affSColin Finck         if ((CreateOptions & (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT)) ==
2638c2c66affSColin Finck             (FILE_SYNCHRONOUS_IO_NONALERT | FILE_SYNCHRONOUS_IO_ALERT))
2639c2c66affSColin Finck         {
2640c2c66affSColin Finck             DPRINT1("File Create 'FileAttributes' parameter both FILE_SYNCHRONOUS_IO_NONALERT and FILE_SYNCHRONOUS_IO_ALERT specified!\n");
2641c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2642c2c66affSColin Finck         }
2643c2c66affSColin Finck 
2644c2c66affSColin Finck         if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) &&
2645c2c66affSColin Finck             (CreateOptions & ~(FILE_DIRECTORY_FILE |
2646c2c66affSColin Finck                                FILE_SYNCHRONOUS_IO_ALERT |
2647c2c66affSColin Finck                                FILE_SYNCHRONOUS_IO_NONALERT |
2648c2c66affSColin Finck                                FILE_WRITE_THROUGH |
2649c2c66affSColin Finck                                FILE_COMPLETE_IF_OPLOCKED |
2650c2c66affSColin Finck                                FILE_OPEN_FOR_BACKUP_INTENT |
2651c2c66affSColin Finck                                FILE_DELETE_ON_CLOSE |
2652c2c66affSColin Finck                                FILE_OPEN_FOR_FREE_SPACE_QUERY |
2653c2c66affSColin Finck                                FILE_OPEN_BY_FILE_ID |
2654c2c66affSColin Finck                                FILE_NO_COMPRESSION |
2655c2c66affSColin Finck                                FILE_OPEN_REPARSE_POINT)))
2656c2c66affSColin Finck         {
2657c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' Parameter has flags incompatible with FILE_DIRECTORY_FILE!\n");
2658c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2659c2c66affSColin Finck         }
2660c2c66affSColin Finck 
2661c2c66affSColin Finck         if ((CreateOptions & FILE_DIRECTORY_FILE) && !(CreateOptions & FILE_NON_DIRECTORY_FILE) &&
2662c2c66affSColin Finck             (Disposition != FILE_CREATE) && (Disposition != FILE_OPEN) && (Disposition != FILE_OPEN_IF))
2663c2c66affSColin Finck         {
2664c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' Parameter FILE_DIRECTORY_FILE requested, but 'Disposition' is not FILE_CREATE/FILE_OPEN/FILE_OPEN_IF!\n");
2665c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2666c2c66affSColin Finck         }
2667c2c66affSColin Finck 
2668c2c66affSColin Finck         if ((CreateOptions & FILE_COMPLETE_IF_OPLOCKED) && (CreateOptions & FILE_RESERVE_OPFILTER))
2669c2c66affSColin Finck         {
2670c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' Parameter both FILE_COMPLETE_IF_OPLOCKED and FILE_RESERVE_OPFILTER specified!\n");
2671c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2672c2c66affSColin Finck         }
2673c2c66affSColin Finck 
2674c2c66affSColin Finck         if ((CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) && (DesiredAccess & FILE_APPEND_DATA))
2675c2c66affSColin Finck         {
2676c2c66affSColin Finck             DPRINT1("File Create 'CreateOptions' parameter FILE_NO_INTERMEDIATE_BUFFERING requested, but 'DesiredAccess' FILE_APPEND_DATA requires it!\n");
2677c2c66affSColin Finck             return STATUS_INVALID_PARAMETER;
2678c2c66affSColin Finck         }
2679c2c66affSColin Finck 
2680c2c66affSColin Finck         /* Now check if this is a named pipe */
2681c2c66affSColin Finck         if (CreateFileType == CreateFileTypeNamedPipe)
2682c2c66affSColin Finck         {
2683c2c66affSColin Finck             /* Make sure we have extra parameters */
2684c2c66affSColin Finck             if (!ExtraCreateParameters)
2685c2c66affSColin Finck             {
2686c2c66affSColin Finck                 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2687c2c66affSColin Finck                 return STATUS_INVALID_PARAMETER;
2688c2c66affSColin Finck             }
2689c2c66affSColin Finck 
2690c2c66affSColin Finck             /* Get the parameters and validate them */
2691c2c66affSColin Finck             NamedPipeCreateParameters = ExtraCreateParameters;
2692c2c66affSColin Finck             if ((NamedPipeCreateParameters->NamedPipeType > FILE_PIPE_MESSAGE_TYPE) ||
2693c2c66affSColin Finck                 (NamedPipeCreateParameters->ReadMode > FILE_PIPE_MESSAGE_MODE) ||
2694c2c66affSColin Finck                 (NamedPipeCreateParameters->CompletionMode > FILE_PIPE_COMPLETE_OPERATION) ||
2695c2c66affSColin Finck                 (ShareAccess & FILE_SHARE_DELETE) ||
2696c2c66affSColin Finck                 ((Disposition < FILE_OPEN) || (Disposition > FILE_OPEN_IF)) ||
2697c2c66affSColin Finck                 (CreateOptions & ~FILE_VALID_PIPE_OPTION_FLAGS))
2698c2c66affSColin Finck             {
2699c2c66affSColin Finck                 /* Invalid named pipe create */
2700c2c66affSColin Finck                 DPRINT1("Invalid named pipe create\n");
2701c2c66affSColin Finck                 return STATUS_INVALID_PARAMETER;
2702c2c66affSColin Finck             }
2703c2c66affSColin Finck         }
2704c2c66affSColin Finck         else if (CreateFileType == CreateFileTypeMailslot)
2705c2c66affSColin Finck         {
2706c2c66affSColin Finck             /* Make sure we have extra parameters */
2707c2c66affSColin Finck             if (!ExtraCreateParameters)
2708c2c66affSColin Finck             {
2709c2c66affSColin Finck                 DPRINT1("Invalid parameter: ExtraCreateParameters == 0!\n");
2710c2c66affSColin Finck                 return STATUS_INVALID_PARAMETER;
2711c2c66affSColin Finck             }
2712c2c66affSColin Finck 
2713c2c66affSColin Finck             /* Get the parameters and validate them */
2714c2c66affSColin Finck             if ((ShareAccess & FILE_SHARE_DELETE) ||
2715c2c66affSColin Finck                 !(ShareAccess & ~FILE_SHARE_WRITE) ||
2716c2c66affSColin Finck                 (Disposition != FILE_CREATE) ||
2717c2c66affSColin Finck                 (CreateOptions & ~FILE_VALID_MAILSLOT_OPTION_FLAGS))
2718c2c66affSColin Finck             {
2719c2c66affSColin Finck                 /* Invalid mailslot create */
2720c2c66affSColin Finck                 DPRINT1("Invalid mailslot create\n");
2721c2c66affSColin Finck                 return STATUS_INVALID_PARAMETER;
2722c2c66affSColin Finck             }
2723c2c66affSColin Finck         }
2724c2c66affSColin Finck     }
2725c2c66affSColin Finck 
2726c2c66affSColin Finck     /* Allocate the open packet */
2727c2c66affSColin Finck     OpenPacket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*OpenPacket), 'pOoI');
2728c2c66affSColin Finck     if (!OpenPacket) return STATUS_INSUFFICIENT_RESOURCES;
2729c2c66affSColin Finck     RtlZeroMemory(OpenPacket, sizeof(*OpenPacket));
2730c2c66affSColin Finck 
2731c2c66affSColin Finck     /* Check if the call came from user mode */
2732c2c66affSColin Finck     if (AccessMode != KernelMode)
2733c2c66affSColin Finck     {
2734c2c66affSColin Finck         _SEH2_TRY
2735c2c66affSColin Finck         {
2736c2c66affSColin Finck             /* Probe the output parameters */
2737c2c66affSColin Finck             ProbeForWriteHandle(FileHandle);
2738c2c66affSColin Finck             ProbeForWriteIoStatusBlock(IoStatusBlock);
2739c2c66affSColin Finck 
2740c2c66affSColin Finck             /* Probe the allocation size if one was passed in */
2741c2c66affSColin Finck             if (AllocationSize)
2742c2c66affSColin Finck             {
2743c2c66affSColin Finck                 SafeAllocationSize = ProbeForReadLargeInteger(AllocationSize);
2744c2c66affSColin Finck             }
2745c2c66affSColin Finck             else
2746c2c66affSColin Finck             {
2747c2c66affSColin Finck                 SafeAllocationSize.QuadPart = 0;
2748c2c66affSColin Finck             }
2749c2c66affSColin Finck 
2750c2c66affSColin Finck             /* Make sure it's valid */
2751c2c66affSColin Finck             if (SafeAllocationSize.QuadPart < 0)
2752c2c66affSColin Finck             {
2753c2c66affSColin Finck                 RtlRaiseStatus(STATUS_INVALID_PARAMETER);
2754c2c66affSColin Finck             }
2755c2c66affSColin Finck 
2756c2c66affSColin Finck             /* Check if EA was passed in */
2757c2c66affSColin Finck             if ((EaBuffer) && (EaLength))
2758c2c66affSColin Finck             {
2759c2c66affSColin Finck                 /* Probe it */
2760c2c66affSColin Finck                 ProbeForRead(EaBuffer, EaLength, sizeof(ULONG));
2761c2c66affSColin Finck 
2762c2c66affSColin Finck                 /* And marshall it */
2763c2c66affSColin Finck                 OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool,
2764c2c66affSColin Finck                                                              EaLength,
2765c2c66affSColin Finck                                                              TAG_EA);
2766c2c66affSColin Finck                 OpenPacket->EaLength = EaLength;
2767c2c66affSColin Finck                 RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength);
2768c2c66affSColin Finck 
2769c2c66affSColin Finck                 /* Validate the buffer */
2770c2c66affSColin Finck                 Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer,
2771c2c66affSColin Finck                                                  EaLength,
2772c2c66affSColin Finck                                                  &EaErrorOffset);
2773c2c66affSColin Finck                 if (!NT_SUCCESS(Status))
2774c2c66affSColin Finck                 {
2775c2c66affSColin Finck                     /* Undo everything if it's invalid */
2776c2c66affSColin Finck                     DPRINT1("Invalid EA buffer\n");
2777c2c66affSColin Finck                     IoStatusBlock->Status = Status;
2778c2c66affSColin Finck                     IoStatusBlock->Information = EaErrorOffset;
2779c2c66affSColin Finck                     RtlRaiseStatus(Status);
2780c2c66affSColin Finck                 }
2781c2c66affSColin Finck             }
2782c2c66affSColin Finck         }
2783c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2784c2c66affSColin Finck         {
2785c2c66affSColin Finck             /* Return the exception code */
2786c2c66affSColin Finck             if (OpenPacket->EaBuffer != NULL) ExFreePool(OpenPacket->EaBuffer);
2787c2c66affSColin Finck             ExFreePool(OpenPacket);
2788c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
2789c2c66affSColin Finck         }
2790c2c66affSColin Finck         _SEH2_END;
2791c2c66affSColin Finck     }
2792c2c66affSColin Finck     else
2793c2c66affSColin Finck     {
2794c2c66affSColin Finck         /* Check if this is a device attach */
2795c2c66affSColin Finck         if (CreateOptions & IO_ATTACH_DEVICE_API)
2796c2c66affSColin Finck         {
2797c2c66affSColin Finck             /* Set the flag properly */
2798c2c66affSColin Finck             Options |= IO_ATTACH_DEVICE;
2799c2c66affSColin Finck             CreateOptions &= ~IO_ATTACH_DEVICE_API;
2800c2c66affSColin Finck         }
2801c2c66affSColin Finck 
2802c2c66affSColin Finck         /* Check if we have allocation size */
2803c2c66affSColin Finck         if (AllocationSize)
2804c2c66affSColin Finck         {
2805c2c66affSColin Finck             /* Capture it */
2806c2c66affSColin Finck             SafeAllocationSize = *AllocationSize;
2807c2c66affSColin Finck         }
2808c2c66affSColin Finck         else
2809c2c66affSColin Finck         {
2810c2c66affSColin Finck             /* Otherwise, no size */
2811c2c66affSColin Finck             SafeAllocationSize.QuadPart = 0;
2812c2c66affSColin Finck         }
2813c2c66affSColin Finck 
2814c2c66affSColin Finck         /* Check if we have an EA packet */
2815c2c66affSColin Finck         if ((EaBuffer) && (EaLength))
2816c2c66affSColin Finck         {
2817c2c66affSColin Finck             /* Allocate the kernel copy */
2818c2c66affSColin Finck             OpenPacket->EaBuffer = ExAllocatePoolWithTag(NonPagedPool,
2819c2c66affSColin Finck                                                          EaLength,
2820c2c66affSColin Finck                                                          TAG_EA);
2821c2c66affSColin Finck             if (!OpenPacket->EaBuffer)
2822c2c66affSColin Finck             {
2823c2c66affSColin Finck                 ExFreePool(OpenPacket);
2824c2c66affSColin Finck                 DPRINT1("Failed to allocate open packet EA buffer\n");
2825c2c66affSColin Finck                 return STATUS_INSUFFICIENT_RESOURCES;
2826c2c66affSColin Finck             }
2827c2c66affSColin Finck 
2828c2c66affSColin Finck             /* Copy the data */
2829c2c66affSColin Finck             OpenPacket->EaLength = EaLength;
2830c2c66affSColin Finck             RtlCopyMemory(OpenPacket->EaBuffer, EaBuffer, EaLength);
2831c2c66affSColin Finck 
2832c2c66affSColin Finck             /* Validate the buffer */
2833c2c66affSColin Finck             Status = IoCheckEaBufferValidity(OpenPacket->EaBuffer,
2834c2c66affSColin Finck                                              EaLength,
2835c2c66affSColin Finck                                              &EaErrorOffset);
2836c2c66affSColin Finck             if (!NT_SUCCESS(Status))
2837c2c66affSColin Finck             {
2838c2c66affSColin Finck                 /* Undo everything if it's invalid */
2839c2c66affSColin Finck                 DPRINT1("Invalid EA buffer\n");
2840c2c66affSColin Finck                 ExFreePool(OpenPacket->EaBuffer);
2841c2c66affSColin Finck                 IoStatusBlock->Status = Status;
2842c2c66affSColin Finck                 IoStatusBlock->Information = EaErrorOffset;
2843c2c66affSColin Finck                 ExFreePool(OpenPacket);
2844c2c66affSColin Finck                 return Status;
2845c2c66affSColin Finck             }
2846c2c66affSColin Finck         }
2847c2c66affSColin Finck     }
2848c2c66affSColin Finck 
2849c2c66affSColin Finck     /* Setup the Open Packet */
2850c2c66affSColin Finck     OpenPacket->Type = IO_TYPE_OPEN_PACKET;
2851c2c66affSColin Finck     OpenPacket->Size = sizeof(*OpenPacket);
2852c2c66affSColin Finck     OpenPacket->AllocationSize = SafeAllocationSize;
2853c2c66affSColin Finck     OpenPacket->CreateOptions = CreateOptions;
2854c2c66affSColin Finck     OpenPacket->FileAttributes = (USHORT)FileAttributes;
2855c2c66affSColin Finck     OpenPacket->ShareAccess = (USHORT)ShareAccess;
2856c2c66affSColin Finck     OpenPacket->Options = Options;
2857c2c66affSColin Finck     OpenPacket->Disposition = Disposition;
2858c2c66affSColin Finck     OpenPacket->CreateFileType = CreateFileType;
2859c2c66affSColin Finck     OpenPacket->ExtraCreateParameters = ExtraCreateParameters;
2860c2c66affSColin Finck     OpenPacket->InternalFlags = Flags;
2861c2c66affSColin Finck     OpenPacket->TopDeviceObjectHint = DeviceObject;
2862c2c66affSColin Finck 
2863c2c66affSColin Finck     /* Update the operation count */
2864c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
2865c2c66affSColin Finck 
2866c2c66affSColin Finck     /*
2867c2c66affSColin Finck      * Attempt opening the file. This will call the I/O Parse Routine for
2868c2c66affSColin Finck      * the File Object (IopParseDevice) which will create the object and
2869c2c66affSColin Finck      * send the IRP to its device object. Note that we have two statuses
2870c2c66affSColin Finck      * to worry about: the Object Manager's status (in Status) and the I/O
2871c2c66affSColin Finck      * status, which is in the Open Packet's Final Status, and determined
2872c2c66affSColin Finck      * by the Parse Check member.
2873c2c66affSColin Finck      */
2874c2c66affSColin Finck     Status = ObOpenObjectByName(ObjectAttributes,
2875c2c66affSColin Finck                                 NULL,
2876c2c66affSColin Finck                                 AccessMode,
2877c2c66affSColin Finck                                 NULL,
2878c2c66affSColin Finck                                 DesiredAccess,
2879c2c66affSColin Finck                                 OpenPacket,
2880c2c66affSColin Finck                                 &LocalHandle);
2881c2c66affSColin Finck 
2882c2c66affSColin Finck     /* Free the EA Buffer */
2883c2c66affSColin Finck     if (OpenPacket->EaBuffer) ExFreePool(OpenPacket->EaBuffer);
2884c2c66affSColin Finck 
2885c2c66affSColin Finck     /* Now check for Ob or Io failure */
2886c2c66affSColin Finck     if (!(NT_SUCCESS(Status)) || (OpenPacket->ParseCheck == FALSE))
2887c2c66affSColin Finck     {
2888c2c66affSColin Finck         /* Check if Ob thinks well went well */
2889c2c66affSColin Finck         if (NT_SUCCESS(Status))
2890c2c66affSColin Finck         {
2891c2c66affSColin Finck             /*
2892c2c66affSColin Finck              * Tell it otherwise. Because we didn't use an ObjectType,
2893c2c66affSColin Finck              * it incorrectly returned us a handle to God knows what.
2894c2c66affSColin Finck              */
2895c2c66affSColin Finck             ZwClose(LocalHandle);
2896c2c66affSColin Finck             Status = STATUS_OBJECT_TYPE_MISMATCH;
2897c2c66affSColin Finck         }
2898c2c66affSColin Finck 
2899c2c66affSColin Finck         /* Now check the Io status */
2900c2c66affSColin Finck         if (!NT_SUCCESS(OpenPacket->FinalStatus))
2901c2c66affSColin Finck         {
2902c2c66affSColin Finck             /* Use this status instead of Ob's */
2903c2c66affSColin Finck             Status = OpenPacket->FinalStatus;
2904c2c66affSColin Finck 
2905c2c66affSColin Finck             /* Check if it was only a warning */
2906c2c66affSColin Finck             if (NT_WARNING(Status))
2907c2c66affSColin Finck             {
2908c2c66affSColin Finck                 /* Protect write with SEH */
2909c2c66affSColin Finck                 _SEH2_TRY
2910c2c66affSColin Finck                 {
2911c2c66affSColin Finck                     /* In this case, we copy the I/O Status back */
2912c2c66affSColin Finck                     IoStatusBlock->Information = OpenPacket->Information;
2913c2c66affSColin Finck                     IoStatusBlock->Status = OpenPacket->FinalStatus;
2914c2c66affSColin Finck                 }
2915c2c66affSColin Finck                 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2916c2c66affSColin Finck                 {
2917c2c66affSColin Finck                     /* Get exception code */
2918c2c66affSColin Finck                     Status = _SEH2_GetExceptionCode();
2919c2c66affSColin Finck                 }
2920c2c66affSColin Finck                 _SEH2_END;
2921c2c66affSColin Finck             }
2922c2c66affSColin Finck         }
2923c2c66affSColin Finck         else if ((OpenPacket->FileObject) && (OpenPacket->ParseCheck == FALSE))
2924c2c66affSColin Finck         {
2925c2c66affSColin Finck             /*
2926c2c66affSColin Finck              * This can happen in the very bizarre case where the parse routine
2927c2c66affSColin Finck              * actually executed more then once (due to a reparse) and ended
2928c2c66affSColin Finck              * up failing after already having created the File Object.
2929c2c66affSColin Finck              */
2930c2c66affSColin Finck             if (OpenPacket->FileObject->FileName.Length)
2931c2c66affSColin Finck             {
2932c2c66affSColin Finck                 /* It had a name, free it */
2933c2c66affSColin Finck                 ExFreePoolWithTag(OpenPacket->FileObject->FileName.Buffer, TAG_IO_NAME);
2934c2c66affSColin Finck             }
2935c2c66affSColin Finck 
2936c2c66affSColin Finck             /* Clear the device object to invalidate the FO, and dereference */
2937c2c66affSColin Finck             OpenPacket->FileObject->DeviceObject = NULL;
2938c2c66affSColin Finck             ObDereferenceObject(OpenPacket->FileObject);
2939c2c66affSColin Finck         }
2940c2c66affSColin Finck     }
2941c2c66affSColin Finck     else
2942c2c66affSColin Finck     {
2943c2c66affSColin Finck         /* We reached success and have a valid file handle */
2944c2c66affSColin Finck         OpenPacket->FileObject->Flags |= FO_HANDLE_CREATED;
2945c2c66affSColin Finck         ASSERT(OpenPacket->FileObject->Type == IO_TYPE_FILE);
2946c2c66affSColin Finck 
2947c2c66affSColin Finck         /* Enter SEH for write back */
2948c2c66affSColin Finck         _SEH2_TRY
2949c2c66affSColin Finck         {
2950c2c66affSColin Finck             /* Write back the handle and I/O Status */
2951c2c66affSColin Finck             *FileHandle = LocalHandle;
2952c2c66affSColin Finck             IoStatusBlock->Information = OpenPacket->Information;
2953c2c66affSColin Finck             IoStatusBlock->Status = OpenPacket->FinalStatus;
2954c2c66affSColin Finck 
2955c2c66affSColin Finck             /* Get the Io status */
2956c2c66affSColin Finck             Status = OpenPacket->FinalStatus;
2957c2c66affSColin Finck         }
2958c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2959c2c66affSColin Finck         {
2960c2c66affSColin Finck             /* Get the exception status */
2961c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
2962c2c66affSColin Finck         }
2963c2c66affSColin Finck         _SEH2_END;
2964c2c66affSColin Finck     }
2965c2c66affSColin Finck 
2966c2c66affSColin Finck     /* Check if we were 100% successful */
2967c2c66affSColin Finck     if ((OpenPacket->ParseCheck != FALSE) && (OpenPacket->FileObject))
2968c2c66affSColin Finck     {
2969c2c66affSColin Finck         /* Dereference the File Object */
2970c2c66affSColin Finck         ObDereferenceObject(OpenPacket->FileObject);
2971c2c66affSColin Finck     }
2972c2c66affSColin Finck 
2973c2c66affSColin Finck     /* Return status */
2974c2c66affSColin Finck     ExFreePool(OpenPacket);
2975c2c66affSColin Finck     return Status;
2976c2c66affSColin Finck }
2977c2c66affSColin Finck 
2978c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
2979c2c66affSColin Finck 
2980c2c66affSColin Finck /*
2981c2c66affSColin Finck  * @unimplemented
2982c2c66affSColin Finck  */
2983c2c66affSColin Finck NTSTATUS
2984c2c66affSColin Finck NTAPI
IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,IN ULONG Length,IN BOOLEAN SetOperation)2985c2c66affSColin Finck IoCheckQuerySetFileInformation(IN FILE_INFORMATION_CLASS FileInformationClass,
2986c2c66affSColin Finck                                IN ULONG Length,
2987c2c66affSColin Finck                                IN BOOLEAN SetOperation)
2988c2c66affSColin Finck {
2989c2c66affSColin Finck     UNIMPLEMENTED;
2990c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
2991c2c66affSColin Finck }
2992c2c66affSColin Finck 
2993c2c66affSColin Finck /*
2994c2c66affSColin Finck  * @unimplemented
2995c2c66affSColin Finck  */
2996c2c66affSColin Finck NTSTATUS
2997c2c66affSColin Finck NTAPI
IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,IN ULONG QuotaLength,OUT PULONG ErrorOffset)2998c2c66affSColin Finck IoCheckQuotaBufferValidity(IN PFILE_QUOTA_INFORMATION QuotaBuffer,
2999c2c66affSColin Finck                            IN ULONG QuotaLength,
3000c2c66affSColin Finck                            OUT PULONG ErrorOffset)
3001c2c66affSColin Finck {
3002c2c66affSColin Finck     UNIMPLEMENTED;
3003c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
3004c2c66affSColin Finck }
3005c2c66affSColin Finck 
3006c2c66affSColin Finck /*
3007c2c66affSColin Finck  * @implemented
3008c2c66affSColin Finck  */
3009c2c66affSColin Finck NTSTATUS
3010c2c66affSColin Finck NTAPI
IoCreateFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PLARGE_INTEGER AllocationSize OPTIONAL,IN ULONG FileAttributes,IN ULONG ShareAccess,IN ULONG Disposition,IN ULONG CreateOptions,IN PVOID EaBuffer OPTIONAL,IN ULONG EaLength,IN CREATE_FILE_TYPE CreateFileType,IN PVOID ExtraCreateParameters OPTIONAL,IN ULONG Options)3011c2c66affSColin Finck IoCreateFile(OUT PHANDLE FileHandle,
3012c2c66affSColin Finck              IN ACCESS_MASK DesiredAccess,
3013c2c66affSColin Finck              IN POBJECT_ATTRIBUTES ObjectAttributes,
3014c2c66affSColin Finck              OUT PIO_STATUS_BLOCK IoStatusBlock,
3015c2c66affSColin Finck              IN PLARGE_INTEGER AllocationSize OPTIONAL,
3016c2c66affSColin Finck              IN ULONG FileAttributes,
3017c2c66affSColin Finck              IN ULONG ShareAccess,
3018c2c66affSColin Finck              IN ULONG Disposition,
3019c2c66affSColin Finck              IN ULONG CreateOptions,
3020c2c66affSColin Finck              IN PVOID EaBuffer OPTIONAL,
3021c2c66affSColin Finck              IN ULONG EaLength,
3022c2c66affSColin Finck              IN CREATE_FILE_TYPE CreateFileType,
3023c2c66affSColin Finck              IN PVOID ExtraCreateParameters OPTIONAL,
3024c2c66affSColin Finck              IN ULONG Options)
3025c2c66affSColin Finck {
3026c2c66affSColin Finck     PAGED_CODE();
3027c2c66affSColin Finck 
3028c2c66affSColin Finck     return IopCreateFile(FileHandle,
3029c2c66affSColin Finck                          DesiredAccess,
3030c2c66affSColin Finck                          ObjectAttributes,
3031c2c66affSColin Finck                          IoStatusBlock,
3032c2c66affSColin Finck                          AllocationSize,
3033c2c66affSColin Finck                          FileAttributes,
3034c2c66affSColin Finck                          ShareAccess,
3035c2c66affSColin Finck                          Disposition,
3036c2c66affSColin Finck                          CreateOptions,
3037c2c66affSColin Finck                          EaBuffer,
3038c2c66affSColin Finck                          EaLength,
3039c2c66affSColin Finck                          CreateFileType,
3040c2c66affSColin Finck                          ExtraCreateParameters,
3041c2c66affSColin Finck                          Options,
3042c2c66affSColin Finck                          0,
3043c2c66affSColin Finck                          NULL);
3044c2c66affSColin Finck }
3045c2c66affSColin Finck 
3046c2c66affSColin Finck /*
3047c2c66affSColin Finck  * @unimplemented
3048c2c66affSColin Finck  */
3049c2c66affSColin Finck NTSTATUS
3050c2c66affSColin Finck NTAPI
IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PLARGE_INTEGER AllocationSize OPTIONAL,IN ULONG FileAttributes,IN ULONG ShareAccess,IN ULONG Disposition,IN ULONG CreateOptions,IN PVOID EaBuffer OPTIONAL,IN ULONG EaLength,IN CREATE_FILE_TYPE CreateFileType,IN PVOID ExtraCreateParameters OPTIONAL,IN ULONG Options,IN PVOID DeviceObject)3051c2c66affSColin Finck IoCreateFileSpecifyDeviceObjectHint(OUT PHANDLE FileHandle,
3052c2c66affSColin Finck                                     IN ACCESS_MASK DesiredAccess,
3053c2c66affSColin Finck                                     IN POBJECT_ATTRIBUTES ObjectAttributes,
3054c2c66affSColin Finck                                     OUT PIO_STATUS_BLOCK IoStatusBlock,
3055c2c66affSColin Finck                                     IN PLARGE_INTEGER AllocationSize OPTIONAL,
3056c2c66affSColin Finck                                     IN ULONG FileAttributes,
3057c2c66affSColin Finck                                     IN ULONG ShareAccess,
3058c2c66affSColin Finck                                     IN ULONG Disposition,
3059c2c66affSColin Finck                                     IN ULONG CreateOptions,
3060c2c66affSColin Finck                                     IN PVOID EaBuffer OPTIONAL,
3061c2c66affSColin Finck                                     IN ULONG EaLength,
3062c2c66affSColin Finck                                     IN CREATE_FILE_TYPE CreateFileType,
3063c2c66affSColin Finck                                     IN PVOID ExtraCreateParameters OPTIONAL,
3064c2c66affSColin Finck                                     IN ULONG Options,
3065c2c66affSColin Finck                                     IN PVOID DeviceObject)
3066c2c66affSColin Finck {
3067c2c66affSColin Finck     ULONG Flags = 0;
3068c2c66affSColin Finck 
3069c2c66affSColin Finck     PAGED_CODE();
3070c2c66affSColin Finck 
3071c2c66affSColin Finck     /* Check if we were passed a device to send the create request to*/
3072c2c66affSColin Finck     if (DeviceObject)
3073c2c66affSColin Finck     {
3074c2c66affSColin Finck         /* We'll tag this request into a file object extension */
3075c2c66affSColin Finck         Flags = (IOP_CREATE_FILE_OBJECT_EXTENSION | IOP_USE_TOP_LEVEL_DEVICE_HINT);
3076c2c66affSColin Finck     }
3077c2c66affSColin Finck 
3078c2c66affSColin Finck     return IopCreateFile(FileHandle,
3079c2c66affSColin Finck                          DesiredAccess,
3080c2c66affSColin Finck                          ObjectAttributes,
3081c2c66affSColin Finck                          IoStatusBlock,
3082c2c66affSColin Finck                          AllocationSize,
3083c2c66affSColin Finck                          FileAttributes,
3084c2c66affSColin Finck                          ShareAccess,
3085c2c66affSColin Finck                          Disposition,
3086c2c66affSColin Finck                          CreateOptions,
3087c2c66affSColin Finck                          EaBuffer,
3088c2c66affSColin Finck                          EaLength,
3089c2c66affSColin Finck                          CreateFileType,
3090c2c66affSColin Finck                          ExtraCreateParameters,
3091c2c66affSColin Finck                          Options | IO_NO_PARAMETER_CHECKING,
3092c2c66affSColin Finck                          Flags,
3093c2c66affSColin Finck                          DeviceObject);
3094c2c66affSColin Finck }
3095c2c66affSColin Finck 
3096c2c66affSColin Finck /*
3097c2c66affSColin Finck  * @implemented
3098c2c66affSColin Finck  */
3099c2c66affSColin Finck PFILE_OBJECT
3100c2c66affSColin Finck NTAPI
IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,IN PDEVICE_OBJECT DeviceObject OPTIONAL,OUT PHANDLE FileObjectHandle OPTIONAL)3101c2c66affSColin Finck IoCreateStreamFileObjectEx(IN PFILE_OBJECT FileObject OPTIONAL,
3102c2c66affSColin Finck                            IN PDEVICE_OBJECT DeviceObject OPTIONAL,
3103c2c66affSColin Finck                            OUT PHANDLE FileObjectHandle OPTIONAL)
3104c2c66affSColin Finck {
3105c2c66affSColin Finck     PFILE_OBJECT CreatedFileObject;
3106c2c66affSColin Finck     NTSTATUS Status;
3107c2c66affSColin Finck     HANDLE FileHandle;
3108c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
3109c2c66affSColin Finck     PAGED_CODE();
3110c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject);
3111c2c66affSColin Finck 
3112c2c66affSColin Finck     /* Choose Device Object */
3113c2c66affSColin Finck     if (FileObject) DeviceObject = FileObject->DeviceObject;
3114c2c66affSColin Finck 
3115c2c66affSColin Finck     /* Reference the device object and initialize attributes */
3116c2c66affSColin Finck     InterlockedIncrement(&DeviceObject->ReferenceCount);
3117c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
3118c2c66affSColin Finck 
3119c2c66affSColin Finck     /* Create the File Object */
3120c2c66affSColin Finck     Status = ObCreateObject(KernelMode,
3121c2c66affSColin Finck                             IoFileObjectType,
3122c2c66affSColin Finck                             &ObjectAttributes,
3123c2c66affSColin Finck                             KernelMode,
3124c2c66affSColin Finck                             NULL,
3125c2c66affSColin Finck                             sizeof(FILE_OBJECT),
3126c2c66affSColin Finck                             sizeof(FILE_OBJECT),
3127c2c66affSColin Finck                             0,
3128c2c66affSColin Finck                             (PVOID*)&CreatedFileObject);
3129c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3130c2c66affSColin Finck     {
3131c2c66affSColin Finck         /* Fail */
3132c2c66affSColin Finck         IopDereferenceDeviceObject(DeviceObject, FALSE);
3133c2c66affSColin Finck         ExRaiseStatus(Status);
3134c2c66affSColin Finck     }
3135c2c66affSColin Finck 
3136c2c66affSColin Finck     /* Set File Object Data */
3137c2c66affSColin Finck     RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT));
3138c2c66affSColin Finck     CreatedFileObject->DeviceObject = DeviceObject;
3139c2c66affSColin Finck     CreatedFileObject->Type = IO_TYPE_FILE;
3140c2c66affSColin Finck     CreatedFileObject->Size = sizeof(FILE_OBJECT);
3141c2c66affSColin Finck     CreatedFileObject->Flags = FO_STREAM_FILE;
3142c2c66affSColin Finck 
3143c2c66affSColin Finck     /* Initialize the wait event */
3144c2c66affSColin Finck     KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE);
3145c2c66affSColin Finck 
3146c2c66affSColin Finck     /* Insert it to create a handle for it */
3147c2c66affSColin Finck     Status = ObInsertObject(CreatedFileObject,
3148c2c66affSColin Finck                             NULL,
3149c2c66affSColin Finck                             FILE_READ_DATA,
3150c2c66affSColin Finck                             1,
3151c2c66affSColin Finck                             (PVOID*)&CreatedFileObject,
3152c2c66affSColin Finck                             &FileHandle);
3153c2c66affSColin Finck     if (!NT_SUCCESS(Status)) ExRaiseStatus(Status);
3154c2c66affSColin Finck 
3155c2c66affSColin Finck     /* Set the handle created flag */
3156c2c66affSColin Finck     CreatedFileObject->Flags |= FO_HANDLE_CREATED;
3157c2c66affSColin Finck     ASSERT(CreatedFileObject->Type == IO_TYPE_FILE);
3158c2c66affSColin Finck 
3159c2c66affSColin Finck     /* Check if we have a VPB */
3160c2c66affSColin Finck     if (DeviceObject->Vpb)
3161c2c66affSColin Finck     {
3162c2c66affSColin Finck         /* Reference it */
3163c2c66affSColin Finck          InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount);
3164c2c66affSColin Finck     }
3165c2c66affSColin Finck 
3166c2c66affSColin Finck     /* Check if the caller wants the handle */
3167c2c66affSColin Finck     if (FileObjectHandle)
3168c2c66affSColin Finck     {
3169c2c66affSColin Finck         /* Return it */
3170c2c66affSColin Finck         *FileObjectHandle = FileHandle;
3171c2c66affSColin Finck         ObDereferenceObject(CreatedFileObject);
3172c2c66affSColin Finck     }
3173c2c66affSColin Finck     else
3174c2c66affSColin Finck     {
3175c2c66affSColin Finck         /* Otherwise, close it */
3176c2c66affSColin Finck         ObCloseHandle(FileHandle, KernelMode);
3177c2c66affSColin Finck     }
3178c2c66affSColin Finck 
3179c2c66affSColin Finck     /* Return the file object */
3180c2c66affSColin Finck     return CreatedFileObject;
3181c2c66affSColin Finck }
3182c2c66affSColin Finck 
3183c2c66affSColin Finck /*
3184c2c66affSColin Finck  * @implemented
3185c2c66affSColin Finck  */
3186c2c66affSColin Finck PFILE_OBJECT
3187c2c66affSColin Finck NTAPI
IoCreateStreamFileObject(IN PFILE_OBJECT FileObject,IN PDEVICE_OBJECT DeviceObject)3188c2c66affSColin Finck IoCreateStreamFileObject(IN PFILE_OBJECT FileObject,
3189c2c66affSColin Finck                          IN PDEVICE_OBJECT DeviceObject)
3190c2c66affSColin Finck {
3191c2c66affSColin Finck     /* Call the newer function */
3192c2c66affSColin Finck     return IoCreateStreamFileObjectEx(FileObject, DeviceObject, NULL);
3193c2c66affSColin Finck }
3194c2c66affSColin Finck 
3195c2c66affSColin Finck /*
3196c2c66affSColin Finck  * @implemented
3197c2c66affSColin Finck  */
3198c2c66affSColin Finck PFILE_OBJECT
3199c2c66affSColin Finck NTAPI
IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,IN PDEVICE_OBJECT DeviceObject OPTIONAL)3200c2c66affSColin Finck IoCreateStreamFileObjectLite(IN PFILE_OBJECT FileObject OPTIONAL,
3201c2c66affSColin Finck                              IN PDEVICE_OBJECT DeviceObject OPTIONAL)
3202c2c66affSColin Finck {
3203c2c66affSColin Finck     PFILE_OBJECT CreatedFileObject;
3204c2c66affSColin Finck     NTSTATUS Status;
3205c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
3206c2c66affSColin Finck     PAGED_CODE();
3207c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "FileObject: %p\n", FileObject);
3208c2c66affSColin Finck 
3209c2c66affSColin Finck     /* Choose Device Object */
3210c2c66affSColin Finck     if (FileObject) DeviceObject = FileObject->DeviceObject;
3211c2c66affSColin Finck 
3212c2c66affSColin Finck     /* Reference the device object and initialize attributes */
3213c2c66affSColin Finck     InterlockedIncrement(&DeviceObject->ReferenceCount);
3214c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
3215c2c66affSColin Finck 
3216c2c66affSColin Finck     /* Create the File Object */
3217c2c66affSColin Finck     Status = ObCreateObject(KernelMode,
3218c2c66affSColin Finck                             IoFileObjectType,
3219c2c66affSColin Finck                             &ObjectAttributes,
3220c2c66affSColin Finck                             KernelMode,
3221c2c66affSColin Finck                             NULL,
3222c2c66affSColin Finck                             sizeof(FILE_OBJECT),
3223c2c66affSColin Finck                             sizeof(FILE_OBJECT),
3224c2c66affSColin Finck                             0,
3225c2c66affSColin Finck                             (PVOID*)&CreatedFileObject);
3226c2c66affSColin Finck     if (!NT_SUCCESS(Status))
3227c2c66affSColin Finck     {
3228c2c66affSColin Finck         /* Fail */
3229c2c66affSColin Finck         IopDereferenceDeviceObject(DeviceObject, FALSE);
3230c2c66affSColin Finck         ExRaiseStatus(Status);
3231c2c66affSColin Finck     }
3232c2c66affSColin Finck 
3233c2c66affSColin Finck     /* Set File Object Data */
3234c2c66affSColin Finck     RtlZeroMemory(CreatedFileObject, sizeof(FILE_OBJECT));
3235c2c66affSColin Finck     CreatedFileObject->DeviceObject = DeviceObject;
3236c2c66affSColin Finck     CreatedFileObject->Type = IO_TYPE_FILE;
3237c2c66affSColin Finck     CreatedFileObject->Size = sizeof(FILE_OBJECT);
3238c2c66affSColin Finck     CreatedFileObject->Flags = FO_STREAM_FILE;
3239c2c66affSColin Finck 
3240c2c66affSColin Finck     /* Initialize the wait event */
3241c2c66affSColin Finck     KeInitializeEvent(&CreatedFileObject->Event, SynchronizationEvent, FALSE);
3242c2c66affSColin Finck 
3243c2c66affSColin Finck     /* Destroy create information */
3244c2c66affSColin Finck     ObFreeObjectCreateInfoBuffer(OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->
3245c2c66affSColin Finck                                  ObjectCreateInfo);
3246c2c66affSColin Finck     OBJECT_TO_OBJECT_HEADER(CreatedFileObject)->ObjectCreateInfo = NULL;
3247c2c66affSColin Finck 
3248c2c66affSColin Finck     /* Set the handle created flag */
3249c2c66affSColin Finck     CreatedFileObject->Flags |= FO_HANDLE_CREATED;
3250c2c66affSColin Finck     ASSERT(CreatedFileObject->Type == IO_TYPE_FILE);
3251c2c66affSColin Finck 
3252c2c66affSColin Finck     /* Check if we have a VPB */
3253c2c66affSColin Finck     if (DeviceObject->Vpb)
3254c2c66affSColin Finck     {
3255c2c66affSColin Finck         /* Reference it */
3256c2c66affSColin Finck          InterlockedIncrement((PLONG)&DeviceObject->Vpb->ReferenceCount);
3257c2c66affSColin Finck     }
3258c2c66affSColin Finck 
3259c2c66affSColin Finck     /* Return the file object */
3260c2c66affSColin Finck     return CreatedFileObject;
3261c2c66affSColin Finck }
3262c2c66affSColin Finck 
3263c2c66affSColin Finck /*
3264c2c66affSColin Finck  * @implemented
3265c2c66affSColin Finck  */
3266c2c66affSColin Finck PGENERIC_MAPPING
3267c2c66affSColin Finck NTAPI
IoGetFileObjectGenericMapping(VOID)3268c2c66affSColin Finck IoGetFileObjectGenericMapping(VOID)
3269c2c66affSColin Finck {
3270c2c66affSColin Finck     /* Return the mapping */
3271c2c66affSColin Finck     return &IopFileMapping;
3272c2c66affSColin Finck }
3273c2c66affSColin Finck 
3274c2c66affSColin Finck /*
3275c2c66affSColin Finck  * @implemented
3276c2c66affSColin Finck  */
3277c2c66affSColin Finck BOOLEAN
3278c2c66affSColin Finck NTAPI
IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)3279c2c66affSColin Finck IoIsFileOriginRemote(IN PFILE_OBJECT FileObject)
3280c2c66affSColin Finck {
3281c2c66affSColin Finck     /* Return the flag status */
3282c2c66affSColin Finck     return FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE;
3283c2c66affSColin Finck }
3284c2c66affSColin Finck 
3285c2c66affSColin Finck /*
3286c2c66affSColin Finck  * @implemented
3287c2c66affSColin Finck  */
3288c2c66affSColin Finck BOOLEAN
3289c2c66affSColin Finck NTAPI
IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,IN ACCESS_MASK DesiredAccess,IN ULONG OpenOptions,OUT PIO_STATUS_BLOCK IoStatus,OUT PFILE_NETWORK_OPEN_INFORMATION Buffer)3290c2c66affSColin Finck IoFastQueryNetworkAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes,
3291c2c66affSColin Finck                              IN ACCESS_MASK DesiredAccess,
3292c2c66affSColin Finck                              IN ULONG OpenOptions,
3293c2c66affSColin Finck                              OUT PIO_STATUS_BLOCK IoStatus,
3294c2c66affSColin Finck                              OUT PFILE_NETWORK_OPEN_INFORMATION Buffer)
3295c2c66affSColin Finck {
3296c2c66affSColin Finck     NTSTATUS Status;
3297c2c66affSColin Finck     DUMMY_FILE_OBJECT LocalFileObject;
3298c2c66affSColin Finck     HANDLE Handle;
3299c2c66affSColin Finck     OPEN_PACKET OpenPacket;
3300c2c66affSColin Finck     PAGED_CODE();
3301c2c66affSColin Finck     IOTRACE(IO_FILE_DEBUG, "FileName: %wZ\n", ObjectAttributes->ObjectName);
3302c2c66affSColin Finck 
3303c2c66affSColin Finck     /* Setup the Open Packet */
3304c2c66affSColin Finck     RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
3305c2c66affSColin Finck     OpenPacket.Type = IO_TYPE_OPEN_PACKET;
3306c2c66affSColin Finck     OpenPacket.Size = sizeof(OPEN_PACKET);
3307c2c66affSColin Finck     OpenPacket.CreateOptions = OpenOptions | FILE_OPEN_REPARSE_POINT;
3308c2c66affSColin Finck     OpenPacket.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
3309c2c66affSColin Finck     OpenPacket.Options = IO_FORCE_ACCESS_CHECK;
3310c2c66affSColin Finck     OpenPacket.Disposition = FILE_OPEN;
3311c2c66affSColin Finck     OpenPacket.NetworkInformation = Buffer;
3312c2c66affSColin Finck     OpenPacket.QueryOnly = TRUE;
3313c2c66affSColin Finck     OpenPacket.FullAttributes = TRUE;
3314c2c66affSColin Finck     OpenPacket.LocalFileObject = &LocalFileObject;
3315c2c66affSColin Finck 
3316c2c66affSColin Finck     /*
3317c2c66affSColin Finck      * Attempt opening the file. This will call the I/O Parse Routine for
3318c2c66affSColin Finck      * the File Object (IopParseDevice) which will use the dummy file obejct
3319c2c66affSColin Finck      * send the IRP to its device object. Note that we have two statuses
3320c2c66affSColin Finck      * to worry about: the Object Manager's status (in Status) and the I/O
3321c2c66affSColin Finck      * status, which is in the Open Packet's Final Status, and determined
3322c2c66affSColin Finck      * by the Parse Check member.
3323c2c66affSColin Finck      */
3324c2c66affSColin Finck     Status = ObOpenObjectByName(ObjectAttributes,
3325c2c66affSColin Finck                                 NULL,
3326c2c66affSColin Finck                                 KernelMode,
3327c2c66affSColin Finck                                 NULL,
3328c2c66affSColin Finck                                 DesiredAccess,
3329c2c66affSColin Finck                                 &OpenPacket,
3330c2c66affSColin Finck                                 &Handle);
3331c2c66affSColin Finck     if (OpenPacket.ParseCheck == FALSE)
3332c2c66affSColin Finck     {
3333c2c66affSColin Finck         /* Parse failed */
3334c2c66affSColin Finck         IoStatus->Status = Status;
3335c2c66affSColin Finck     }
3336c2c66affSColin Finck     else
3337c2c66affSColin Finck     {
3338c2c66affSColin Finck         /* Use the Io status */
3339c2c66affSColin Finck         IoStatus->Status = OpenPacket.FinalStatus;
3340c2c66affSColin Finck         IoStatus->Information = OpenPacket.Information;
3341c2c66affSColin Finck     }
3342c2c66affSColin Finck 
3343c2c66affSColin Finck     /* Return success */
3344c2c66affSColin Finck     return TRUE;
3345c2c66affSColin Finck }
3346c2c66affSColin Finck 
3347c2c66affSColin Finck /*
3348c2c66affSColin Finck  * @implemented
3349c2c66affSColin Finck  */
3350c2c66affSColin Finck VOID
3351c2c66affSColin Finck NTAPI
IoUpdateShareAccess(IN PFILE_OBJECT FileObject,OUT PSHARE_ACCESS ShareAccess)3352c2c66affSColin Finck IoUpdateShareAccess(IN PFILE_OBJECT FileObject,
3353c2c66affSColin Finck                     OUT PSHARE_ACCESS ShareAccess)
3354c2c66affSColin Finck {
3355c2c66affSColin Finck     PAGED_CODE();
3356c2c66affSColin Finck 
3357c2c66affSColin Finck     /* Check if the file has an extension */
3358c2c66affSColin Finck     if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)
3359c2c66affSColin Finck     {
3360c2c66affSColin Finck         /* Check if caller specified to ignore access checks */
3361c2c66affSColin Finck         //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3362c2c66affSColin Finck         {
3363c2c66affSColin Finck             /* Don't update share access */
3364c2c66affSColin Finck             return;
3365c2c66affSColin Finck         }
3366c2c66affSColin Finck     }
3367c2c66affSColin Finck 
3368c2c66affSColin Finck     /* Otherwise, check if there's any access present */
3369c2c66affSColin Finck     if ((FileObject->ReadAccess) ||
3370c2c66affSColin Finck         (FileObject->WriteAccess) ||
3371c2c66affSColin Finck         (FileObject->DeleteAccess))
3372c2c66affSColin Finck     {
3373c2c66affSColin Finck         /* Increase the open count */
3374c2c66affSColin Finck         ShareAccess->OpenCount++;
3375c2c66affSColin Finck 
3376c2c66affSColin Finck         /* Add new share access */
3377c2c66affSColin Finck         ShareAccess->Readers += FileObject->ReadAccess;
3378c2c66affSColin Finck         ShareAccess->Writers += FileObject->WriteAccess;
3379c2c66affSColin Finck         ShareAccess->Deleters += FileObject->DeleteAccess;
3380c2c66affSColin Finck         ShareAccess->SharedRead += FileObject->SharedRead;
3381c2c66affSColin Finck         ShareAccess->SharedWrite += FileObject->SharedWrite;
3382c2c66affSColin Finck         ShareAccess->SharedDelete += FileObject->SharedDelete;
3383c2c66affSColin Finck     }
3384c2c66affSColin Finck }
3385c2c66affSColin Finck 
3386c2c66affSColin Finck /*
3387c2c66affSColin Finck  * @implemented
3388c2c66affSColin Finck  */
3389c2c66affSColin Finck NTSTATUS
3390c2c66affSColin Finck NTAPI
IoCheckShareAccess(IN ACCESS_MASK DesiredAccess,IN ULONG DesiredShareAccess,IN PFILE_OBJECT FileObject,IN PSHARE_ACCESS ShareAccess,IN BOOLEAN Update)3391c2c66affSColin Finck IoCheckShareAccess(IN ACCESS_MASK DesiredAccess,
3392c2c66affSColin Finck                    IN ULONG DesiredShareAccess,
3393c2c66affSColin Finck                    IN PFILE_OBJECT FileObject,
3394c2c66affSColin Finck                    IN PSHARE_ACCESS ShareAccess,
3395c2c66affSColin Finck                    IN BOOLEAN Update)
3396c2c66affSColin Finck {
3397c2c66affSColin Finck     BOOLEAN ReadAccess;
3398c2c66affSColin Finck     BOOLEAN WriteAccess;
3399c2c66affSColin Finck     BOOLEAN DeleteAccess;
3400c2c66affSColin Finck     BOOLEAN SharedRead;
3401c2c66affSColin Finck     BOOLEAN SharedWrite;
3402c2c66affSColin Finck     BOOLEAN SharedDelete;
3403c2c66affSColin Finck     PAGED_CODE();
3404c2c66affSColin Finck 
3405c2c66affSColin Finck     /* Get access masks */
3406c2c66affSColin Finck     ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
3407c2c66affSColin Finck     WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
3408c2c66affSColin Finck     DeleteAccess = (DesiredAccess & DELETE) != 0;
3409c2c66affSColin Finck 
3410c2c66affSColin Finck     /* Set them in the file object */
3411c2c66affSColin Finck     FileObject->ReadAccess = ReadAccess;
3412c2c66affSColin Finck     FileObject->WriteAccess = WriteAccess;
3413c2c66affSColin Finck     FileObject->DeleteAccess = DeleteAccess;
3414c2c66affSColin Finck 
3415c2c66affSColin Finck     /* Check if the file has an extension */
3416c2c66affSColin Finck     if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)
3417c2c66affSColin Finck     {
3418c2c66affSColin Finck         /* Check if caller specified to ignore access checks */
3419c2c66affSColin Finck         //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3420c2c66affSColin Finck         {
3421c2c66affSColin Finck             /* Don't check share access */
3422c2c66affSColin Finck             return STATUS_SUCCESS;
3423c2c66affSColin Finck         }
3424c2c66affSColin Finck     }
3425c2c66affSColin Finck 
3426c2c66affSColin Finck     /* Check if we have any access */
3427c2c66affSColin Finck     if ((ReadAccess) || (WriteAccess) || (DeleteAccess))
3428c2c66affSColin Finck     {
3429c2c66affSColin Finck         /* Get shared access masks */
3430c2c66affSColin Finck         SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
3431c2c66affSColin Finck         SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
3432c2c66affSColin Finck         SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
3433c2c66affSColin Finck 
3434c2c66affSColin Finck         /* Check if the shared access is violated */
3435c2c66affSColin Finck         if ((ReadAccess &&
3436c2c66affSColin Finck              (ShareAccess->SharedRead < ShareAccess->OpenCount)) ||
3437c2c66affSColin Finck             (WriteAccess &&
3438c2c66affSColin Finck              (ShareAccess->SharedWrite < ShareAccess->OpenCount)) ||
3439c2c66affSColin Finck             (DeleteAccess &&
3440c2c66affSColin Finck              (ShareAccess->SharedDelete < ShareAccess->OpenCount)) ||
3441c2c66affSColin Finck             ((ShareAccess->Readers != 0) && !SharedRead) ||
3442c2c66affSColin Finck             ((ShareAccess->Writers != 0) && !SharedWrite) ||
3443c2c66affSColin Finck             ((ShareAccess->Deleters != 0) && !SharedDelete))
3444c2c66affSColin Finck         {
3445c2c66affSColin Finck             /* Sharing violation, fail */
3446c2c66affSColin Finck             return STATUS_SHARING_VIOLATION;
3447c2c66affSColin Finck         }
3448c2c66affSColin Finck 
34491d1dba51SJérôme Gardou         /* Set them */
34501d1dba51SJérôme Gardou         FileObject->SharedRead = SharedRead;
34511d1dba51SJérôme Gardou         FileObject->SharedWrite = SharedWrite;
34521d1dba51SJérôme Gardou         FileObject->SharedDelete = SharedDelete;
34531d1dba51SJérôme Gardou 
3454c2c66affSColin Finck         /* It's not, check if caller wants us to update it */
3455c2c66affSColin Finck         if (Update)
3456c2c66affSColin Finck         {
3457c2c66affSColin Finck             /* Increase open count */
3458c2c66affSColin Finck             ShareAccess->OpenCount++;
3459c2c66affSColin Finck 
3460c2c66affSColin Finck             /* Update shared access */
3461c2c66affSColin Finck             ShareAccess->Readers += ReadAccess;
3462c2c66affSColin Finck             ShareAccess->Writers += WriteAccess;
3463c2c66affSColin Finck             ShareAccess->Deleters += DeleteAccess;
3464c2c66affSColin Finck             ShareAccess->SharedRead += SharedRead;
3465c2c66affSColin Finck             ShareAccess->SharedWrite += SharedWrite;
3466c2c66affSColin Finck             ShareAccess->SharedDelete += SharedDelete;
3467c2c66affSColin Finck         }
3468c2c66affSColin Finck     }
3469c2c66affSColin Finck 
3470c2c66affSColin Finck     /* Validation successful */
3471c2c66affSColin Finck     return STATUS_SUCCESS;
3472c2c66affSColin Finck }
3473c2c66affSColin Finck 
3474c2c66affSColin Finck /*
3475c2c66affSColin Finck  * @implemented
3476c2c66affSColin Finck  */
3477c2c66affSColin Finck VOID
3478c2c66affSColin Finck NTAPI
IoRemoveShareAccess(IN PFILE_OBJECT FileObject,IN PSHARE_ACCESS ShareAccess)3479c2c66affSColin Finck IoRemoveShareAccess(IN PFILE_OBJECT FileObject,
3480c2c66affSColin Finck                     IN PSHARE_ACCESS ShareAccess)
3481c2c66affSColin Finck {
3482c2c66affSColin Finck     PAGED_CODE();
3483c2c66affSColin Finck 
3484c2c66affSColin Finck     /* Check if the file has an extension */
3485c2c66affSColin Finck     if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)
3486c2c66affSColin Finck     {
3487c2c66affSColin Finck         /* Check if caller specified to ignore access checks */
3488c2c66affSColin Finck         //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3489c2c66affSColin Finck         {
3490c2c66affSColin Finck             /* Don't update share access */
3491c2c66affSColin Finck             return;
3492c2c66affSColin Finck         }
3493c2c66affSColin Finck     }
3494c2c66affSColin Finck 
3495c2c66affSColin Finck     /* Otherwise, check if there's any access present */
3496c2c66affSColin Finck     if ((FileObject->ReadAccess) ||
3497c2c66affSColin Finck         (FileObject->WriteAccess) ||
3498c2c66affSColin Finck         (FileObject->DeleteAccess))
3499c2c66affSColin Finck     {
3500c2c66affSColin Finck         /* Decrement the open count */
3501c2c66affSColin Finck         ShareAccess->OpenCount--;
3502c2c66affSColin Finck 
3503c2c66affSColin Finck         /* Remove share access */
3504c2c66affSColin Finck         ShareAccess->Readers -= FileObject->ReadAccess;
3505c2c66affSColin Finck         ShareAccess->Writers -= FileObject->WriteAccess;
3506c2c66affSColin Finck         ShareAccess->Deleters -= FileObject->DeleteAccess;
3507c2c66affSColin Finck         ShareAccess->SharedRead -= FileObject->SharedRead;
3508c2c66affSColin Finck         ShareAccess->SharedWrite -= FileObject->SharedWrite;
3509c2c66affSColin Finck         ShareAccess->SharedDelete -= FileObject->SharedDelete;
3510c2c66affSColin Finck     }
3511c2c66affSColin Finck }
3512c2c66affSColin Finck 
3513c2c66affSColin Finck /*
3514c2c66affSColin Finck  * @implemented
3515c2c66affSColin Finck  */
3516c2c66affSColin Finck VOID
3517c2c66affSColin Finck NTAPI
IoSetShareAccess(IN ACCESS_MASK DesiredAccess,IN ULONG DesiredShareAccess,IN PFILE_OBJECT FileObject,OUT PSHARE_ACCESS ShareAccess)3518c2c66affSColin Finck IoSetShareAccess(IN ACCESS_MASK DesiredAccess,
3519c2c66affSColin Finck                  IN ULONG DesiredShareAccess,
3520c2c66affSColin Finck                  IN PFILE_OBJECT FileObject,
3521c2c66affSColin Finck                  OUT PSHARE_ACCESS ShareAccess)
3522c2c66affSColin Finck {
3523c2c66affSColin Finck     BOOLEAN ReadAccess;
3524c2c66affSColin Finck     BOOLEAN WriteAccess;
3525c2c66affSColin Finck     BOOLEAN DeleteAccess;
3526c2c66affSColin Finck     BOOLEAN SharedRead;
3527c2c66affSColin Finck     BOOLEAN SharedWrite;
3528c2c66affSColin Finck     BOOLEAN SharedDelete;
3529c2c66affSColin Finck     BOOLEAN Update = TRUE;
3530c2c66affSColin Finck     PAGED_CODE();
3531c2c66affSColin Finck 
3532c2c66affSColin Finck     ReadAccess = (DesiredAccess & (FILE_READ_DATA | FILE_EXECUTE)) != 0;
3533c2c66affSColin Finck     WriteAccess = (DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
3534c2c66affSColin Finck     DeleteAccess = (DesiredAccess & DELETE) != 0;
3535c2c66affSColin Finck 
3536c2c66affSColin Finck     /* Check if the file has an extension */
3537c2c66affSColin Finck     if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION)
3538c2c66affSColin Finck     {
3539c2c66affSColin Finck         /* Check if caller specified to ignore access checks */
3540c2c66affSColin Finck         //if (FileObject->FoExtFlags & IO_IGNORE_SHARE_ACCESS_CHECK)
3541c2c66affSColin Finck         {
3542c2c66affSColin Finck             /* Don't update share access */
3543c2c66affSColin Finck             Update = FALSE;
3544c2c66affSColin Finck         }
3545c2c66affSColin Finck     }
3546c2c66affSColin Finck 
3547c2c66affSColin Finck     /* Update basic access */
3548c2c66affSColin Finck     FileObject->ReadAccess = ReadAccess;
3549c2c66affSColin Finck     FileObject->WriteAccess = WriteAccess;
3550c2c66affSColin Finck     FileObject->DeleteAccess = DeleteAccess;
3551c2c66affSColin Finck 
3552c2c66affSColin Finck     /* Check if we have no access as all */
3553c2c66affSColin Finck     if (!(ReadAccess) && !(WriteAccess) && !(DeleteAccess))
3554c2c66affSColin Finck     {
3555c2c66affSColin Finck         /* Check if we need to update the structure */
3556c2c66affSColin Finck         if (!Update) return;
3557c2c66affSColin Finck 
3558c2c66affSColin Finck         /* Otherwise, clear data */
3559c2c66affSColin Finck         ShareAccess->OpenCount = 0;
3560c2c66affSColin Finck         ShareAccess->Readers = 0;
3561c2c66affSColin Finck         ShareAccess->Writers = 0;
3562c2c66affSColin Finck         ShareAccess->Deleters = 0;
3563c2c66affSColin Finck         ShareAccess->SharedRead = 0;
3564c2c66affSColin Finck         ShareAccess->SharedWrite = 0;
3565c2c66affSColin Finck         ShareAccess->SharedDelete = 0;
3566c2c66affSColin Finck     }
3567c2c66affSColin Finck     else
3568c2c66affSColin Finck     {
3569c2c66affSColin Finck         /* Calculate shared access */
3570c2c66affSColin Finck         SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
3571c2c66affSColin Finck         SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
3572c2c66affSColin Finck         SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
3573c2c66affSColin Finck 
3574c2c66affSColin Finck         /* Set it in the FO */
3575c2c66affSColin Finck         FileObject->SharedRead = SharedRead;
3576c2c66affSColin Finck         FileObject->SharedWrite = SharedWrite;
3577c2c66affSColin Finck         FileObject->SharedDelete = SharedDelete;
3578c2c66affSColin Finck 
3579c2c66affSColin Finck         /* Check if we need to update the structure */
3580c2c66affSColin Finck         if (!Update) return;
3581c2c66affSColin Finck 
3582c2c66affSColin Finck         /* Otherwise, set data */
3583c2c66affSColin Finck         ShareAccess->OpenCount = 1;
3584c2c66affSColin Finck         ShareAccess->Readers = ReadAccess;
3585c2c66affSColin Finck         ShareAccess->Writers = WriteAccess;
3586c2c66affSColin Finck         ShareAccess->Deleters = DeleteAccess;
3587c2c66affSColin Finck         ShareAccess->SharedRead = SharedRead;
3588c2c66affSColin Finck         ShareAccess->SharedWrite = SharedWrite;
3589c2c66affSColin Finck         ShareAccess->SharedDelete = SharedDelete;
3590c2c66affSColin Finck     }
3591c2c66affSColin Finck }
3592c2c66affSColin Finck 
3593c2c66affSColin Finck /*
3594c2c66affSColin Finck  * @implemented
3595c2c66affSColin Finck  */
3596c2c66affSColin Finck VOID
3597c2c66affSColin Finck NTAPI
IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject,IN PFILE_OBJECT FileObject)3598c2c66affSColin Finck IoCancelFileOpen(IN PDEVICE_OBJECT DeviceObject,
3599c2c66affSColin Finck                  IN PFILE_OBJECT FileObject)
3600c2c66affSColin Finck {
3601c2c66affSColin Finck     PIRP Irp;
3602c2c66affSColin Finck     KEVENT Event;
3603c2c66affSColin Finck     KIRQL OldIrql;
3604c2c66affSColin Finck     NTSTATUS Status;
3605c2c66affSColin Finck     PIO_STACK_LOCATION Stack;
3606c2c66affSColin Finck 
3607c2c66affSColin Finck     /* Check if handles were already created for the
3608c2c66affSColin Finck      * open file. If so, that's over.
3609c2c66affSColin Finck      */
3610c2c66affSColin Finck     if (FileObject->Flags & FO_HANDLE_CREATED)
3611c2c66affSColin Finck         KeBugCheckEx(INVALID_CANCEL_OF_FILE_OPEN,
3612c2c66affSColin Finck                      (ULONG_PTR)FileObject,
3613c2c66affSColin Finck                      (ULONG_PTR)DeviceObject, 0, 0);
3614c2c66affSColin Finck 
3615c2c66affSColin Finck     /* Reset the events */
3616c2c66affSColin Finck     KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
3617c2c66affSColin Finck     KeClearEvent(&FileObject->Event);
3618c2c66affSColin Finck 
3619c2c66affSColin Finck     /* Allocate the IRP we'll use */
3620c2c66affSColin Finck     Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
3621c2c66affSColin Finck     /* Properly set it */
3622c2c66affSColin Finck     Irp->Tail.Overlay.Thread = PsGetCurrentThread();
3623c2c66affSColin Finck     Irp->UserEvent = &Event;
3624c2c66affSColin Finck     Irp->UserIosb = &Irp->IoStatus;
3625c2c66affSColin Finck     Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
3626c2c66affSColin Finck     Irp->Tail.Overlay.OriginalFileObject = FileObject;
3627c2c66affSColin Finck     Irp->RequestorMode = KernelMode;
3628c2c66affSColin Finck     Irp->Flags = IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_API;
3629c2c66affSColin Finck 
3630c2c66affSColin Finck     Stack = IoGetNextIrpStackLocation(Irp);
3631c2c66affSColin Finck     Stack->MajorFunction = IRP_MJ_CLEANUP;
3632c2c66affSColin Finck     Stack->FileObject = FileObject;
3633c2c66affSColin Finck 
3634c2c66affSColin Finck     /* Put on top of IRPs list of the thread */
3635c2c66affSColin Finck     IopQueueIrpToThread(Irp);
3636c2c66affSColin Finck 
3637c2c66affSColin Finck     /* Call the driver */
3638c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
3639c2c66affSColin Finck     if (Status == STATUS_PENDING)
3640c2c66affSColin Finck     {
3641c2c66affSColin Finck         KeWaitForSingleObject(&Event, UserRequest,
3642c2c66affSColin Finck                               KernelMode, FALSE, NULL);
3643c2c66affSColin Finck     }
3644c2c66affSColin Finck 
3645c2c66affSColin Finck     /* Remove from IRPs list */
3646c2c66affSColin Finck     KeRaiseIrql(APC_LEVEL, &OldIrql);
3647c2c66affSColin Finck     IopUnQueueIrpFromThread(Irp);
3648c2c66affSColin Finck     KeLowerIrql(OldIrql);
3649c2c66affSColin Finck 
3650c2c66affSColin Finck     /* Free the IRP */
3651c2c66affSColin Finck     IoFreeIrp(Irp);
3652c2c66affSColin Finck 
3653c2c66affSColin Finck     /* Clear the event */
3654c2c66affSColin Finck     KeClearEvent(&FileObject->Event);
3655c2c66affSColin Finck     /* And finally, mark the open operation as canceled */
3656c2c66affSColin Finck     FileObject->Flags |= FO_FILE_OPEN_CANCELLED;
3657c2c66affSColin Finck }
3658c2c66affSColin Finck 
3659c2c66affSColin Finck /*
36604a7e8977SPierre Schweitzer  * @implemented
3661c2c66affSColin Finck  */
3662c2c66affSColin Finck NTSTATUS
3663c2c66affSColin Finck NTAPI
IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,OUT POBJECT_NAME_INFORMATION * ObjectNameInformation)3664c2c66affSColin Finck IoQueryFileDosDeviceName(IN PFILE_OBJECT FileObject,
3665c2c66affSColin Finck                          OUT POBJECT_NAME_INFORMATION *ObjectNameInformation)
3666c2c66affSColin Finck {
36674a7e8977SPierre Schweitzer     NTSTATUS Status;
36684a7e8977SPierre Schweitzer     ULONG Length, ReturnLength;
36694a7e8977SPierre Schweitzer     POBJECT_NAME_INFORMATION LocalInfo;
36704a7e8977SPierre Schweitzer 
36714a7e8977SPierre Schweitzer     /* Start with a buffer length of 200 */
36724a7e8977SPierre Schweitzer     ReturnLength = 200;
36734a7e8977SPierre Schweitzer     /*
36744a7e8977SPierre Schweitzer      * We'll loop until query works.
36754a7e8977SPierre Schweitzer      * We will use returned length for next loop
36764a7e8977SPierre Schweitzer      * iteration, trying to have a big enough buffer.
36774a7e8977SPierre Schweitzer      */
36784a7e8977SPierre Schweitzer     for (Length = 200; ; Length = ReturnLength)
36794a7e8977SPierre Schweitzer     {
36804a7e8977SPierre Schweitzer         /* Allocate our work buffer */
36814a7e8977SPierre Schweitzer         LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, 'nDoI');
36824a7e8977SPierre Schweitzer         if (LocalInfo == NULL)
36834a7e8977SPierre Schweitzer         {
36844a7e8977SPierre Schweitzer             return STATUS_INSUFFICIENT_RESOURCES;
36854a7e8977SPierre Schweitzer         }
36864a7e8977SPierre Schweitzer 
36874a7e8977SPierre Schweitzer         /* Query the DOS name */
36884a7e8977SPierre Schweitzer         Status = IopQueryNameInternal(FileObject,
36894a7e8977SPierre Schweitzer                                       TRUE,
36904a7e8977SPierre Schweitzer                                       TRUE,
36914a7e8977SPierre Schweitzer                                       LocalInfo,
36924a7e8977SPierre Schweitzer                                       Length,
36934a7e8977SPierre Schweitzer                                       &ReturnLength,
36944a7e8977SPierre Schweitzer                                       KernelMode);
36954a7e8977SPierre Schweitzer         /* If it succeed, nothing more to do */
36964a7e8977SPierre Schweitzer         if (Status == STATUS_SUCCESS)
36974a7e8977SPierre Schweitzer         {
36984a7e8977SPierre Schweitzer             break;
36994a7e8977SPierre Schweitzer         }
37004a7e8977SPierre Schweitzer 
37014a7e8977SPierre Schweitzer         /* Otherwise, prepare for re-allocation */
37024a7e8977SPierre Schweitzer         ExFreePoolWithTag(LocalInfo, 'nDoI');
37034a7e8977SPierre Schweitzer 
37044a7e8977SPierre Schweitzer         /*
37054a7e8977SPierre Schweitzer          * If we failed because of something else
37064a7e8977SPierre Schweitzer          * than memory, simply stop and fail here
37074a7e8977SPierre Schweitzer          */
37084a7e8977SPierre Schweitzer         if (Status != STATUS_BUFFER_OVERFLOW)
37094a7e8977SPierre Schweitzer         {
3710520f404eSPierre Schweitzer             return Status;
37114a7e8977SPierre Schweitzer         }
37124a7e8977SPierre Schweitzer     }
37134a7e8977SPierre Schweitzer 
37144a7e8977SPierre Schweitzer     /* Success case here: return our buffer */
37154a7e8977SPierre Schweitzer     *ObjectNameInformation = LocalInfo;
37164a7e8977SPierre Schweitzer     return STATUS_SUCCESS;
3717c2c66affSColin Finck }
3718c2c66affSColin Finck 
3719c2c66affSColin Finck /*
3720c2c66affSColin Finck  * @implemented
3721c2c66affSColin Finck  */
3722c2c66affSColin Finck NTSTATUS
3723c2c66affSColin Finck NTAPI
IoSetFileOrigin(IN PFILE_OBJECT FileObject,IN BOOLEAN Remote)3724c2c66affSColin Finck IoSetFileOrigin(IN PFILE_OBJECT FileObject,
3725c2c66affSColin Finck                 IN BOOLEAN Remote)
3726c2c66affSColin Finck {
3727c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
3728c2c66affSColin Finck     BOOLEAN FlagSet;
3729c2c66affSColin Finck 
3730c2c66affSColin Finck     /* Get the flag status */
3731c2c66affSColin Finck     FlagSet = FileObject->Flags & FO_REMOTE_ORIGIN ? TRUE : FALSE;
3732c2c66affSColin Finck 
3733c2c66affSColin Finck     /* Don't set the flag if it was set already, and don't remove it if it wasn't set */
3734c2c66affSColin Finck     if (Remote && !FlagSet)
3735c2c66affSColin Finck     {
3736c2c66affSColin Finck         /* Set the flag */
3737c2c66affSColin Finck         FileObject->Flags |= FO_REMOTE_ORIGIN;
3738c2c66affSColin Finck     }
3739c2c66affSColin Finck     else if (!Remote && FlagSet)
3740c2c66affSColin Finck     {
3741c2c66affSColin Finck         /* Remove the flag */
3742c2c66affSColin Finck         FileObject->Flags &= ~FO_REMOTE_ORIGIN;
3743c2c66affSColin Finck     }
3744c2c66affSColin Finck     else
3745c2c66affSColin Finck     {
3746c2c66affSColin Finck         /* Fail */
3747c2c66affSColin Finck         Status = STATUS_INVALID_PARAMETER_MIX;
3748c2c66affSColin Finck     }
3749c2c66affSColin Finck 
3750c2c66affSColin Finck     /* Return status */
3751c2c66affSColin Finck     return Status;
3752c2c66affSColin Finck }
3753c2c66affSColin Finck 
3754c2c66affSColin Finck /*
3755c2c66affSColin Finck  * @implemented
3756c2c66affSColin Finck  */
3757c2c66affSColin Finck NTSTATUS
3758c2c66affSColin Finck NTAPI
NtCreateFile(PHANDLE FileHandle,ACCESS_MASK DesiredAccess,POBJECT_ATTRIBUTES ObjectAttributes,PIO_STATUS_BLOCK IoStatusBlock,PLARGE_INTEGER AllocateSize,ULONG FileAttributes,ULONG ShareAccess,ULONG CreateDisposition,ULONG CreateOptions,PVOID EaBuffer,ULONG EaLength)3759c2c66affSColin Finck NtCreateFile(PHANDLE FileHandle,
3760c2c66affSColin Finck              ACCESS_MASK DesiredAccess,
3761c2c66affSColin Finck              POBJECT_ATTRIBUTES ObjectAttributes,
3762c2c66affSColin Finck              PIO_STATUS_BLOCK IoStatusBlock,
3763c2c66affSColin Finck              PLARGE_INTEGER AllocateSize,
3764c2c66affSColin Finck              ULONG FileAttributes,
3765c2c66affSColin Finck              ULONG ShareAccess,
3766c2c66affSColin Finck              ULONG CreateDisposition,
3767c2c66affSColin Finck              ULONG CreateOptions,
3768c2c66affSColin Finck              PVOID EaBuffer,
3769c2c66affSColin Finck              ULONG EaLength)
3770c2c66affSColin Finck {
3771c2c66affSColin Finck     /* Call the I/O Function */
3772c2c66affSColin Finck     return IoCreateFile(FileHandle,
3773c2c66affSColin Finck                         DesiredAccess,
3774c2c66affSColin Finck                         ObjectAttributes,
3775c2c66affSColin Finck                         IoStatusBlock,
3776c2c66affSColin Finck                         AllocateSize,
3777c2c66affSColin Finck                         FileAttributes,
3778c2c66affSColin Finck                         ShareAccess,
3779c2c66affSColin Finck                         CreateDisposition,
3780c2c66affSColin Finck                         CreateOptions,
3781c2c66affSColin Finck                         EaBuffer,
3782c2c66affSColin Finck                         EaLength,
3783c2c66affSColin Finck                         CreateFileTypeNone,
3784c2c66affSColin Finck                         NULL,
3785c2c66affSColin Finck                         0);
3786c2c66affSColin Finck }
3787c2c66affSColin Finck 
3788c2c66affSColin Finck NTSTATUS
3789c2c66affSColin Finck NTAPI
NtCreateMailslotFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN ULONG CreateOptions,IN ULONG MailslotQuota,IN ULONG MaxMessageSize,IN PLARGE_INTEGER TimeOut)3790c2c66affSColin Finck NtCreateMailslotFile(OUT PHANDLE FileHandle,
3791c2c66affSColin Finck                      IN ACCESS_MASK DesiredAccess,
3792c2c66affSColin Finck                      IN POBJECT_ATTRIBUTES ObjectAttributes,
3793c2c66affSColin Finck                      OUT PIO_STATUS_BLOCK IoStatusBlock,
3794c2c66affSColin Finck                      IN ULONG CreateOptions,
3795c2c66affSColin Finck                      IN ULONG MailslotQuota,
3796c2c66affSColin Finck                      IN ULONG MaxMessageSize,
3797c2c66affSColin Finck                      IN PLARGE_INTEGER TimeOut)
3798c2c66affSColin Finck {
3799c2c66affSColin Finck     MAILSLOT_CREATE_PARAMETERS Buffer;
3800c2c66affSColin Finck     PAGED_CODE();
3801c2c66affSColin Finck 
3802c2c66affSColin Finck     /* Check for Timeout */
3803c2c66affSColin Finck     if (TimeOut)
3804c2c66affSColin Finck     {
3805c2c66affSColin Finck         /* check if the call came from user mode */
3806c2c66affSColin Finck         if (KeGetPreviousMode() != KernelMode)
3807c2c66affSColin Finck         {
3808c2c66affSColin Finck             /* Enter SEH for Probe */
3809c2c66affSColin Finck             _SEH2_TRY
3810c2c66affSColin Finck             {
3811c2c66affSColin Finck                 /* Probe the timeout */
3812c2c66affSColin Finck                 Buffer.ReadTimeout = ProbeForReadLargeInteger(TimeOut);
3813c2c66affSColin Finck             }
3814c2c66affSColin Finck             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3815c2c66affSColin Finck             {
3816c2c66affSColin Finck                 /* Return the exception code */
3817c2c66affSColin Finck                 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3818c2c66affSColin Finck             }
3819c2c66affSColin Finck             _SEH2_END;
3820c2c66affSColin Finck         }
3821c2c66affSColin Finck         else
3822c2c66affSColin Finck         {
3823c2c66affSColin Finck             /* Otherwise, capture directly */
3824c2c66affSColin Finck             Buffer.ReadTimeout = *TimeOut;
3825c2c66affSColin Finck         }
3826c2c66affSColin Finck 
3827c2c66affSColin Finck         /* Set the correct setting */
3828c2c66affSColin Finck         Buffer.TimeoutSpecified = TRUE;
3829c2c66affSColin Finck     }
3830c2c66affSColin Finck     else
3831c2c66affSColin Finck     {
3832c2c66affSColin Finck         /* Tell the FSD we don't have a timeout */
3833c2c66affSColin Finck         Buffer.TimeoutSpecified = FALSE;
3834c2c66affSColin Finck     }
3835c2c66affSColin Finck 
3836c2c66affSColin Finck     /* Set Settings */
3837c2c66affSColin Finck     Buffer.MailslotQuota = MailslotQuota;
3838c2c66affSColin Finck     Buffer.MaximumMessageSize = MaxMessageSize;
3839c2c66affSColin Finck 
3840c2c66affSColin Finck     /* Call I/O */
3841c2c66affSColin Finck     return IoCreateFile(FileHandle,
3842c2c66affSColin Finck                         DesiredAccess,
3843c2c66affSColin Finck                         ObjectAttributes,
3844c2c66affSColin Finck                         IoStatusBlock,
3845c2c66affSColin Finck                         NULL,
3846c2c66affSColin Finck                         0,
3847c2c66affSColin Finck                         FILE_SHARE_READ | FILE_SHARE_WRITE,
3848c2c66affSColin Finck                         FILE_CREATE,
3849c2c66affSColin Finck                         CreateOptions,
3850c2c66affSColin Finck                         NULL,
3851c2c66affSColin Finck                         0,
3852c2c66affSColin Finck                         CreateFileTypeMailslot,
3853c2c66affSColin Finck                         (PVOID)&Buffer,
3854c2c66affSColin Finck                         0);
3855c2c66affSColin Finck }
3856c2c66affSColin Finck 
3857c2c66affSColin Finck NTSTATUS
3858c2c66affSColin Finck NTAPI
NtCreateNamedPipeFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN ULONG ShareAccess,IN ULONG CreateDisposition,IN ULONG CreateOptions,IN ULONG NamedPipeType,IN ULONG ReadMode,IN ULONG CompletionMode,IN ULONG MaximumInstances,IN ULONG InboundQuota,IN ULONG OutboundQuota,IN PLARGE_INTEGER DefaultTimeout)3859c2c66affSColin Finck NtCreateNamedPipeFile(OUT PHANDLE FileHandle,
3860c2c66affSColin Finck                       IN ACCESS_MASK DesiredAccess,
3861c2c66affSColin Finck                       IN POBJECT_ATTRIBUTES ObjectAttributes,
3862c2c66affSColin Finck                       OUT PIO_STATUS_BLOCK IoStatusBlock,
3863c2c66affSColin Finck                       IN ULONG ShareAccess,
3864c2c66affSColin Finck                       IN ULONG CreateDisposition,
3865c2c66affSColin Finck                       IN ULONG CreateOptions,
3866c2c66affSColin Finck                       IN ULONG NamedPipeType,
3867c2c66affSColin Finck                       IN ULONG ReadMode,
3868c2c66affSColin Finck                       IN ULONG CompletionMode,
3869c2c66affSColin Finck                       IN ULONG MaximumInstances,
3870c2c66affSColin Finck                       IN ULONG InboundQuota,
3871c2c66affSColin Finck                       IN ULONG OutboundQuota,
3872c2c66affSColin Finck                       IN PLARGE_INTEGER DefaultTimeout)
3873c2c66affSColin Finck {
3874c2c66affSColin Finck     NAMED_PIPE_CREATE_PARAMETERS Buffer;
3875c2c66affSColin Finck     PAGED_CODE();
3876c2c66affSColin Finck 
3877c2c66affSColin Finck     /* Check for Timeout */
3878c2c66affSColin Finck     if (DefaultTimeout)
3879c2c66affSColin Finck     {
3880c2c66affSColin Finck         /* check if the call came from user mode */
3881c2c66affSColin Finck         if (KeGetPreviousMode() != KernelMode)
3882c2c66affSColin Finck         {
3883c2c66affSColin Finck             /* Enter SEH for Probe */
3884c2c66affSColin Finck             _SEH2_TRY
3885c2c66affSColin Finck             {
3886c2c66affSColin Finck                 /* Probe the timeout */
3887c2c66affSColin Finck                 Buffer.DefaultTimeout =
3888c2c66affSColin Finck                     ProbeForReadLargeInteger(DefaultTimeout);
3889c2c66affSColin Finck             }
3890c2c66affSColin Finck             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3891c2c66affSColin Finck             {
3892c2c66affSColin Finck                 /* Return the exception code */
3893c2c66affSColin Finck                 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3894c2c66affSColin Finck             }
3895c2c66affSColin Finck             _SEH2_END;
3896c2c66affSColin Finck         }
3897c2c66affSColin Finck         else
3898c2c66affSColin Finck         {
3899c2c66affSColin Finck             /* Otherwise, capture directly */
3900c2c66affSColin Finck             Buffer.DefaultTimeout = *DefaultTimeout;
3901c2c66affSColin Finck         }
3902c2c66affSColin Finck 
3903c2c66affSColin Finck         /* Set the correct setting */
3904c2c66affSColin Finck         Buffer.TimeoutSpecified = TRUE;
3905c2c66affSColin Finck     }
3906c2c66affSColin Finck     else
3907c2c66affSColin Finck     {
3908c2c66affSColin Finck         /* Tell the FSD we don't have a timeout */
3909c2c66affSColin Finck         Buffer.TimeoutSpecified = FALSE;
3910c2c66affSColin Finck     }
3911c2c66affSColin Finck 
3912c2c66affSColin Finck     /* Set Settings */
3913c2c66affSColin Finck     Buffer.NamedPipeType = NamedPipeType;
3914c2c66affSColin Finck     Buffer.ReadMode = ReadMode;
3915c2c66affSColin Finck     Buffer.CompletionMode = CompletionMode;
3916c2c66affSColin Finck     Buffer.MaximumInstances = MaximumInstances;
3917c2c66affSColin Finck     Buffer.InboundQuota = InboundQuota;
3918c2c66affSColin Finck     Buffer.OutboundQuota = OutboundQuota;
3919c2c66affSColin Finck 
3920c2c66affSColin Finck     /* Call I/O */
3921c2c66affSColin Finck     return IoCreateFile(FileHandle,
3922c2c66affSColin Finck                         DesiredAccess,
3923c2c66affSColin Finck                         ObjectAttributes,
3924c2c66affSColin Finck                         IoStatusBlock,
3925c2c66affSColin Finck                         NULL,
3926c2c66affSColin Finck                         0,
3927c2c66affSColin Finck                         ShareAccess,
3928c2c66affSColin Finck                         CreateDisposition,
3929c2c66affSColin Finck                         CreateOptions,
3930c2c66affSColin Finck                         NULL,
3931c2c66affSColin Finck                         0,
3932c2c66affSColin Finck                         CreateFileTypeNamedPipe,
3933c2c66affSColin Finck                         (PVOID)&Buffer,
3934c2c66affSColin Finck                         0);
3935c2c66affSColin Finck }
3936c2c66affSColin Finck 
3937c2c66affSColin Finck NTSTATUS
3938c2c66affSColin Finck NTAPI
NtFlushWriteBuffer(VOID)3939c2c66affSColin Finck NtFlushWriteBuffer(VOID)
3940c2c66affSColin Finck {
3941c2c66affSColin Finck     PAGED_CODE();
3942c2c66affSColin Finck 
3943c2c66affSColin Finck     /* Call the kernel */
3944c2c66affSColin Finck     KeFlushWriteBuffer();
3945c2c66affSColin Finck     return STATUS_SUCCESS;
3946c2c66affSColin Finck }
3947c2c66affSColin Finck 
3948c2c66affSColin Finck /*
3949c2c66affSColin Finck  * @implemented
3950c2c66affSColin Finck  */
3951c2c66affSColin Finck NTSTATUS
3952c2c66affSColin Finck NTAPI
NtOpenFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN ULONG ShareAccess,IN ULONG OpenOptions)3953c2c66affSColin Finck NtOpenFile(OUT PHANDLE FileHandle,
3954c2c66affSColin Finck            IN ACCESS_MASK DesiredAccess,
3955c2c66affSColin Finck            IN POBJECT_ATTRIBUTES ObjectAttributes,
3956c2c66affSColin Finck            OUT PIO_STATUS_BLOCK IoStatusBlock,
3957c2c66affSColin Finck            IN ULONG ShareAccess,
3958c2c66affSColin Finck            IN ULONG OpenOptions)
3959c2c66affSColin Finck {
3960c2c66affSColin Finck     /* Call the I/O Function */
3961c2c66affSColin Finck     return IoCreateFile(FileHandle,
3962c2c66affSColin Finck                         DesiredAccess,
3963c2c66affSColin Finck                         ObjectAttributes,
3964c2c66affSColin Finck                         IoStatusBlock,
3965c2c66affSColin Finck                         NULL,
3966c2c66affSColin Finck                         0,
3967c2c66affSColin Finck                         ShareAccess,
3968c2c66affSColin Finck                         FILE_OPEN,
3969c2c66affSColin Finck                         OpenOptions,
3970c2c66affSColin Finck                         NULL,
3971c2c66affSColin Finck                         0,
3972c2c66affSColin Finck                         CreateFileTypeNone,
3973c2c66affSColin Finck                         NULL,
3974c2c66affSColin Finck                         0);
3975c2c66affSColin Finck }
3976c2c66affSColin Finck 
3977c2c66affSColin Finck NTSTATUS
3978c2c66affSColin Finck NTAPI
NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PFILE_BASIC_INFORMATION FileInformation)3979c2c66affSColin Finck NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
3980c2c66affSColin Finck                       OUT PFILE_BASIC_INFORMATION FileInformation)
3981c2c66affSColin Finck {
3982c2c66affSColin Finck     /* Call the internal helper API */
3983c2c66affSColin Finck     return IopQueryAttributesFile(ObjectAttributes,
3984c2c66affSColin Finck                                   FileBasicInformation,
3985c2c66affSColin Finck                                   sizeof(FILE_BASIC_INFORMATION),
3986c2c66affSColin Finck                                   FileInformation);
3987c2c66affSColin Finck }
3988c2c66affSColin Finck 
3989c2c66affSColin Finck NTSTATUS
3990c2c66affSColin Finck NTAPI
NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)3991c2c66affSColin Finck NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
3992c2c66affSColin Finck                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
3993c2c66affSColin Finck {
3994c2c66affSColin Finck     /* Call the internal helper API */
3995c2c66affSColin Finck     return IopQueryAttributesFile(ObjectAttributes,
3996c2c66affSColin Finck                                   FileNetworkOpenInformation,
3997c2c66affSColin Finck                                   sizeof(FILE_NETWORK_OPEN_INFORMATION),
3998c2c66affSColin Finck                                   FileInformation);
3999c2c66affSColin Finck }
4000c2c66affSColin Finck 
4001c2c66affSColin Finck /**
4002c2c66affSColin Finck  * @name NtCancelIoFile
4003c2c66affSColin Finck  *
4004c2c66affSColin Finck  * Cancel all pending I/O operations in the current thread for specified
4005c2c66affSColin Finck  * file object.
4006c2c66affSColin Finck  *
4007c2c66affSColin Finck  * @param FileHandle
4008c2c66affSColin Finck  *        Handle to file object to cancel requests for. No specific
4009c2c66affSColin Finck  *        access rights are needed.
4010c2c66affSColin Finck  * @param IoStatusBlock
4011c2c66affSColin Finck  *        Pointer to status block which is filled with final completition
4012c2c66affSColin Finck  *        status on successful return.
4013c2c66affSColin Finck  *
4014c2c66affSColin Finck  * @return Status.
4015c2c66affSColin Finck  *
4016c2c66affSColin Finck  * @implemented
4017c2c66affSColin Finck  */
4018c2c66affSColin Finck NTSTATUS
4019c2c66affSColin Finck NTAPI
NtCancelIoFile(IN HANDLE FileHandle,OUT PIO_STATUS_BLOCK IoStatusBlock)4020c2c66affSColin Finck NtCancelIoFile(IN HANDLE FileHandle,
4021c2c66affSColin Finck                OUT PIO_STATUS_BLOCK IoStatusBlock)
4022c2c66affSColin Finck {
4023c2c66affSColin Finck     PFILE_OBJECT FileObject;
4024c2c66affSColin Finck     PETHREAD Thread;
4025c2c66affSColin Finck     PIRP Irp;
4026c2c66affSColin Finck     KIRQL OldIrql;
4027c2c66affSColin Finck     BOOLEAN OurIrpsInList = FALSE;
4028c2c66affSColin Finck     LARGE_INTEGER Interval;
4029c2c66affSColin Finck     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
4030c2c66affSColin Finck     NTSTATUS Status;
4031c2c66affSColin Finck     PLIST_ENTRY ListHead, NextEntry;
4032c2c66affSColin Finck     PAGED_CODE();
4033c2c66affSColin Finck     IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
4034c2c66affSColin Finck 
4035c2c66affSColin Finck     /* Check the previous mode */
4036c2c66affSColin Finck     if (PreviousMode != KernelMode)
4037c2c66affSColin Finck     {
4038c2c66affSColin Finck         /* Enter SEH for probing */
4039c2c66affSColin Finck         _SEH2_TRY
4040c2c66affSColin Finck         {
4041c2c66affSColin Finck             /* Probe the I/O Status Block */
4042c2c66affSColin Finck             ProbeForWriteIoStatusBlock(IoStatusBlock);
4043c2c66affSColin Finck         }
4044c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4045c2c66affSColin Finck         {
4046c2c66affSColin Finck             /* Return the exception code */
4047c2c66affSColin Finck             _SEH2_YIELD(return _SEH2_GetExceptionCode());
4048c2c66affSColin Finck         }
4049c2c66affSColin Finck         _SEH2_END;
4050c2c66affSColin Finck     }
4051c2c66affSColin Finck 
4052c2c66affSColin Finck     /* Reference the file object */
4053c2c66affSColin Finck     Status = ObReferenceObjectByHandle(FileHandle,
4054c2c66affSColin Finck                                        0,
4055c2c66affSColin Finck                                        IoFileObjectType,
4056c2c66affSColin Finck                                        PreviousMode,
4057c2c66affSColin Finck                                        (PVOID*)&FileObject,
4058c2c66affSColin Finck                                        NULL);
4059c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return Status;
4060c2c66affSColin Finck 
4061c2c66affSColin Finck     /* IRP cancellations are synchronized at APC_LEVEL. */
4062c2c66affSColin Finck     KeRaiseIrql(APC_LEVEL, &OldIrql);
4063c2c66affSColin Finck 
4064c2c66affSColin Finck     /* Get the current thread */
4065c2c66affSColin Finck     Thread = PsGetCurrentThread();
4066c2c66affSColin Finck 
4067c2c66affSColin Finck     /* Update the operation counts */
4068c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
4069c2c66affSColin Finck 
4070c2c66affSColin Finck     /* Loop the list */
4071c2c66affSColin Finck     ListHead = &Thread->IrpList;
4072c2c66affSColin Finck     NextEntry = ListHead->Flink;
4073c2c66affSColin Finck     while (ListHead != NextEntry)
4074c2c66affSColin Finck     {
4075c2c66affSColin Finck         /* Get the IRP and check if the File Object matches */
4076c2c66affSColin Finck         Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
4077c2c66affSColin Finck         if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
4078c2c66affSColin Finck         {
4079c2c66affSColin Finck             /* Cancel this IRP and keep looping */
4080c2c66affSColin Finck             IoCancelIrp(Irp);
4081c2c66affSColin Finck             OurIrpsInList = TRUE;
4082c2c66affSColin Finck         }
4083c2c66affSColin Finck 
4084c2c66affSColin Finck         /* Go to the next entry */
4085c2c66affSColin Finck         NextEntry = NextEntry->Flink;
4086c2c66affSColin Finck     }
4087c2c66affSColin Finck 
4088c2c66affSColin Finck     /* Lower the IRQL */
4089c2c66affSColin Finck     KeLowerIrql(OldIrql);
4090c2c66affSColin Finck 
4091c2c66affSColin Finck     /* Check if we had found an IRP */
4092c2c66affSColin Finck     if (OurIrpsInList)
4093c2c66affSColin Finck     {
4094c2c66affSColin Finck         /* Setup a 10ms wait */
4095c2c66affSColin Finck         Interval.QuadPart = -100000;
4096c2c66affSColin Finck 
4097c2c66affSColin Finck         /* Start looping */
4098c2c66affSColin Finck         while (OurIrpsInList)
4099c2c66affSColin Finck         {
4100c2c66affSColin Finck             /* Do the wait */
4101c2c66affSColin Finck             KeDelayExecutionThread(KernelMode, FALSE, &Interval);
4102c2c66affSColin Finck             OurIrpsInList = FALSE;
4103c2c66affSColin Finck 
4104c2c66affSColin Finck             /* Raise IRQL */
4105c2c66affSColin Finck             KeRaiseIrql(APC_LEVEL, &OldIrql);
4106c2c66affSColin Finck 
4107c2c66affSColin Finck             /* Now loop the list again */
4108c2c66affSColin Finck             NextEntry = ListHead->Flink;
4109c2c66affSColin Finck             while (NextEntry != ListHead)
4110c2c66affSColin Finck             {
4111c2c66affSColin Finck                 /* Get the IRP and check if the File Object matches */
4112c2c66affSColin Finck                 Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);
4113c2c66affSColin Finck                 if (Irp->Tail.Overlay.OriginalFileObject == FileObject)
4114c2c66affSColin Finck                 {
4115c2c66affSColin Finck                     /* Keep looping */
4116c2c66affSColin Finck                     OurIrpsInList = TRUE;
4117c2c66affSColin Finck                     break;
4118c2c66affSColin Finck                 }
4119c2c66affSColin Finck 
4120c2c66affSColin Finck                 /* Go to the next entry */
4121c2c66affSColin Finck                 NextEntry = NextEntry->Flink;
4122c2c66affSColin Finck             }
4123c2c66affSColin Finck 
4124c2c66affSColin Finck             /* Lower the IRQL */
4125c2c66affSColin Finck             KeLowerIrql(OldIrql);
4126c2c66affSColin Finck         }
4127c2c66affSColin Finck     }
4128c2c66affSColin Finck 
4129c2c66affSColin Finck     /* Enter SEH for writing back the I/O Status */
4130c2c66affSColin Finck     _SEH2_TRY
4131c2c66affSColin Finck     {
4132c2c66affSColin Finck         /* Write success */
4133c2c66affSColin Finck         IoStatusBlock->Status = STATUS_SUCCESS;
4134c2c66affSColin Finck         IoStatusBlock->Information = 0;
4135c2c66affSColin Finck     }
4136c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4137c2c66affSColin Finck     {
4138c2c66affSColin Finck         /* Ignore exception */
4139c2c66affSColin Finck     }
4140c2c66affSColin Finck     _SEH2_END;
4141c2c66affSColin Finck 
4142c2c66affSColin Finck     /* Dereference the file object and return success */
4143c2c66affSColin Finck     ObDereferenceObject(FileObject);
4144c2c66affSColin Finck     return STATUS_SUCCESS;
4145c2c66affSColin Finck }
4146c2c66affSColin Finck 
4147c2c66affSColin Finck /*
4148c2c66affSColin Finck  * @implemented
4149c2c66affSColin Finck  */
4150c2c66affSColin Finck NTSTATUS
4151c2c66affSColin Finck NTAPI
NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)4152c2c66affSColin Finck NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
4153c2c66affSColin Finck {
4154c2c66affSColin Finck     NTSTATUS Status;
4155c2c66affSColin Finck     DUMMY_FILE_OBJECT LocalFileObject;
4156c2c66affSColin Finck     HANDLE Handle;
4157c2c66affSColin Finck     KPROCESSOR_MODE AccessMode = KeGetPreviousMode();
4158c2c66affSColin Finck     OPEN_PACKET OpenPacket;
4159c2c66affSColin Finck     PAGED_CODE();
4160c2c66affSColin Finck     IOTRACE(IO_API_DEBUG, "FileMame: %wZ\n", ObjectAttributes->ObjectName);
4161c2c66affSColin Finck 
4162c2c66affSColin Finck     /* Setup the Open Packet */
4163c2c66affSColin Finck     RtlZeroMemory(&OpenPacket, sizeof(OPEN_PACKET));
4164c2c66affSColin Finck     OpenPacket.Type = IO_TYPE_OPEN_PACKET;
4165c2c66affSColin Finck     OpenPacket.Size = sizeof(OPEN_PACKET);
4166c2c66affSColin Finck     OpenPacket.CreateOptions = FILE_DELETE_ON_CLOSE;
4167c2c66affSColin Finck     OpenPacket.ShareAccess = FILE_SHARE_READ |
4168c2c66affSColin Finck                              FILE_SHARE_WRITE |
4169c2c66affSColin Finck                              FILE_SHARE_DELETE;
4170c2c66affSColin Finck     OpenPacket.Disposition = FILE_OPEN;
4171c2c66affSColin Finck     OpenPacket.DeleteOnly = TRUE;
4172c2c66affSColin Finck     OpenPacket.LocalFileObject = &LocalFileObject;
4173c2c66affSColin Finck 
4174c2c66affSColin Finck     /* Update the operation counts */
4175c2c66affSColin Finck     IopUpdateOperationCount(IopOtherTransfer);
4176c2c66affSColin Finck 
4177c2c66affSColin Finck     /*
4178c2c66affSColin Finck      * Attempt opening the file. This will call the I/O Parse Routine for
4179c2c66affSColin Finck      * the File Object (IopParseDevice) which will use the dummy file obejct
4180c2c66affSColin Finck      * send the IRP to its device object. Note that we have two statuses
4181c2c66affSColin Finck      * to worry about: the Object Manager's status (in Status) and the I/O
4182c2c66affSColin Finck      * status, which is in the Open Packet's Final Status, and determined
4183c2c66affSColin Finck      * by the Parse Check member.
4184c2c66affSColin Finck      */
4185c2c66affSColin Finck     Status = ObOpenObjectByName(ObjectAttributes,
4186c2c66affSColin Finck                                 NULL,
4187c2c66affSColin Finck                                 AccessMode,
4188c2c66affSColin Finck                                 NULL,
4189c2c66affSColin Finck                                 DELETE,
4190c2c66affSColin Finck                                 &OpenPacket,
4191c2c66affSColin Finck                                 &Handle);
4192c2c66affSColin Finck     if (OpenPacket.ParseCheck == FALSE) return Status;
4193c2c66affSColin Finck 
4194c2c66affSColin Finck     /* Retrn the Io status */
4195c2c66affSColin Finck     return OpenPacket.FinalStatus;
4196c2c66affSColin Finck }
4197c2c66affSColin Finck 
4198c2c66affSColin Finck /* EOF */
4199