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