1 /* $Id: create.c,v 1.71 2003/12/14 17:44:02 hbirr Exp $
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 ***************************************************************/
14 #define NTOS_MODE_KERNEL
16 #include <internal/ob.h>
17 #include <internal/io.h>
18 #include <internal/id.h>
19 #include <internal/pool.h>
22 #include <internal/debug.h>
24 /* GLOBALS *******************************************************************/
26 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
28 /* FUNCTIONS *************************************************************/
30 /**********************************************************************
47 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
50 return(STATUS_NOT_IMPLEMENTED
);
54 /**********************************************************************
67 IopCreateFile(PVOID ObjectBody
,
70 POBJECT_ATTRIBUTES ObjectAttributes
)
72 PDEVICE_OBJECT DeviceObject
;
73 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
74 POBJECT_TYPE ParentObjectType
;
77 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
84 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
85 for the cache manager, so return STATUS_SUCCESS */
86 DPRINT("Parent object was NULL\n");
87 return(STATUS_SUCCESS
);
90 ParentObjectType
= BODY_TO_HEADER(Parent
)->ObjectType
;
92 if (ParentObjectType
!= IoDeviceObjectType
&&
93 ParentObjectType
!= IoFileObjectType
)
95 CPRINT("Parent is a %S which is neither a file type nor a device type\n",
96 BODY_TO_HEADER(Parent
)->ObjectType
->TypeName
.Buffer
);
97 return(STATUS_UNSUCCESSFUL
);
100 Status
= ObReferenceObjectByPointer(Parent
,
101 STANDARD_RIGHTS_REQUIRED
,
104 if (!NT_SUCCESS(Status
))
106 CPRINT("Failed to reference parent object %x\n", Parent
);
110 if (ParentObjectType
== IoDeviceObjectType
)
112 /* Parent is a devce object */
113 DeviceObject
= IoGetAttachedDevice((PDEVICE_OBJECT
)Parent
);
114 DPRINT("DeviceObject %x\n", DeviceObject
);
116 if (RemainingPath
== NULL
)
118 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
119 FileObject
->FileName
.Buffer
= 0;
120 FileObject
->FileName
.Length
= FileObject
->FileName
.MaximumLength
= 0;
124 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
125 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
126 && (DeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
)
127 && (DeviceObject
->DeviceType
!= FILE_DEVICE_TAPE
)
128 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
129 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
130 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
132 CPRINT("Device was wrong type\n");
133 return(STATUS_UNSUCCESSFUL
);
136 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
137 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
138 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
140 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
142 DPRINT("Mount the logical volume\n");
143 Status
= IoMountVolume(DeviceObject
, FALSE
);
144 DPRINT("Status %x\n", Status
);
145 if (!NT_SUCCESS(Status
))
147 CPRINT("Failed to mount logical volume (Status %x)\n",
152 DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
153 DPRINT("FsDeviceObject %lx\n", DeviceObject
);
155 RtlCreateUnicodeString(&(FileObject
->FileName
),
161 /* Parent is a file object */
162 if (RemainingPath
== NULL
)
164 CPRINT("Device is unnamed\n");
165 return STATUS_UNSUCCESSFUL
;
168 DeviceObject
= ((PFILE_OBJECT
)Parent
)->DeviceObject
;
169 DPRINT("DeviceObject %x\n", DeviceObject
);
171 FileObject
->RelatedFileObject
= (PFILE_OBJECT
)Parent
;
173 RtlCreateUnicodeString(&(FileObject
->FileName
),
177 DPRINT("FileObject->FileName %wZ\n",
178 &FileObject
->FileName
);
179 FileObject
->DeviceObject
= DeviceObject
;
180 DPRINT("FileObject %x DeviceObject %x\n",
183 FileObject
->Vpb
= DeviceObject
->Vpb
;
184 FileObject
->Type
= InternalFileType
;
186 return(STATUS_SUCCESS
);
190 /**********************************************************************
192 * IoCreateStreamFileObject@8
212 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
213 PDEVICE_OBJECT DeviceObject
)
215 PFILE_OBJECT CreatedFileObject
;
218 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
219 FileObject
, DeviceObject
);
221 assert_irql(PASSIVE_LEVEL
);
223 Status
= ObCreateObject(KernelMode
,
231 (PVOID
*)&CreatedFileObject
);
232 if (!NT_SUCCESS(Status
))
234 DPRINT("Could not create FileObject\n");
238 if (FileObject
!= NULL
)
240 DeviceObject
= FileObject
->DeviceObject
;
242 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
244 DPRINT("DeviceObject %x\n", DeviceObject
);
246 CreatedFileObject
->DeviceObject
= DeviceObject
->Vpb
->DeviceObject
;
247 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
248 CreatedFileObject
->Type
= InternalFileType
;
249 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
251 // shouldn't we initialize the lock event, and several other things here too?
252 KeInitializeEvent(&CreatedFileObject
->Event
, NotificationEvent
, FALSE
);
254 return CreatedFileObject
;
258 /**********************************************************************
263 * Either causes a new file or directory to be created, or it
264 * opens an existing file, device, directory or volume, giving
265 * the caller a handle for the file object. This handle can be
266 * used by subsequent calls to manipulate data within the file
267 * or the file object's state of attributes.
271 * Points to a variable which receives the file handle
275 * Desired access to the file;
278 * Structure describing the file;
280 * IoStatusBlock (OUT)
281 * Receives information about the operation on return;
283 * AllocationSize [OPTIONAL]
284 * Initial size of the file in bytes;
287 * Attributes to create the file with;
290 * Type of shared access the caller would like to the
294 * Specifies what to do, depending on whether the
295 * file already exists;
298 * Options for creating a new file;
300 * EaBuffer [OPTIONAL]
307 * Type of file (normal, named pipe, mailslot) to create;
309 * ExtraCreateParameters [OPTIONAL]
310 * Additional creation data for named pipe and mailsots;
319 * Prototype taken from Bo Branten's ntifs.h v15.
320 * Description taken from old NtCreateFile's which is
321 * now a wrapper of this call.
328 IoCreateFile(OUT PHANDLE FileHandle
,
329 IN ACCESS_MASK DesiredAccess
,
330 IN POBJECT_ATTRIBUTES ObjectAttributes
,
331 OUT PIO_STATUS_BLOCK IoStatusBlock
,
332 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
333 IN ULONG FileAttributes
,
334 IN ULONG ShareAccess
,
335 IN ULONG CreateDisposition
,
336 IN ULONG CreateOptions
,
337 IN PVOID EaBuffer OPTIONAL
,
339 IN CREATE_FILE_TYPE CreateFileType
,
340 IN PVOID ExtraCreateParameters OPTIONAL
,
343 PFILE_OBJECT FileObject
;
346 PIO_STACK_LOCATION StackLoc
;
347 IO_SECURITY_CONTEXT SecurityContext
;
348 KPROCESSOR_MODE PreviousMode
;
350 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
351 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
352 FileHandle
,DesiredAccess
,ObjectAttributes
,
353 ObjectAttributes
->ObjectName
->Buffer
);
355 assert_irql(PASSIVE_LEVEL
);
357 if (IoStatusBlock
== NULL
)
358 return STATUS_ACCESS_VIOLATION
;
362 PreviousMode
= ExGetPreviousMode();
364 Status
= ObCreateObject(PreviousMode
,
372 (PVOID
*)&FileObject
);
373 if (!NT_SUCCESS(Status
))
375 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status
);
379 Status
= ObInsertObject ((PVOID
)FileObject
,
385 if (!NT_SUCCESS(Status
))
387 DPRINT("ObInsertObject() failed! (Status %lx)\n", Status
);
388 ObDereferenceObject (FileObject
);
392 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
394 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
396 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
398 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
401 if( CreateOptions
& FILE_NO_INTERMEDIATE_BUFFERING
)
402 FileObject
->Flags
|= FO_NO_INTERMEDIATE_BUFFERING
;
404 SecurityContext
.SecurityQos
= NULL
; /* ?? */
405 SecurityContext
.AccessState
= NULL
; /* ?? */
406 SecurityContext
.DesiredAccess
= DesiredAccess
;
407 SecurityContext
.FullCreateOptions
= 0; /* ?? */
409 KeInitializeEvent(&FileObject
->Lock
, SynchronizationEvent
, TRUE
);
410 KeInitializeEvent(&FileObject
->Event
, NotificationEvent
, FALSE
);
412 DPRINT("FileObject %x\n", FileObject
);
413 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
415 * Create a new IRP to hand to
416 * the FS driver: this may fail
417 * due to resource shortage.
419 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
422 ZwClose(*FileHandle
);
423 return (STATUS_UNSUCCESSFUL
);
426 //trigger FileObject/Event dereferencing
427 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
428 Irp
->RequestorMode
= PreviousMode
;
429 Irp
->UserIosb
= IoStatusBlock
;
430 Irp
->AssociatedIrp
.SystemBuffer
= EaBuffer
;
431 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PCHAR
)ExtraCreateParameters
;
432 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
433 Irp
->UserEvent
= &FileObject
->Event
;
436 Irp
->Overlay
.AllocationSize
= *AllocationSize
;
440 * Get the stack location for the new
441 * IRP and prepare it.
443 StackLoc
= IoGetNextIrpStackLocation(Irp
);
444 switch (CreateFileType
)
447 case CreateFileTypeNone
:
448 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
451 case CreateFileTypeNamedPipe
:
452 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
455 case CreateFileTypeMailslot
:
456 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
459 StackLoc
->MinorFunction
= 0;
460 StackLoc
->Flags
= Options
;
461 StackLoc
->Control
= 0;
462 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
463 StackLoc
->FileObject
= FileObject
;
464 StackLoc
->Parameters
.Create
.SecurityContext
= &SecurityContext
;
465 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
466 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
467 StackLoc
->Parameters
.Create
.FileAttributes
= FileAttributes
;
468 StackLoc
->Parameters
.Create
.ShareAccess
= ShareAccess
;
469 StackLoc
->Parameters
.Create
.EaLength
= EaLength
;
472 * Now call the driver and
473 * possibly wait if it can
474 * not complete the request
477 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
479 if (Status
== STATUS_PENDING
)
481 KeWaitForSingleObject(&FileObject
->Event
,
486 Status
= IoStatusBlock
->Status
;
488 if (!NT_SUCCESS(Status
))
490 DPRINT("Failing create request with status %x\n", Status
);
491 FileObject
->DeviceObject
= NULL
;
492 FileObject
->Vpb
= NULL
;
494 ZwClose(*FileHandle
);
497 assert_irql(PASSIVE_LEVEL
);
499 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
505 /**********************************************************************
510 * Entry point to call IoCreateFile with
511 * default parameters.
521 * Code originally in NtCreateFile moved in IoCreateFile.
526 NtCreateFile(PHANDLE FileHandle
,
527 ACCESS_MASK DesiredAccess
,
528 POBJECT_ATTRIBUTES ObjectAttributes
,
529 PIO_STATUS_BLOCK IoStatusBlock
,
530 PLARGE_INTEGER AllocateSize
,
531 ULONG FileAttributes
,
533 ULONG CreateDisposition
,
538 return IoCreateFile(FileHandle
,
555 /**********************************************************************
560 * Opens an existing file (simpler than NtCreateFile).
564 * Variable that receives the file handle on return;
567 * Access desired by the caller to the file;
570 * Structue describing the file to be opened;
572 * IoStatusBlock (OUT)
573 * Receives details about the result of the
577 * Type of shared access the caller requires;
580 * Options for the file open.
591 NtOpenFile(PHANDLE FileHandle
,
592 ACCESS_MASK DesiredAccess
,
593 POBJECT_ATTRIBUTES ObjectAttributes
,
594 PIO_STATUS_BLOCK IoStatusBlock
,
598 return IoCreateFile(FileHandle
,