Added some modifications for asyncronous i/o requests (for vfatfs).
[reactos.git] / reactos / ntoskrnl / io / create.c
1 /* $Id: create.c,v 1.50 2001/11/02 22:22:33 hbirr 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
320 DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
321 "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
322 FileHandle,DesiredAccess,ObjectAttributes,
323 ObjectAttributes->ObjectName->Buffer);
324
325 assert_irql(PASSIVE_LEVEL);
326
327 *FileHandle = 0;
328
329 Status = ObCreateObject(FileHandle,
330 DesiredAccess,
331 ObjectAttributes,
332 IoFileObjectType,
333 (PVOID*)&FileObject);
334 if (!NT_SUCCESS(Status))
335 {
336 DPRINT("ObCreateObject() failed!\n");
337 return (Status);
338 }
339 if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
340 {
341 FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
342 }
343 if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
344 {
345 FileObject->Flags |= FO_SYNCHRONOUS_IO;
346 }
347 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
348 KeInitializeEvent(&Event, NotificationEvent, FALSE);
349
350 DPRINT("FileObject %x\n", FileObject);
351 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
352 /*
353 * Create a new IRP to hand to
354 * the FS driver: this may fail
355 * due to resource shortage.
356 */
357 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
358 if (Irp == NULL)
359 {
360 ZwClose(*FileHandle);
361 return (STATUS_UNSUCCESSFUL);
362 }
363
364 Irp->UserIosb = &IoSB; //return iostatus
365 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
366 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
367 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
368 Irp->UserEvent = &Event;
369
370 /*
371 * Get the stack location for the new
372 * IRP and prepare it.
373 */
374 StackLoc = IoGetNextIrpStackLocation(Irp);
375 switch (CreateFileType)
376 {
377 default:
378 case CreateFileTypeNone:
379 StackLoc->MajorFunction = IRP_MJ_CREATE;
380 break;
381
382 case CreateFileTypeNamedPipe:
383 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
384 break;
385
386 case CreateFileTypeMailslot:
387 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
388 break;
389 }
390 StackLoc->MinorFunction = 0;
391 StackLoc->Flags = 0;
392 StackLoc->Control = 0;
393 StackLoc->DeviceObject = FileObject->DeviceObject;
394 StackLoc->FileObject = FileObject;
395 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
396 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
397
398 /*
399 * Now call the driver and
400 * possibly wait if it can
401 * not complete the request
402 * immediately.
403 */
404 Status = IofCallDriver(FileObject->DeviceObject, Irp );
405
406 if (Status == STATUS_PENDING)
407 {
408 KeWaitForSingleObject(&Event,
409 Executive,
410 KernelMode,
411 FALSE,
412 NULL);
413 Status = IoSB.Status;
414 }
415 if (!NT_SUCCESS(Status))
416 {
417 DPRINT("Failing create request with status %x\n", Status);
418 ZwClose(*FileHandle);
419 }
420 if (IoStatusBlock)
421 {
422 *IoStatusBlock = IoSB;
423 }
424 assert_irql(PASSIVE_LEVEL);
425
426 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
427
428 return (Status);
429 }
430
431
432 /**********************************************************************
433 * NAME EXPORTED
434 * NtCreateFile@44
435 *
436 * DESCRIPTION
437 * Entry point to call IoCreateFile with
438 * default parameters.
439 *
440 * ARGUMENTS
441 * See IoCreateFile.
442 *
443 * RETURN VALUE
444 * See IoCreateFile.
445 *
446 * REVISIONS
447 * 2000-03-25 (ea)
448 * Code originally in NtCreateFile moved in IoCreateFile.
449 */
450 NTSTATUS STDCALL
451 NtCreateFile(PHANDLE FileHandle,
452 ACCESS_MASK DesiredAccess,
453 POBJECT_ATTRIBUTES ObjectAttributes,
454 PIO_STATUS_BLOCK IoStatusBlock,
455 PLARGE_INTEGER AllocateSize,
456 ULONG FileAttributes,
457 ULONG ShareAccess,
458 ULONG CreateDisposition,
459 ULONG CreateOptions,
460 PVOID EaBuffer,
461 ULONG EaLength)
462 {
463 return IoCreateFile(FileHandle,
464 DesiredAccess,
465 ObjectAttributes,
466 IoStatusBlock,
467 AllocateSize,
468 FileAttributes,
469 ShareAccess,
470 CreateDisposition,
471 CreateOptions,
472 EaBuffer,
473 EaLength,
474 CreateFileTypeNone,
475 NULL,
476 0);
477 }
478
479
480 /**********************************************************************
481 * NAME EXPORTED
482 * NtOpenFile@24
483 *
484 * DESCRIPTION
485 * Opens an existing file (simpler than NtCreateFile).
486 *
487 * ARGUMENTS
488 * FileHandle (OUT)
489 * Variable that receives the file handle on return;
490 *
491 * DesiredAccess
492 * Access desired by the caller to the file;
493 *
494 * ObjectAttributes
495 * Structue describing the file to be opened;
496 *
497 * IoStatusBlock (OUT)
498 * Receives details about the result of the
499 * operation;
500 *
501 * ShareAccess
502 * Type of shared access the caller requires;
503 *
504 * OpenOptions
505 * Options for the file open.
506 *
507 * RETURN VALUE
508 * Status.
509 *
510 * NOTE
511 * Undocumented.
512 */
513 NTSTATUS STDCALL
514 NtOpenFile(PHANDLE FileHandle,
515 ACCESS_MASK DesiredAccess,
516 POBJECT_ATTRIBUTES ObjectAttributes,
517 PIO_STATUS_BLOCK IoStatusBlock,
518 ULONG ShareAccess,
519 ULONG OpenOptions)
520 {
521 return IoCreateFile(FileHandle,
522 DesiredAccess,
523 ObjectAttributes,
524 IoStatusBlock,
525 NULL,
526 0,
527 ShareAccess,
528 FILE_OPEN,
529 OpenOptions,
530 NULL,
531 0,
532 CreateFileTypeNone,
533 NULL,
534 0);
535 }
536
537 /* EOF */