3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/create.c
6 * PURPOSE: Handling file create/open apis
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES ***************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
22 /* FUNCTIONS *************************************************************/
24 /**********************************************************************
41 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
44 return(STATUS_NOT_IMPLEMENTED
);
48 /**********************************************************************
61 IopCreateFile(PVOID ObjectBody
,
64 POBJECT_ATTRIBUTES ObjectAttributes
)
66 PDEVICE_OBJECT DeviceObject
;
67 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
68 POBJECT_TYPE ParentObjectType
;
71 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
78 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
79 for the cache manager, so return STATUS_SUCCESS */
80 DPRINT("Parent object was NULL\n");
81 return(STATUS_SUCCESS
);
84 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
86 if (ParentObjectType
!= IoDeviceObjectType
&&
87 ParentObjectType
!= IoFileObjectType
)
89 CPRINT("Parent is a %S which is neither a file type nor a device type\n",
90 BODY_TO_HEADER(Parent
)->ObjectType
->TypeName
.Buffer
);
91 return(STATUS_UNSUCCESSFUL
);
94 Status
= ObReferenceObjectByPointer(Parent
,
95 STANDARD_RIGHTS_REQUIRED
,
98 if (!NT_SUCCESS(Status
))
100 CPRINT("Failed to reference parent object %x\n", Parent
);
104 if (ParentObjectType
== IoDeviceObjectType
)
106 /* Parent is a devce object */
107 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
108 DPRINT("DeviceObject %x\n", DeviceObject
);
110 if (RemainingPath
== NULL
)
112 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
113 FileObject
->FileName
.Buffer
= 0;
114 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
118 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
119 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
120 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
121 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
122 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
123 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
124 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
126 CPRINT("Device was wrong type\n");
127 return(STATUS_UNSUCCESSFUL
);
130 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
131 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
132 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
134 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
136 DPRINT("Mount the logical volume\n");
137 Status
= IoMountVolume(DeviceObject
, FALSE
);
138 DPRINT("Status %x\n", Status
);
139 if (!NT_SUCCESS(Status
))
141 CPRINT("Failed to mount logical volume (Status %x)\n",
146 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
147 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
149 RtlCreateUnicodeString(&(FileObject
->FileName
),
155 /* Parent is a file object */
156 if (RemainingPath
== NULL
)
158 CPRINT("Device is unnamed\n");
159 return STATUS_UNSUCCESSFUL
;
162 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
163 DPRINT("DeviceObject %x\n", DeviceObject
);
165 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
167 RtlCreateUnicodeString(&(FileObject
->FileName
),
171 DPRINT("FileObject->FileName %wZ\n",
172 &FileObject
->FileName
);
173 FileObject
->DeviceObject
= DeviceObject
;
174 DPRINT("FileObject %x DeviceObject %x\n",
177 FileObject
->Vpb
= DeviceObject
->Vpb
;
178 FileObject
->Type
= InternalFileType
;
180 return(STATUS_SUCCESS
);
184 /**********************************************************************
186 * IoCreateStreamFileObject@8
206 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
207 PDEVICE_OBJECT DeviceObject
)
209 PFILE_OBJECT CreatedFileObject
;
212 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
213 FileObject
, DeviceObject
);
215 ASSERT_IRQL(PASSIVE_LEVEL
);
217 Status
= ObCreateObject(KernelMode
,
225 (PVOID
*)&CreatedFileObject
);
226 if (!NT_SUCCESS(Status
))
228 DPRINT("Could not create FileObject\n");
232 if (FileObject
!= NULL
)
234 DeviceObject
= FileObject
->DeviceObject
;
236 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
238 DPRINT("DeviceObject %x\n", DeviceObject
);
240 CreatedFileObject
->DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
241 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
242 CreatedFileObject
->Type
= InternalFileType
;
243 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
245 // shouldn't we initialize the lock event, and several other things here too?
246 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
248 return CreatedFileObject
;
252 /**********************************************************************
257 * Either causes a new file or directory to be created, or it
258 * opens an existing file, device, directory or volume, giving
259 * the caller a handle for the file object. This handle can be
260 * used by subsequent calls to manipulate data within the file
261 * or the file object's state of attributes.
265 * Points to a variable which receives the file handle
269 * Desired access to the file;
272 * Structure describing the file;
274 * IoStatusBlock (OUT)
275 * Receives information about the operation on return;
277 * AllocationSize [OPTIONAL]
278 * Initial size of the file in bytes;
281 * Attributes to create the file with;
284 * Type of shared access the caller would like to the
288 * Specifies what to do, depending on whether the
289 * file already exists;
292 * Options for creating a new file;
294 * EaBuffer [OPTIONAL]
301 * Type of file (normal, named pipe, mailslot) to create;
303 * ExtraCreateParameters [OPTIONAL]
304 * Additional creation data for named pipe and mailsots;
313 * Prototype taken from Bo Branten's ntifs.h v15.
314 * Description taken from old NtCreateFile's which is
315 * now a wrapper of this call.
322 IoCreateFile(OUT PHANDLE FileHandle
,
323 IN ACCESS_MASK DesiredAccess
,
324 IN POBJECT_ATTRIBUTES ObjectAttributes
,
325 OUT PIO_STATUS_BLOCK IoStatusBlock
,
326 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
327 IN ULONG FileAttributes
,
328 IN ULONG ShareAccess
,
329 IN ULONG CreateDisposition
,
330 IN ULONG CreateOptions
,
331 IN PVOID EaBuffer OPTIONAL
,
333 IN CREATE_FILE_TYPE CreateFileType
,
334 IN PVOID ExtraCreateParameters OPTIONAL
,
337 PFILE_OBJECT FileObject
;
340 PIO_STACK_LOCATION StackLoc
;
341 IO_SECURITY_CONTEXT SecurityContext
;
342 KPROCESSOR_MODE PreviousMode
;
344 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
345 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
346 FileHandle
,DesiredAccess
,ObjectAttributes
,
347 ObjectAttributes
->ObjectName
->Buffer
);
349 ASSERT_IRQL(PASSIVE_LEVEL
);
351 if (IoStatusBlock
== NULL
)
352 return STATUS_ACCESS_VIOLATION
;
356 PreviousMode
= ExGetPreviousMode();
358 Status
= ObCreateObject(PreviousMode
,
366 (PVOID
*)&FileObject
);
367 if (!NT_SUCCESS(Status
))
369 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
373 RtlMapGenericMask(&DesiredAccess
,
374 BODY_TO_HEADER(FileObject
)->ObjectType
->Mapping
);
376 Status
= ObInsertObject ((PVOID
)FileObject
,
382 if (!NT_SUCCESS(Status
))
384 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
385 ObDereferenceObject (FileObject
);
389 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
391 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
393 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
395 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
398 if (CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
399 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
401 SecurityContext
.SecurityQos
= NULL
; /* ?? */
402 SecurityContext
.AccessState
= NULL
; /* ?? */
403 SecurityContext
.DesiredAccess
= DesiredAccess
;
404 SecurityContext
.FullCreateOptions
= 0; /* ?? */
406 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
407 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
409 DPRINT("FileObject %x\n", FileObject
);
410 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
412 * Create a new IRP to hand to
413 * the FS driver: this may fail
414 * due to resource shortage.
416 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
419 ZwClose(*FileHandle
);
420 return STATUS_UNSUCCESSFUL
;
423 //trigger FileObject/Event dereferencing
424 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
425 Irp
->RequestorMode
= PreviousMode
;
426 Irp
->UserIosb
= IoStatusBlock
;
427 Irp
->AssociatedIrp
.SystemBuffer
= EaBuffer
;
428 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= NULL
;
429 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
430 Irp
->UserEvent
= &FileObject
->Event
;
433 Irp
->Overlay
.AllocationSize
= *AllocationSize
;
437 * Get the stack location for the new
438 * IRP and prepare it.
440 StackLoc
= IoGetNextIrpStackLocation(Irp
);
441 StackLoc
->MinorFunction
= 0;
442 StackLoc
->Flags
= (UCHAR
)Options
;
443 StackLoc
->Control
= 0;
444 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
445 StackLoc
->FileObject
= FileObject
;
447 switch (CreateFileType
)
450 case CreateFileTypeNone
:
451 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
452 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
453 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
454 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
455 StackLoc
->Parameters
.Create
.FileAttributes
= (USHORT
)FileAttributes
;
456 StackLoc
->Parameters
.Create
.ShareAccess
= (USHORT
)ShareAccess
;
457 StackLoc
->Parameters
.Create
.EaLength
= EaLength
;
460 case CreateFileTypeNamedPipe
:
461 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
462 StackLoc
->Parameters
.CreatePipe
.SecurityContext
= &SecurityContext
;
463 StackLoc
->Parameters
.CreatePipe
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
464 StackLoc
->Parameters
.CreatePipe
.Options
|= (CreateDisposition
<< 24);
465 StackLoc
->Parameters
.CreatePipe
.ShareAccess
= (USHORT
)ShareAccess
;
466 StackLoc
->Parameters
.CreatePipe
.Parameters
= ExtraCreateParameters
;
469 case CreateFileTypeMailslot
:
470 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
471 StackLoc
->Parameters
.CreateMailslot
.SecurityContext
= &SecurityContext
;
472 StackLoc
->Parameters
.CreateMailslot
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
473 StackLoc
->Parameters
.CreateMailslot
.Options
|= (CreateDisposition
<< 24);
474 StackLoc
->Parameters
.CreateMailslot
.ShareAccess
= (USHORT
)ShareAccess
;
475 StackLoc
->Parameters
.CreateMailslot
.Parameters
= ExtraCreateParameters
;
480 * Now call the driver and
481 * possibly wait if it can
482 * not complete the request
485 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
487 if (Status
== STATUS_PENDING
)
489 KeWaitForSingleObject(&FileObject
->Event
,
494 Status
= IoStatusBlock
->Status
;
496 if (!NT_SUCCESS(Status
))
498 DPRINT("Failing create request with status %x\n", Status
);
499 FileObject
->DeviceObject
= NULL
;
500 FileObject
->Vpb
= NULL
;
502 ZwClose(*FileHandle
);
505 ASSERT_IRQL(PASSIVE_LEVEL
);
507 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
513 /**********************************************************************
518 * Entry point to call IoCreateFile with
519 * default parameters.
529 * Code originally in NtCreateFile moved in IoCreateFile.
534 NtCreateFile(PHANDLE FileHandle
,
535 ACCESS_MASK DesiredAccess
,
536 POBJECT_ATTRIBUTES ObjectAttributes
,
537 PIO_STATUS_BLOCK IoStatusBlock
,
538 PLARGE_INTEGER AllocateSize
,
539 ULONG FileAttributes
,
541 ULONG CreateDisposition
,
546 return IoCreateFile(FileHandle
,
563 /**********************************************************************
568 * Opens an existing file (simpler than NtCreateFile).
572 * Variable that receives the file handle on return;
575 * Access desired by the caller to the file;
578 * Structue describing the file to be opened;
580 * IoStatusBlock (OUT)
581 * Receives details about the result of the
585 * Type of shared access the caller requires;
588 * Options for the file open.
599 NtOpenFile(PHANDLE FileHandle
,
600 ACCESS_MASK DesiredAccess
,
601 POBJECT_ATTRIBUTES ObjectAttributes
,
602 PIO_STATUS_BLOCK IoStatusBlock
,
606 return IoCreateFile(FileHandle
,