Added missing create parameters to IoCreateFile().
[reactos.git] / reactos / ntoskrnl / io / create.c
1 /* $Id: create.c,v 1.51 2001/12/05 12:11:55 ekohl Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * 24/05/98: Created
10 */
11
12 /* INCLUDES ***************************************************************/
13
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>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 #define TAG_FILE_NAME TAG('F', 'N', 'A', 'M')
26
27 /* FUNCTIONS *************************************************************/
28
29 /**********************************************************************
30 * NAME EXPORTED
31 * NtDeleteFile@4
32 *
33 * DESCRIPTION
34 *
35 * ARGUMENTS
36 * ObjectAttributes
37 * ?
38 *
39 * RETURN VALUE
40 *
41 * REVISIONS
42 *
43 */
44 NTSTATUS STDCALL
45 NtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes)
46 {
47 UNIMPLEMENTED;
48 }
49
50
51 /**********************************************************************
52 * NAME INTERNAL
53 * IopCreateFile
54 *
55 * DESCRIPTION
56 *
57 * ARGUMENTS
58 *
59 * RETURN VALUE
60 *
61 * REVISIONS
62 *
63 */
64 NTSTATUS STDCALL
65 IopCreateFile(PVOID ObjectBody,
66 PVOID Parent,
67 PWSTR RemainingPath,
68 POBJECT_ATTRIBUTES ObjectAttributes)
69 {
70 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT) Parent;
71 PFILE_OBJECT FileObject = (PFILE_OBJECT) ObjectBody;
72 NTSTATUS Status;
73
74 DPRINT("IopCreateFile(ObjectBody %x, Parent %x, RemainingPath %S)\n",
75 ObjectBody,
76 Parent,
77 RemainingPath);
78
79 if (NULL == DeviceObject)
80 {
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);
85 }
86 if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType)
87 {
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);
91 }
92 Status = ObReferenceObjectByPointer (DeviceObject,
93 STANDARD_RIGHTS_REQUIRED,
94 IoDeviceObjectType,
95 UserMode);
96 if (STATUS_SUCCESS != Status)
97 {
98 CHECKPOINT1;
99 return (Status);
100 }
101
102 DeviceObject = IoGetAttachedDevice (DeviceObject);
103
104 DPRINT("DeviceObject %x\n", DeviceObject);
105
106 if (NULL == RemainingPath)
107 {
108 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
109 FileObject->FileName.Buffer =
110 ExAllocatePoolWithTag(NonPagedPool,
111 (ObjectAttributes->ObjectName->Length+1)*sizeof(WCHAR),
112 TAG_FILE_NAME);
113 FileObject->FileName.Length = ObjectAttributes->ObjectName->Length;
114 FileObject->FileName.MaximumLength =
115 ObjectAttributes->ObjectName->MaximumLength;
116 RtlCopyUnicodeString(&(FileObject->FileName),
117 ObjectAttributes->ObjectName);
118 }
119 else
120 {
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))
126 {
127 CPRINT ("Device was wrong type\n");
128 return (STATUS_UNSUCCESSFUL);
129 }
130
131 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
132 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
133 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
134 {
135 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
136 {
137 DPRINT("Trying to mount storage device\n");
138 Status = IoTryToMountStorageDevice (DeviceObject);
139 DPRINT("Status %x\n", Status);
140 if (!NT_SUCCESS(Status))
141 {
142 CPRINT("Failed to mount storage device (statux %x)\n",
143 Status);
144 return (Status);
145 }
146 DeviceObject = IoGetAttachedDevice(DeviceObject);
147 }
148 }
149 RtlCreateUnicodeString(&(FileObject->FileName),
150 RemainingPath);
151 }
152 DPRINT("FileObject->FileName.Buffer %S\n",
153 FileObject->FileName.Buffer);
154 FileObject->DeviceObject = DeviceObject;
155 DPRINT("FileObject %x DeviceObject %x\n",
156 FileObject,
157 DeviceObject);
158 FileObject->Vpb = DeviceObject->Vpb;
159 FileObject->Type = InternalFileType;
160
161 return (STATUS_SUCCESS);
162 }
163
164
165 /**********************************************************************
166 * NAME EXPORTED
167 * IoCreateStreamFileObject@8
168 *
169 * DESCRIPTION
170 *
171 * ARGUMENTS
172 * FileObject
173 * ?
174 *
175 * DeviceObject
176 * ?
177 *
178 * RETURN VALUE
179 *
180 * NOTE
181 *
182 * REVISIONS
183 *
184 */
185 PFILE_OBJECT STDCALL
186 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
187 PDEVICE_OBJECT DeviceObject)
188 {
189 HANDLE FileHandle;
190 PFILE_OBJECT CreatedFileObject;
191 NTSTATUS Status;
192
193 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
194 FileObject, DeviceObject);
195
196 assert_irql (PASSIVE_LEVEL);
197
198 Status = ObCreateObject (&FileHandle,
199 STANDARD_RIGHTS_REQUIRED,
200 NULL,
201 IoFileObjectType,
202 (PVOID*)&CreatedFileObject);
203 if (!NT_SUCCESS(Status))
204 {
205 DPRINT("Could not create FileObject\n");
206 return (NULL);
207 }
208
209 if (FileObject != NULL)
210 {
211 DeviceObject = FileObject->DeviceObject;
212 }
213 DeviceObject = IoGetAttachedDevice(DeviceObject);
214
215 DPRINT("DeviceObject %x\n", DeviceObject);
216
217 CreatedFileObject->DeviceObject = DeviceObject;
218 CreatedFileObject->Vpb = DeviceObject->Vpb;
219 CreatedFileObject->Type = InternalFileType;
220 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
221
222 ZwClose (FileHandle);
223
224 return (CreatedFileObject);
225 }
226
227
228 /**********************************************************************
229 * NAME EXPORTED
230 * IoCreateFile@56
231 *
232 * DESCRIPTION
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.
238 *
239 * ARGUMENTS
240 * FileHandle (OUT)
241 * Points to a variable which receives the file handle
242 * on return;
243 *
244 * DesiredAccess
245 * Desired access to the file;
246 *
247 * ObjectAttributes
248 * Structure describing the file;
249 *
250 * IoStatusBlock (OUT)
251 * Receives information about the operation on return;
252 *
253 * AllocationSize [OPTIONAL]
254 * Initial size of the file in bytes;
255 *
256 * FileAttributes
257 * Attributes to create the file with;
258 *
259 * ShareAccess
260 * Type of shared access the caller would like to the
261 * file;
262 *
263 * CreateDisposition
264 * Specifies what to do, depending on whether the
265 * file already exists;
266 *
267 * CreateOptions
268 * Options for creating a new file;
269 *
270 * EaBuffer [OPTIONAL]
271 * Undocumented;
272 *
273 * EaLength
274 * Undocumented;
275 *
276 * CreateFileType
277 * Type of file (normal, named pipe, mailslot) to create;
278 *
279 * ExtraCreateParameters [OPTIONAL]
280 * Additional creation data for named pipe and mailsots;
281 *
282 * Options
283 * Undocumented.
284 *
285 * RETURN VALUE
286 * Status
287 *
288 * NOTE
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.
292 *
293 * REVISIONS
294 *
295 */
296 NTSTATUS STDCALL
297 IoCreateFile(
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,
308 IN ULONG EaLength,
309 IN CREATE_FILE_TYPE CreateFileType,
310 IN PVOID ExtraCreateParameters OPTIONAL,
311 IN ULONG Options)
312 {
313 PFILE_OBJECT FileObject;
314 NTSTATUS Status;
315 PIRP Irp;
316 KEVENT Event;
317 PIO_STACK_LOCATION StackLoc;
318 IO_STATUS_BLOCK IoSB;
319 IO_SECURITY_CONTEXT SecurityContext;
320
321 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
322 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
323 FileHandle,DesiredAccess,ObjectAttributes,
324 ObjectAttributes->ObjectName->Buffer);
325
326 assert_irql(PASSIVE_LEVEL);
327
328 *FileHandle = 0;
329
330 Status = ObCreateObject(FileHandle,
331 DesiredAccess,
332 ObjectAttributes,
333 IoFileObjectType,
334 (PVOID*)&FileObject);
335 if (!NT_SUCCESS(Status))
336 {
337 DPRINT("ObCreateObject() failed!\n");
338 return (Status);
339 }
340 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
341 {
342 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
343 }
344 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
345 {
346 FileObject->Flags |= FO_SYNCHRONOUS_IO;
347 }
348
349 SecurityContext.SecurityQos = NULL; /* ?? */
350 SecurityContext.AccessState = NULL; /* ?? */
351 SecurityContext.DesiredAccess = DesiredAccess;
352 SecurityContext.FullCreateOptions = 0; /* ?? */
353
354 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
355 KeInitializeEvent(&Event, NotificationEvent, FALSE);
356
357 DPRINT("FileObject %x\n", FileObject);
358 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
359 /*
360 * Create a new IRP to hand to
361 * the FS driver: this may fail
362 * due to resource shortage.
363 */
364 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
365 if (Irp == NULL)
366 {
367 ZwClose(*FileHandle);
368 return (STATUS_UNSUCCESSFUL);
369 }
370
371 Irp->UserIosb = &IoSB; //return iostatus
372 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
373 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
374 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
375 Irp->UserEvent = &Event;
376
377 /*
378 * Get the stack location for the new
379 * IRP and prepare it.
380 */
381 StackLoc = IoGetNextIrpStackLocation(Irp);
382 switch (CreateFileType)
383 {
384 default:
385 case CreateFileTypeNone:
386 StackLoc->MajorFunction = IRP_MJ_CREATE;
387 break;
388
389 case CreateFileTypeNamedPipe:
390 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
391 break;
392
393 case CreateFileTypeMailslot:
394 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
395 break;
396 }
397 StackLoc->MinorFunction = 0;
398 StackLoc->Flags = 0;
399 StackLoc->Control = 0;
400 StackLoc->DeviceObject = FileObject->DeviceObject;
401 StackLoc->FileObject = FileObject;
402 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
403 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
404 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
405 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
406 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
407 StackLoc->Parameters.Create.EaLength = EaLength;
408
409 /*
410 * Now call the driver and
411 * possibly wait if it can
412 * not complete the request
413 * immediately.
414 */
415 Status = IofCallDriver(FileObject->DeviceObject, Irp );
416
417 if (Status == STATUS_PENDING)
418 {
419 KeWaitForSingleObject(&Event,
420 Executive,
421 KernelMode,
422 FALSE,
423 NULL);
424 Status = IoSB.Status;
425 }
426 if (!NT_SUCCESS(Status))
427 {
428 DPRINT("Failing create request with status %x\n", Status);
429 ZwClose(*FileHandle);
430 }
431 if (IoStatusBlock)
432 {
433 *IoStatusBlock = IoSB;
434 }
435 assert_irql(PASSIVE_LEVEL);
436
437 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
438
439 return (Status);
440 }
441
442
443 /**********************************************************************
444 * NAME EXPORTED
445 * NtCreateFile@44
446 *
447 * DESCRIPTION
448 * Entry point to call IoCreateFile with
449 * default parameters.
450 *
451 * ARGUMENTS
452 * See IoCreateFile.
453 *
454 * RETURN VALUE
455 * See IoCreateFile.
456 *
457 * REVISIONS
458 * 2000-03-25 (ea)
459 * Code originally in NtCreateFile moved in IoCreateFile.
460 */
461 NTSTATUS STDCALL
462 NtCreateFile(PHANDLE FileHandle,
463 ACCESS_MASK DesiredAccess,
464 POBJECT_ATTRIBUTES ObjectAttributes,
465 PIO_STATUS_BLOCK IoStatusBlock,
466 PLARGE_INTEGER AllocateSize,
467 ULONG FileAttributes,
468 ULONG ShareAccess,
469 ULONG CreateDisposition,
470 ULONG CreateOptions,
471 PVOID EaBuffer,
472 ULONG EaLength)
473 {
474 return IoCreateFile(FileHandle,
475 DesiredAccess,
476 ObjectAttributes,
477 IoStatusBlock,
478 AllocateSize,
479 FileAttributes,
480 ShareAccess,
481 CreateDisposition,
482 CreateOptions,
483 EaBuffer,
484 EaLength,
485 CreateFileTypeNone,
486 NULL,
487 0);
488 }
489
490
491 /**********************************************************************
492 * NAME EXPORTED
493 * NtOpenFile@24
494 *
495 * DESCRIPTION
496 * Opens an existing file (simpler than NtCreateFile).
497 *
498 * ARGUMENTS
499 * FileHandle (OUT)
500 * Variable that receives the file handle on return;
501 *
502 * DesiredAccess
503 * Access desired by the caller to the file;
504 *
505 * ObjectAttributes
506 * Structue describing the file to be opened;
507 *
508 * IoStatusBlock (OUT)
509 * Receives details about the result of the
510 * operation;
511 *
512 * ShareAccess
513 * Type of shared access the caller requires;
514 *
515 * OpenOptions
516 * Options for the file open.
517 *
518 * RETURN VALUE
519 * Status.
520 *
521 * NOTE
522 * Undocumented.
523 */
524 NTSTATUS STDCALL
525 NtOpenFile(PHANDLE FileHandle,
526 ACCESS_MASK DesiredAccess,
527 POBJECT_ATTRIBUTES ObjectAttributes,
528 PIO_STATUS_BLOCK IoStatusBlock,
529 ULONG ShareAccess,
530 ULONG OpenOptions)
531 {
532 return IoCreateFile(FileHandle,
533 DesiredAccess,
534 ObjectAttributes,
535 IoStatusBlock,
536 NULL,
537 0,
538 ShareAccess,
539 FILE_OPEN,
540 OpenOptions,
541 NULL,
542 0,
543 CreateFileTypeNone,
544 NULL,
545 0);
546 }
547
548 /* EOF */