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 DeviceObject = IoGetAttachedDevice(DeviceObject);
108 DPRINT("DeviceObject %x\n", DeviceObject);
110 if (NULL == RemainingPath)
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),
153 DPRINT("FileObject->FileName %wZ\n",
154 &FileObject->FileName);
155 FileObject->DeviceObject = DeviceObject;
156 DPRINT("FileObject %x DeviceObject %x\n",
159 FileObject->Vpb = DeviceObject->Vpb;
160 FileObject->Type = InternalFileType;
161 FileObject->RelatedFileObject = NULL;
163 return(STATUS_SUCCESS);
167 /**********************************************************************
169 * IoCreateStreamFileObject@8
188 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
189 PDEVICE_OBJECT DeviceObject)
192 PFILE_OBJECT CreatedFileObject;
195 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
196 FileObject, DeviceObject);
198 assert_irql(PASSIVE_LEVEL);
200 Status = ObCreateObject(&FileHandle,
201 STANDARD_RIGHTS_REQUIRED,
204 (PVOID*)&CreatedFileObject);
205 if (!NT_SUCCESS(Status))
207 DPRINT("Could not create FileObject\n");
211 if (FileObject != NULL)
213 DeviceObject = FileObject->DeviceObject;
215 DeviceObject = IoGetAttachedDevice(DeviceObject);
217 DPRINT("DeviceObject %x\n", DeviceObject);
219 CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
220 CreatedFileObject->Vpb = DeviceObject->Vpb;
221 CreatedFileObject->Type = InternalFileType;
222 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
224 // shouldn't we initialize the lock event, and several other things here too?
225 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
229 return(CreatedFileObject);
233 /**********************************************************************
238 * Either causes a new file or directory to be created, or it
239 * opens an existing file, device, directory or volume, giving
240 * the caller a handle for the file object. This handle can be
241 * used by subsequent calls to manipulate data within the file
242 * or the file object's state of attributes.
246 * Points to a variable which receives the file handle
250 * Desired access to the file;
253 * Structure describing the file;
255 * IoStatusBlock (OUT)
256 * Receives information about the operation on return;
258 * AllocationSize [OPTIONAL]
259 * Initial size of the file in bytes;
262 * Attributes to create the file with;
265 * Type of shared access the caller would like to the
269 * Specifies what to do, depending on whether the
270 * file already exists;
273 * Options for creating a new file;
275 * EaBuffer [OPTIONAL]
282 * Type of file (normal, named pipe, mailslot) to create;
284 * ExtraCreateParameters [OPTIONAL]
285 * Additional creation data for named pipe and mailsots;
294 * Prototype taken from Bo Branten's ntifs.h v15.
295 * Description taken from old NtCreateFile's which is
296 * now a wrapper of this call.
302 IoCreateFile(OUT PHANDLE FileHandle,
303 IN ACCESS_MASK DesiredAccess,
304 IN POBJECT_ATTRIBUTES ObjectAttributes,
305 OUT PIO_STATUS_BLOCK IoStatusBlock,
306 IN PLARGE_INTEGER AllocationSize OPTIONAL,
307 IN ULONG FileAttributes,
308 IN ULONG ShareAccess,
309 IN ULONG CreateDisposition,
310 IN ULONG CreateOptions,
311 IN PVOID EaBuffer OPTIONAL,
313 IN CREATE_FILE_TYPE CreateFileType,
314 IN PVOID ExtraCreateParameters OPTIONAL,
317 PFILE_OBJECT FileObject;
320 PIO_STACK_LOCATION StackLoc;
321 IO_STATUS_BLOCK IoSB;
322 IO_SECURITY_CONTEXT SecurityContext;
324 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
325 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
326 FileHandle,DesiredAccess,ObjectAttributes,
327 ObjectAttributes->ObjectName->Buffer);
329 assert_irql(PASSIVE_LEVEL);
333 Status = ObCreateObject(FileHandle,
337 (PVOID*)&FileObject);
338 if (!NT_SUCCESS(Status))
340 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
343 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
345 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
347 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
349 FileObject->Flags |= FO_SYNCHRONOUS_IO;
352 if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
353 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
355 SecurityContext.SecurityQos = NULL; /* ?? */
356 SecurityContext.AccessState = NULL; /* ?? */
357 SecurityContext.DesiredAccess = DesiredAccess;
358 SecurityContext.FullCreateOptions = 0; /* ?? */
360 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
361 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
363 DPRINT("FileObject %x\n", FileObject);
364 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
366 * Create a new IRP to hand to
367 * the FS driver: this may fail
368 * due to resource shortage.
370 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
373 ZwClose(*FileHandle);
374 return (STATUS_UNSUCCESSFUL);
377 Irp->UserIosb = &IoSB; //return iostatus
378 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
379 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
380 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
381 Irp->UserEvent = &FileObject->Event;
384 Irp->Overlay.AllocationSize = *AllocationSize;
388 * Get the stack location for the new
389 * IRP and prepare it.
391 StackLoc = IoGetNextIrpStackLocation(Irp);
392 switch (CreateFileType)
395 case CreateFileTypeNone:
396 StackLoc->MajorFunction = IRP_MJ_CREATE;
399 case CreateFileTypeNamedPipe:
400 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
403 case CreateFileTypeMailslot:
404 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
407 StackLoc->MinorFunction = 0;
408 StackLoc->Flags = Options;
409 StackLoc->Control = 0;
410 StackLoc->DeviceObject = FileObject->DeviceObject;
411 StackLoc->FileObject = FileObject;
412 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
413 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
414 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
415 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
416 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
417 StackLoc->Parameters.Create.EaLength = EaLength;
420 * Now call the driver and
421 * possibly wait if it can
422 * not complete the request
425 Status = IofCallDriver(FileObject->DeviceObject, Irp );
427 if (Status == STATUS_PENDING)
429 KeWaitForSingleObject(&FileObject->Event,
434 Status = IoSB.Status;
436 if (!NT_SUCCESS(Status))
438 DPRINT("Failing create request with status %x\n", Status);
439 FileObject->DeviceObject = NULL;
440 FileObject->Vpb = NULL;
442 ZwClose(*FileHandle);
446 *IoStatusBlock = IoSB;
448 assert_irql(PASSIVE_LEVEL);
450 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
457 /**********************************************************************
462 * Entry point to call IoCreateFile with
463 * default parameters.
473 * Code originally in NtCreateFile moved in IoCreateFile.
476 NtCreateFile(PHANDLE FileHandle,
477 ACCESS_MASK DesiredAccess,
478 POBJECT_ATTRIBUTES ObjectAttributes,
479 PIO_STATUS_BLOCK IoStatusBlock,
480 PLARGE_INTEGER AllocateSize,
481 ULONG FileAttributes,
483 ULONG CreateDisposition,
488 return IoCreateFile(FileHandle,
505 /**********************************************************************
510 * Opens an existing file (simpler than NtCreateFile).
514 * Variable that receives the file handle on return;
517 * Access desired by the caller to the file;
520 * Structue describing the file to be opened;
522 * IoStatusBlock (OUT)
523 * Receives details about the result of the
527 * Type of shared access the caller requires;
530 * Options for the file open.
539 NtOpenFile(PHANDLE FileHandle,
540 ACCESS_MASK DesiredAccess,
541 POBJECT_ATTRIBUTES ObjectAttributes,
542 PIO_STATUS_BLOCK IoStatusBlock,
546 return IoCreateFile(FileHandle,
562 #endif /* LIBCAPTIVE */