1 /* $Id: create.c,v 1.49 2001/11/02 09:17:52 ekohl 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 #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 *************************************************************/
29 /**********************************************************************
45 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes
)
51 /**********************************************************************
65 IopCreateFile(PVOID ObjectBody
,
68 POBJECT_ATTRIBUTES ObjectAttributes
)
70 PDEVICE_OBJECT DeviceObject
= (PDEVICE_OBJECT
) Parent
;
71 PFILE_OBJECT FileObject
= (PFILE_OBJECT
) ObjectBody
;
74 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
79 if (NULL
== DeviceObject
)
81 /* This is probably an attempt to create a meta fileobject (eg. for FAT)
82 for the cache manager, so return STATUS_SUCCESS */
83 DPRINT("DeviceObject was NULL\n");
84 return (STATUS_SUCCESS
);
86 if (IoDeviceObjectType
!= BODY_TO_HEADER(Parent
)->ObjectType
)
88 CPRINT("Parent is a %S which is not a device type\n",
89 BODY_TO_HEADER(Parent
)->ObjectType
->TypeName
.Buffer
);
90 return (STATUS_UNSUCCESSFUL
);
92 Status
= ObReferenceObjectByPointer (DeviceObject
,
93 STANDARD_RIGHTS_REQUIRED
,
96 if (STATUS_SUCCESS
!= Status
)
102 DeviceObject
= IoGetAttachedDevice (DeviceObject
);
104 DPRINT("DeviceObject %x\n", DeviceObject
);
106 if (NULL
== RemainingPath
)
108 FileObject
->Flags
= FileObject
->Flags
| FO_DIRECT_DEVICE_OPEN
;
109 FileObject
->FileName
.Buffer
=
110 ExAllocatePoolWithTag(NonPagedPool
,
111 (ObjectAttributes
->ObjectName
->Length
+1)*sizeof(WCHAR
),
113 FileObject
->FileName
.Length
= ObjectAttributes
->ObjectName
->Length
;
114 FileObject
->FileName
.MaximumLength
=
115 ObjectAttributes
->ObjectName
->MaximumLength
;
116 RtlCopyUnicodeString(&(FileObject
->FileName
),
117 ObjectAttributes
->ObjectName
);
121 if ((DeviceObject
->DeviceType
!= FILE_DEVICE_FILE_SYSTEM
)
122 && (DeviceObject
->DeviceType
!= FILE_DEVICE_DISK
)
123 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
)
124 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
125 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
127 CPRINT ("Device was wrong type\n");
128 return (STATUS_UNSUCCESSFUL
);
131 if (DeviceObject
->DeviceType
!= FILE_DEVICE_NETWORK
132 && (DeviceObject
->DeviceType
!= FILE_DEVICE_NAMED_PIPE
)
133 && (DeviceObject
->DeviceType
!= FILE_DEVICE_MAILSLOT
))
135 if (!(DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
))
137 DPRINT("Trying to mount storage device\n");
138 Status
= IoTryToMountStorageDevice (DeviceObject
);
139 DPRINT("Status %x\n", Status
);
140 if (!NT_SUCCESS(Status
))
142 CPRINT("Failed to mount storage device (statux %x)\n",
146 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
149 RtlCreateUnicodeString(&(FileObject
->FileName
),
152 DPRINT("FileObject->FileName.Buffer %S\n",
153 FileObject
->FileName
.Buffer
);
154 FileObject
->DeviceObject
= DeviceObject
;
155 DPRINT("FileObject %x DeviceObject %x\n",
158 FileObject
->Vpb
= DeviceObject
->Vpb
;
159 FileObject
->Type
= InternalFileType
;
161 return (STATUS_SUCCESS
);
165 /**********************************************************************
167 * IoCreateStreamFileObject@8
186 IoCreateStreamFileObject(PFILE_OBJECT FileObject
,
187 PDEVICE_OBJECT DeviceObject
)
190 PFILE_OBJECT CreatedFileObject
;
193 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
194 FileObject
, DeviceObject
);
196 assert_irql (PASSIVE_LEVEL
);
198 Status
= ObCreateObject (&FileHandle
,
199 STANDARD_RIGHTS_REQUIRED
,
202 (PVOID
*)&CreatedFileObject
);
203 if (!NT_SUCCESS(Status
))
205 DPRINT("Could not create FileObject\n");
209 if (FileObject
!= NULL
)
211 DeviceObject
= FileObject
->DeviceObject
;
213 DeviceObject
= IoGetAttachedDevice(DeviceObject
);
215 DPRINT("DeviceObject %x\n", DeviceObject
);
217 CreatedFileObject
->DeviceObject
= DeviceObject
;
218 CreatedFileObject
->Vpb
= DeviceObject
->Vpb
;
219 CreatedFileObject
->Type
= InternalFileType
;
220 CreatedFileObject
->Flags
|= FO_DIRECT_DEVICE_OPEN
;
222 ZwClose (FileHandle
);
224 return (CreatedFileObject
);
228 /**********************************************************************
233 * Either causes a new file or directory to be created, or it
234 * opens an existing file, device, directory or volume, giving
235 * the caller a handle for the file object. This handle can be
236 * used by subsequent calls to manipulate data within the file
237 * or the file object's state of attributes.
241 * Points to a variable which receives the file handle
245 * Desired access to the file;
248 * Structure describing the file;
250 * IoStatusBlock (OUT)
251 * Receives information about the operation on return;
253 * AllocationSize [OPTIONAL]
254 * Initial size of the file in bytes;
257 * Attributes to create the file with;
260 * Type of shared access the caller would like to the
264 * Specifies what to do, depending on whether the
265 * file already exists;
268 * Options for creating a new file;
270 * EaBuffer [OPTIONAL]
277 * Type of file (normal, named pipe, mailslot) to create;
279 * ExtraCreateParameters [OPTIONAL]
280 * Additional creation data for named pipe and mailsots;
289 * Prototype taken from Bo Branten's ntifs.h v15.
290 * Description taken from old NtCreateFile's which is
291 * now a wrapper of this call.
298 OUT PHANDLE FileHandle
,
299 IN ACCESS_MASK DesiredAccess
,
300 IN POBJECT_ATTRIBUTES ObjectAttributes
,
301 OUT PIO_STATUS_BLOCK IoStatusBlock
,
302 IN PLARGE_INTEGER AllocationSize OPTIONAL
,
303 IN ULONG FileAttributes
,
304 IN ULONG ShareAccess
,
305 IN ULONG CreateDisposition
,
306 IN ULONG CreateOptions
,
307 IN PVOID EaBuffer OPTIONAL
,
309 IN CREATE_FILE_TYPE CreateFileType
,
310 IN PVOID ExtraCreateParameters OPTIONAL
,
313 PFILE_OBJECT FileObject
;
317 PIO_STACK_LOCATION StackLoc
;
319 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
320 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
321 FileHandle
,DesiredAccess
,ObjectAttributes
,
322 ObjectAttributes
->ObjectName
->Buffer
);
324 assert_irql(PASSIVE_LEVEL
);
328 Status
= ObCreateObject(FileHandle
,
332 (PVOID
*)&FileObject
);
333 if (!NT_SUCCESS(Status
))
335 DPRINT("ObCreateObject() failed!\n");
338 if (CreateOptions
& FILE_SYNCHRONOUS_IO_ALERT
)
340 FileObject
->Flags
|= (FO_ALERTABLE_IO
| FO_SYNCHRONOUS_IO
);
342 if (CreateOptions
& FILE_SYNCHRONOUS_IO_NONALERT
)
344 FileObject
->Flags
|= FO_SYNCHRONOUS_IO
;
346 KeInitializeEvent(&FileObject
->Lock
, NotificationEvent
, TRUE
);
347 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
349 DPRINT("FileObject %x\n", FileObject
);
350 DPRINT("FileObject->DeviceObject %x\n", FileObject
->DeviceObject
);
352 * Create a new IRP to hand to
353 * the FS driver: this may fail
354 * due to resource shortage.
356 Irp
= IoAllocateIrp(FileObject
->DeviceObject
->StackSize
, FALSE
);
359 ZwClose(*FileHandle
);
360 return (STATUS_UNSUCCESSFUL
);
363 Irp
->UserIosb
= IoStatusBlock
; //return iostatus
364 Irp
->AssociatedIrp
.SystemBuffer
= EaBuffer
;
365 Irp
->Tail
.Overlay
.AuxiliaryBuffer
= (PCHAR
)ExtraCreateParameters
;
368 * Get the stack location for the new
369 * IRP and prepare it.
371 StackLoc
= IoGetNextIrpStackLocation(Irp
);
372 switch (CreateFileType
)
375 case CreateFileTypeNone
:
376 StackLoc
->MajorFunction
= IRP_MJ_CREATE
;
379 case CreateFileTypeNamedPipe
:
380 StackLoc
->MajorFunction
= IRP_MJ_CREATE_NAMED_PIPE
;
383 case CreateFileTypeMailslot
:
384 StackLoc
->MajorFunction
= IRP_MJ_CREATE_MAILSLOT
;
387 StackLoc
->MinorFunction
= 0;
389 StackLoc
->Control
= 0;
390 StackLoc
->DeviceObject
= FileObject
->DeviceObject
;
391 StackLoc
->FileObject
= FileObject
;
392 StackLoc
->Parameters
.Create
.Options
= (CreateOptions
& FILE_VALID_OPTION_FLAGS
);
393 StackLoc
->Parameters
.Create
.Options
|= (CreateDisposition
<< 24);
396 * Now call the driver and
397 * possibly wait if it can
398 * not complete the request
401 Status
= IofCallDriver(FileObject
->DeviceObject
, Irp
);
403 if (Status
== STATUS_PENDING
)
405 KeWaitForSingleObject(&Event
,
410 Status
= IoStatusBlock
->Status
;
412 if (!NT_SUCCESS(Status
))
414 DPRINT("Failing create request with status %x\n", Status
);
415 ZwClose(*FileHandle
);
418 assert_irql(PASSIVE_LEVEL
);
420 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle
));
426 /**********************************************************************
431 * Entry point to call IoCreateFile with
432 * default parameters.
442 * Code originally in NtCreateFile moved in IoCreateFile.
445 NtCreateFile(PHANDLE FileHandle
,
446 ACCESS_MASK DesiredAccess
,
447 POBJECT_ATTRIBUTES ObjectAttributes
,
448 PIO_STATUS_BLOCK IoStatusBlock
,
449 PLARGE_INTEGER AllocateSize
,
450 ULONG FileAttributes
,
452 ULONG CreateDisposition
,
457 return IoCreateFile(FileHandle
,
474 /**********************************************************************
479 * Opens an existing file (simpler than NtCreateFile).
483 * Variable that receives the file handle on return;
486 * Access desired by the caller to the file;
489 * Structue describing the file to be opened;
491 * IoStatusBlock (OUT)
492 * Receives details about the result of the
496 * Type of shared access the caller requires;
499 * Options for the file open.
508 NtOpenFile(PHANDLE FileHandle
,
509 ACCESS_MASK DesiredAccess
,
510 POBJECT_ATTRIBUTES ObjectAttributes
,
511 PIO_STATUS_BLOCK IoStatusBlock
,
515 return IoCreateFile(FileHandle
,