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)
53 /**********************************************************************
66 IopCreateFile(PVOID ObjectBody,
69 POBJECT_ATTRIBUTES ObjectAttributes)
71 PDEVICE_OBJECT DeviceObject;
72 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
73 POBJECT_TYPE ParentObjectType;
76 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
83 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
84 for the cache manager, so return STATUS_SUCCESS */
85 DPRINT("Parent object was NULL\n");
86 return(STATUS_SUCCESS);
89 ParentObjectType = BODY_TO_HEADER(Parent)->ObjectType;
91 if (ParentObjectType != IoDeviceObjectType &&
92 ParentObjectType != IoFileObjectType)
94 CPRINT("Parent is a %S which is neither a file type nor a device type\n",
95 BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer);
96 return(STATUS_UNSUCCESSFUL);
99 Status = ObReferenceObjectByPointer(Parent,
100 STANDARD_RIGHTS_REQUIRED,
103 if (!NT_SUCCESS(Status))
105 CPRINT("Failed to reference parent object %x\n", Parent);
109 if (ParentObjectType == IoDeviceObjectType)
111 /* Parent is a devce object */
112 DeviceObject = IoGetAttachedDevice((PDEVICE_OBJECT)Parent);
113 DPRINT("DeviceObject %x\n", DeviceObject);
115 if (RemainingPath == NULL)
117 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
118 FileObject->FileName.Buffer = 0;
119 FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
123 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
124 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
125 && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
126 && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
127 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
128 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
129 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
131 CPRINT("Device was wrong type\n");
132 return(STATUS_UNSUCCESSFUL);
135 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
136 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
137 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
139 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
141 DPRINT("Mount the logical volume\n");
142 Status = IoMountVolume(DeviceObject, FALSE);
143 DPRINT("Status %x\n", Status);
144 if (!NT_SUCCESS(Status))
146 CPRINT("Failed to mount logical volume (Status %x)\n",
151 DeviceObject = DeviceObject->Vpb->DeviceObject;
152 DPRINT("FsDeviceObject %lx\n", DeviceObject);
154 RtlCreateUnicodeString(&(FileObject->FileName),
160 /* Parent is a file object */
161 if (RemainingPath == NULL)
163 CPRINT("Device is unnamed\n");
164 return STATUS_UNSUCCESSFUL;
167 DeviceObject = ((PFILE_OBJECT)Parent)->DeviceObject;
168 DPRINT("DeviceObject %x\n", DeviceObject);
170 FileObject->RelatedFileObject = (PFILE_OBJECT)Parent;
172 RtlCreateUnicodeString(&(FileObject->FileName),
176 DPRINT("FileObject->FileName %wZ\n",
177 &FileObject->FileName);
178 FileObject->DeviceObject = DeviceObject;
179 DPRINT("FileObject %x DeviceObject %x\n",
182 FileObject->Vpb = DeviceObject->Vpb;
183 FileObject->Type = InternalFileType;
185 return(STATUS_SUCCESS);
189 /**********************************************************************
191 * IoCreateStreamFileObject@8
211 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
212 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 = ObRosCreateObject(&FileHandle,
224 STANDARD_RIGHTS_REQUIRED,
227 (PVOID*)&CreatedFileObject);
228 if (!NT_SUCCESS(Status))
230 DPRINT("Could not create FileObject\n");
234 if (FileObject != NULL)
236 DeviceObject = FileObject->DeviceObject;
238 DeviceObject = IoGetAttachedDevice(DeviceObject);
240 DPRINT("DeviceObject %x\n", DeviceObject);
242 CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
243 CreatedFileObject->Vpb = DeviceObject->Vpb;
244 CreatedFileObject->Type = InternalFileType;
245 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
247 // shouldn't we initialize the lock event, and several other things here too?
248 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
252 return(CreatedFileObject);
256 /**********************************************************************
261 * Either causes a new file or directory to be created, or it
262 * opens an existing file, device, directory or volume, giving
263 * the caller a handle for the file object. This handle can be
264 * used by subsequent calls to manipulate data within the file
265 * or the file object's state of attributes.
269 * Points to a variable which receives the file handle
273 * Desired access to the file;
276 * Structure describing the file;
278 * IoStatusBlock (OUT)
279 * Receives information about the operation on return;
281 * AllocationSize [OPTIONAL]
282 * Initial size of the file in bytes;
285 * Attributes to create the file with;
288 * Type of shared access the caller would like to the
292 * Specifies what to do, depending on whether the
293 * file already exists;
296 * Options for creating a new file;
298 * EaBuffer [OPTIONAL]
305 * Type of file (normal, named pipe, mailslot) to create;
307 * ExtraCreateParameters [OPTIONAL]
308 * Additional creation data for named pipe and mailsots;
317 * Prototype taken from Bo Branten's ntifs.h v15.
318 * Description taken from old NtCreateFile's which is
319 * now a wrapper of this call.
326 IoCreateFile(OUT PHANDLE FileHandle,
327 IN ACCESS_MASK DesiredAccess,
328 IN POBJECT_ATTRIBUTES ObjectAttributes,
329 OUT PIO_STATUS_BLOCK IoStatusBlock,
330 IN PLARGE_INTEGER AllocationSize OPTIONAL,
331 IN ULONG FileAttributes,
332 IN ULONG ShareAccess,
333 IN ULONG CreateDisposition,
334 IN ULONG CreateOptions,
335 IN PVOID EaBuffer OPTIONAL,
337 IN CREATE_FILE_TYPE CreateFileType,
338 IN PVOID ExtraCreateParameters OPTIONAL,
341 PFILE_OBJECT FileObject;
344 PIO_STACK_LOCATION StackLoc;
345 IO_STATUS_BLOCK IoSB;
346 IO_SECURITY_CONTEXT SecurityContext;
348 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
349 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
350 FileHandle,DesiredAccess,ObjectAttributes,
351 ObjectAttributes->ObjectName->Buffer);
353 assert_irql(PASSIVE_LEVEL);
357 Status = ObRosCreateObject(FileHandle,
361 (PVOID*)&FileObject);
362 if (!NT_SUCCESS(Status))
364 DPRINT("ObRosCreateObject() failed! (Status %lx)\n", Status);
367 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
369 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
371 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
373 FileObject->Flags |= FO_SYNCHRONOUS_IO;
376 if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
377 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
379 SecurityContext.SecurityQos = NULL; /* ?? */
380 SecurityContext.AccessState = NULL; /* ?? */
381 SecurityContext.DesiredAccess = DesiredAccess;
382 SecurityContext.FullCreateOptions = 0; /* ?? */
384 KeInitializeEvent(&FileObject->Lock, SynchronizationEvent, TRUE);
385 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
387 DPRINT("FileObject %x\n", FileObject);
388 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
390 * Create a new IRP to hand to
391 * the FS driver: this may fail
392 * due to resource shortage.
394 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
397 ZwClose(*FileHandle);
398 return (STATUS_UNSUCCESSFUL);
401 //trigger FileObject/Event dereferencing
402 Irp->Tail.Overlay.OriginalFileObject = FileObject;
404 Irp->UserIosb = &IoSB; //return iostatus
405 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
406 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
407 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
408 Irp->UserEvent = &FileObject->Event;
411 Irp->Overlay.AllocationSize = *AllocationSize;
415 * Get the stack location for the new
416 * IRP and prepare it.
418 StackLoc = IoGetNextIrpStackLocation(Irp);
419 switch (CreateFileType)
422 case CreateFileTypeNone:
423 StackLoc->MajorFunction = IRP_MJ_CREATE;
426 case CreateFileTypeNamedPipe:
427 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
430 case CreateFileTypeMailslot:
431 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
434 StackLoc->MinorFunction = 0;
435 StackLoc->Flags = Options;
436 StackLoc->Control = 0;
437 StackLoc->DeviceObject = FileObject->DeviceObject;
438 StackLoc->FileObject = FileObject;
439 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
440 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
441 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
442 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
443 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
444 StackLoc->Parameters.Create.EaLength = EaLength;
447 * Now call the driver and
448 * possibly wait if it can
449 * not complete the request
452 Status = IofCallDriver(FileObject->DeviceObject, Irp );
454 if (Status == STATUS_PENDING)
456 KeWaitForSingleObject(&FileObject->Event,
461 Status = IoSB.Status;
463 if (!NT_SUCCESS(Status))
465 DPRINT("Failing create request with status %x\n", Status);
466 FileObject->DeviceObject = NULL;
467 FileObject->Vpb = NULL;
469 ZwClose(*FileHandle);
473 *IoStatusBlock = IoSB;
475 assert_irql(PASSIVE_LEVEL);
477 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
483 /**********************************************************************
488 * Entry point to call IoCreateFile with
489 * default parameters.
499 * Code originally in NtCreateFile moved in IoCreateFile.
504 NtCreateFile(PHANDLE FileHandle,
505 ACCESS_MASK DesiredAccess,
506 POBJECT_ATTRIBUTES ObjectAttributes,
507 PIO_STATUS_BLOCK IoStatusBlock,
508 PLARGE_INTEGER AllocateSize,
509 ULONG FileAttributes,
511 ULONG CreateDisposition,
516 return IoCreateFile(FileHandle,
533 /**********************************************************************
538 * Opens an existing file (simpler than NtCreateFile).
542 * Variable that receives the file handle on return;
545 * Access desired by the caller to the file;
548 * Structue describing the file to be opened;
550 * IoStatusBlock (OUT)
551 * Receives details about the result of the
555 * Type of shared access the caller requires;
558 * Options for the file open.
569 NtOpenFile(PHANDLE FileHandle,
570 ACCESS_MASK DesiredAccess,
571 POBJECT_ATTRIBUTES ObjectAttributes,
572 PIO_STATUS_BLOCK IoStatusBlock,
576 return IoCreateFile(FileHandle,