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)
193 PFILE_OBJECT CreatedFileObject;
196 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
197 FileObject, DeviceObject);
199 assert_irql(PASSIVE_LEVEL);
201 /* We don't need any 'Handle' therefore pass 1st parameter as NULL and it
202 * will not be created by ObCreateObject() at all.
204 Status = ObCreateObject(NULL,
205 STANDARD_RIGHTS_REQUIRED,
208 (PVOID*)&CreatedFileObject);
209 if (!NT_SUCCESS(Status))
211 DPRINT("Could not create FileObject\n");
215 if (FileObject != NULL)
217 DeviceObject = FileObject->DeviceObject;
219 DeviceObject = IoGetAttachedDevice(DeviceObject);
221 DPRINT("DeviceObject %x\n", DeviceObject);
223 CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
224 CreatedFileObject->Vpb = DeviceObject->Vpb;
225 CreatedFileObject->Type = InternalFileType;
226 /* Why was FO_DIRECT_DEVICE_OPEN used here before?
227 * FO_STREAM_FILE is according to W32 documentation.
229 CreatedFileObject->Flags |= FO_STREAM_FILE;
231 /* We are fully single-threaded/single-processed;
232 * prevent at least IopDeleteFile()->...->IoIsOperationSynchronous() to return FALSE
234 CreatedFileObject->Flags |= FO_SYNCHRONOUS_IO;
235 #endif /* LIBCAPTIVE */
236 CreatedFileObject->FileName.Length=0;
237 CreatedFileObject->FileName.MaximumLength=0;
238 CreatedFileObject->FileName.Buffer=NULL;
240 // shouldn't we initialize the lock event, and several other things here too?
241 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
243 return(CreatedFileObject);
247 /**********************************************************************
252 * Either causes a new file or directory to be created, or it
253 * opens an existing file, device, directory or volume, giving
254 * the caller a handle for the file object. This handle can be
255 * used by subsequent calls to manipulate data within the file
256 * or the file object's state of attributes.
260 * Points to a variable which receives the file handle
264 * Desired access to the file;
267 * Structure describing the file;
269 * IoStatusBlock (OUT)
270 * Receives information about the operation on return;
272 * AllocationSize [OPTIONAL]
273 * Initial size of the file in bytes;
276 * Attributes to create the file with;
279 * Type of shared access the caller would like to the
283 * Specifies what to do, depending on whether the
284 * file already exists;
287 * Options for creating a new file;
289 * EaBuffer [OPTIONAL]
296 * Type of file (normal, named pipe, mailslot) to create;
298 * ExtraCreateParameters [OPTIONAL]
299 * Additional creation data for named pipe and mailsots;
308 * Prototype taken from Bo Branten's ntifs.h v15.
309 * Description taken from old NtCreateFile's which is
310 * now a wrapper of this call.
316 IoCreateFile(OUT PHANDLE FileHandle,
317 IN ACCESS_MASK DesiredAccess,
318 IN POBJECT_ATTRIBUTES ObjectAttributes,
319 OUT PIO_STATUS_BLOCK IoStatusBlock,
320 IN PLARGE_INTEGER AllocationSize OPTIONAL,
321 IN ULONG FileAttributes,
322 IN ULONG ShareAccess,
323 IN ULONG CreateDisposition,
324 IN ULONG CreateOptions,
325 IN PVOID EaBuffer OPTIONAL,
327 IN CREATE_FILE_TYPE CreateFileType,
328 IN PVOID ExtraCreateParameters OPTIONAL,
331 PFILE_OBJECT FileObject;
334 PIO_STACK_LOCATION StackLoc;
335 IO_STATUS_BLOCK IoSB;
336 IO_SECURITY_CONTEXT SecurityContext;
337 ACCESS_STATE AccessState;
339 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
340 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
341 FileHandle,DesiredAccess,ObjectAttributes,
342 ObjectAttributes->ObjectName->Buffer);
344 assert_irql(PASSIVE_LEVEL);
348 Status = ObCreateObject(FileHandle,
352 (PVOID*)&FileObject);
353 if (!NT_SUCCESS(Status))
355 DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
358 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
360 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
362 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
364 FileObject->Flags |= FO_SYNCHRONOUS_IO;
367 if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
368 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
371 RtlZeroMemory(&AccessState, sizeof(AccessState));
372 AccessState.RemainingDesiredAccess=0;
373 AccessState.PreviouslyGrantedAccess=0;
375 SecurityContext.SecurityQos = NULL; /* ?? */
376 SecurityContext.AccessState = &AccessState;
377 SecurityContext.DesiredAccess = DesiredAccess;
378 SecurityContext.FullCreateOptions = 0; /* ?? */
380 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
381 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
383 DPRINT("FileObject %x\n", FileObject);
384 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
386 * Create a new IRP to hand to
387 * the FS driver: this may fail
388 * due to resource shortage.
390 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
393 ZwClose(*FileHandle);
394 return (STATUS_UNSUCCESSFUL);
397 Irp->UserIosb = &IoSB; //return iostatus
398 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
399 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
400 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
401 Irp->UserEvent = &FileObject->Event;
404 Irp->Overlay.AllocationSize = *AllocationSize;
408 * Get the stack location for the new
409 * IRP and prepare it.
411 StackLoc = IoGetNextIrpStackLocation(Irp);
412 switch (CreateFileType)
415 case CreateFileTypeNone:
416 StackLoc->MajorFunction = IRP_MJ_CREATE;
419 case CreateFileTypeNamedPipe:
420 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
423 case CreateFileTypeMailslot:
424 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
427 StackLoc->MinorFunction = 0;
428 StackLoc->Flags = Options;
429 StackLoc->Control = 0;
430 StackLoc->DeviceObject = FileObject->DeviceObject;
431 StackLoc->FileObject = FileObject;
432 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
433 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
434 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
435 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
436 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
437 StackLoc->Parameters.Create.EaLength = EaLength;
440 * Now call the driver and
441 * possibly wait if it can
442 * not complete the request
445 Status = IofCallDriver(FileObject->DeviceObject, Irp );
447 if (Status == STATUS_PENDING)
449 KeWaitForSingleObject(&FileObject->Event,
454 Status = IoSB.Status;
456 if (!NT_SUCCESS(Status))
458 DPRINT("Failing create request with status %x\n", Status);
459 FileObject->DeviceObject = NULL;
460 FileObject->Vpb = NULL;
462 ZwClose(*FileHandle);
466 *IoStatusBlock = IoSB;
468 assert_irql(PASSIVE_LEVEL);
470 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
477 /**********************************************************************
482 * Entry point to call IoCreateFile with
483 * default parameters.
493 * Code originally in NtCreateFile moved in IoCreateFile.
496 NtCreateFile(PHANDLE FileHandle,
497 ACCESS_MASK DesiredAccess,
498 POBJECT_ATTRIBUTES ObjectAttributes,
499 PIO_STATUS_BLOCK IoStatusBlock,
500 PLARGE_INTEGER AllocateSize,
501 ULONG FileAttributes,
503 ULONG CreateDisposition,
508 return IoCreateFile(FileHandle,
525 /**********************************************************************
530 * Opens an existing file (simpler than NtCreateFile).
534 * Variable that receives the file handle on return;
537 * Access desired by the caller to the file;
540 * Structue describing the file to be opened;
542 * IoStatusBlock (OUT)
543 * Receives details about the result of the
547 * Type of shared access the caller requires;
550 * Options for the file open.
559 NtOpenFile(PHANDLE FileHandle,
560 ACCESS_MASK DesiredAccess,
561 POBJECT_ATTRIBUTES ObjectAttributes,
562 PIO_STATUS_BLOCK IoStatusBlock,
566 return IoCreateFile(FileHandle,
582 #endif /* LIBCAPTIVE */