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