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 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/io.h>
17 #include <internal/id.h>
18 #include <internal/pool.h>
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
27 /* FUNCTIONS *************************************************************/
31 /**********************************************************************
47 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
52 #endif /* LIBCAPTIVE */
54 /**********************************************************************
68 IopCreateFile(PVOID ObjectBody,
71 POBJECT_ATTRIBUTES ObjectAttributes)
73 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Parent;
74 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
77 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
82 if (NULL == DeviceObject)
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("DeviceObject was NULL\n");
87 return(STATUS_SUCCESS);
90 if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType)
92 CPRINT("Parent is a %S which is not a device type\n",
93 BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer);
94 return(STATUS_UNSUCCESSFUL);
97 Status = ObReferenceObjectByPointer(DeviceObject,
98 STANDARD_RIGHTS_REQUIRED,
101 if (!NT_SUCCESS(Status))
103 CPRINT("Failed to reference device object %x\n", DeviceObject);
107 FileObject->Flags = 0;
109 DeviceObject = IoGetAttachedDevice(DeviceObject);
110 DPRINT("DeviceObject %x\n", DeviceObject);
112 if (NULL == RemainingPath)
114 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
115 FileObject->FileName.Buffer = 0;
116 FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
120 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
121 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
122 && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
123 && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
124 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
125 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
126 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
128 CPRINT("Device was wrong type\n");
129 return(STATUS_UNSUCCESSFUL);
132 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
133 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
134 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
136 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
138 DPRINT("Mount the logical volume\n");
139 Status = IoMountVolume(DeviceObject, FALSE);
140 DPRINT("Status %x\n", Status);
141 if (!NT_SUCCESS(Status))
143 CPRINT("Failed to mount logical volume (Status %x)\n",
148 DeviceObject = DeviceObject->Vpb->DeviceObject;
149 DPRINT("FsDeviceObject %lx\n", DeviceObject);
151 RtlCreateUnicodeString(&(FileObject->FileName),
155 DPRINT("FileObject->FileName %wZ\n",
156 &FileObject->FileName);
157 FileObject->DeviceObject = DeviceObject;
158 DPRINT("FileObject %x DeviceObject %x\n",
161 FileObject->Vpb = DeviceObject->Vpb;
162 FileObject->Type = InternalFileType;
163 FileObject->RelatedFileObject = NULL;
165 return(STATUS_SUCCESS);
169 /**********************************************************************
171 * IoCreateStreamFileObject@8
190 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
191 PDEVICE_OBJECT DeviceObject)
194 PFILE_OBJECT CreatedFileObject;
197 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
198 FileObject, DeviceObject);
200 assert_irql(PASSIVE_LEVEL);
202 Status = ObCreateObject(&FileHandle,
203 STANDARD_RIGHTS_REQUIRED,
206 (PVOID*)&CreatedFileObject);
207 if (!NT_SUCCESS(Status))
209 DPRINT("Could not create FileObject\n");
213 if (FileObject != NULL)
215 DeviceObject = FileObject->DeviceObject;
217 DeviceObject = IoGetAttachedDevice(DeviceObject);
219 DPRINT("DeviceObject %x\n", DeviceObject);
221 CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
222 CreatedFileObject->Vpb = DeviceObject->Vpb;
223 CreatedFileObject->Type = InternalFileType;
224 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
226 // shouldn't we initialize the lock event, and several other things here too?
227 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
231 return(CreatedFileObject);
235 /**********************************************************************
240 * Either causes a new file or directory to be created, or it
241 * opens an existing file, device, directory or volume, giving
242 * the caller a handle for the file object. This handle can be
243 * used by subsequent calls to manipulate data within the file
244 * or the file object's state of attributes.
248 * Points to a variable which receives the file handle
252 * Desired access to the file;
255 * Structure describing the file;
257 * IoStatusBlock (OUT)
258 * Receives information about the operation on return;
260 * AllocationSize [OPTIONAL]
261 * Initial size of the file in bytes;
264 * Attributes to create the file with;
267 * Type of shared access the caller would like to the
271 * Specifies what to do, depending on whether the
272 * file already exists;
275 * Options for creating a new file;
277 * EaBuffer [OPTIONAL]
284 * Type of file (normal, named pipe, mailslot) to create;
286 * ExtraCreateParameters [OPTIONAL]
287 * Additional creation data for named pipe and mailsots;
296 * Prototype taken from Bo Branten's ntifs.h v15.
297 * Description taken from old NtCreateFile's which is
298 * now a wrapper of this call.
304 IoCreateFile(OUT PHANDLE FileHandle,
305 IN ACCESS_MASK DesiredAccess,
306 IN POBJECT_ATTRIBUTES ObjectAttributes,
307 OUT PIO_STATUS_BLOCK IoStatusBlock,
308 IN PLARGE_INTEGER AllocationSize OPTIONAL,
309 IN ULONG FileAttributes,
310 IN ULONG ShareAccess,
311 IN ULONG CreateDisposition,
312 IN ULONG CreateOptions,
313 IN PVOID EaBuffer OPTIONAL,
315 IN CREATE_FILE_TYPE CreateFileType,
316 IN PVOID ExtraCreateParameters OPTIONAL,
319 PFILE_OBJECT FileObject;
322 PIO_STACK_LOCATION StackLoc;
323 IO_STATUS_BLOCK IoSB;
324 IO_SECURITY_CONTEXT SecurityContext;
326 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
327 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
328 FileHandle,DesiredAccess,ObjectAttributes,
329 ObjectAttributes->ObjectName->Buffer);
331 assert_irql(PASSIVE_LEVEL);
335 Status = ObCreateObject(FileHandle,
339 (PVOID*)&FileObject);
340 if (!NT_SUCCESS(Status))
342 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
345 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
347 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
349 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
351 FileObject->Flags |= FO_SYNCHRONOUS_IO;
354 if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
355 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
357 SecurityContext.SecurityQos = NULL; /* ?? */
358 SecurityContext.AccessState = NULL; /* ?? */
359 SecurityContext.DesiredAccess = DesiredAccess;
360 SecurityContext.FullCreateOptions = 0; /* ?? */
362 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
363 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
365 DPRINT("FileObject %x\n", FileObject);
366 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
368 * Create a new IRP to hand to
369 * the FS driver: this may fail
370 * due to resource shortage.
372 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
375 ZwClose(*FileHandle);
376 return (STATUS_UNSUCCESSFUL);
379 Irp->UserIosb = &IoSB; //return iostatus
380 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
381 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
382 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
383 Irp->UserEvent = &FileObject->Event;
386 Irp->Overlay.AllocationSize = *AllocationSize;
390 * Get the stack location for the new
391 * IRP and prepare it.
393 StackLoc = IoGetNextIrpStackLocation(Irp);
394 switch (CreateFileType)
397 case CreateFileTypeNone:
398 StackLoc->MajorFunction = IRP_MJ_CREATE;
401 case CreateFileTypeNamedPipe:
402 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
405 case CreateFileTypeMailslot:
406 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
409 StackLoc->MinorFunction = 0;
410 StackLoc->Flags = Options;
411 StackLoc->Control = 0;
412 StackLoc->DeviceObject = FileObject->DeviceObject;
413 StackLoc->FileObject = FileObject;
414 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
415 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
416 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
417 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
418 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
419 StackLoc->Parameters.Create.EaLength = EaLength;
422 * Now call the driver and
423 * possibly wait if it can
424 * not complete the request
427 Status = IofCallDriver(FileObject->DeviceObject, Irp );
429 if (Status == STATUS_PENDING)
431 KeWaitForSingleObject(&FileObject->Event,
436 Status = IoSB.Status;
438 if (!NT_SUCCESS(Status))
440 DPRINT("Failing create request with status %x\n", Status);
441 FileObject->DeviceObject = NULL;
442 FileObject->Vpb = NULL;
444 ZwClose(*FileHandle);
448 *IoStatusBlock = IoSB;
450 assert_irql(PASSIVE_LEVEL);
452 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
459 /**********************************************************************
464 * Entry point to call IoCreateFile with
465 * default parameters.
475 * Code originally in NtCreateFile moved in IoCreateFile.
478 NtCreateFile(PHANDLE FileHandle,
479 ACCESS_MASK DesiredAccess,
480 POBJECT_ATTRIBUTES ObjectAttributes,
481 PIO_STATUS_BLOCK IoStatusBlock,
482 PLARGE_INTEGER AllocateSize,
483 ULONG FileAttributes,
485 ULONG CreateDisposition,
490 return IoCreateFile(FileHandle,
507 /**********************************************************************
512 * Opens an existing file (simpler than NtCreateFile).
516 * Variable that receives the file handle on return;
519 * Access desired by the caller to the file;
522 * Structue describing the file to be opened;
524 * IoStatusBlock (OUT)
525 * Receives details about the result of the
529 * Type of shared access the caller requires;
532 * Options for the file open.
541 NtOpenFile(PHANDLE FileHandle,
542 ACCESS_MASK DesiredAccess,
543 POBJECT_ATTRIBUTES ObjectAttributes,
544 PIO_STATUS_BLOCK IoStatusBlock,
548 return IoCreateFile(FileHandle,
564 #endif /* LIBCAPTIVE */