Reverted latest changes.
[reactos.git] / reactos / ntoskrnl / io / create.c
1 /* $Id: create.c,v 1.61 2002/09/08 10:23:24 chorns 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
87 if (IoDeviceObjectType != BODY_TO_HEADER(Parent)->ObjectType)
88 {
89 CPRINT("Parent is a %S which is not a device type\n",
90 BODY_TO_HEADER(Parent)->ObjectType->TypeName.Buffer);
91 return(STATUS_UNSUCCESSFUL);
92 }
93
94 Status = ObReferenceObjectByPointer(DeviceObject,
95 STANDARD_RIGHTS_REQUIRED,
96 IoDeviceObjectType,
97 UserMode);
98 if (!NT_SUCCESS(Status))
99 {
100 CPRINT("Failed to reference device object %x\n", DeviceObject);
101 return(Status);
102 }
103
104 DeviceObject = IoGetAttachedDevice(DeviceObject);
105 DPRINT("DeviceObject %x\n", DeviceObject);
106
107 if (NULL == RemainingPath)
108 {
109 FileObject->Flags = FileObject->Flags | FO_DIRECT_DEVICE_OPEN;
110 FileObject->FileName.Buffer = 0;
111 FileObject->FileName.Length = FileObject->FileName.MaximumLength = 0;
112 }
113 else
114 {
115 if ((DeviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM)
116 && (DeviceObject->DeviceType != FILE_DEVICE_DISK)
117 && (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM)
118 && (DeviceObject->DeviceType != FILE_DEVICE_TAPE)
119 && (DeviceObject->DeviceType != FILE_DEVICE_NETWORK)
120 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
121 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
122 {
123 CPRINT("Device was wrong type\n");
124 return(STATUS_UNSUCCESSFUL);
125 }
126
127 if (DeviceObject->DeviceType != FILE_DEVICE_NETWORK
128 && (DeviceObject->DeviceType != FILE_DEVICE_NAMED_PIPE)
129 && (DeviceObject->DeviceType != FILE_DEVICE_MAILSLOT))
130 {
131 if (!(DeviceObject->Vpb->Flags & VPB_MOUNTED))
132 {
133 DPRINT("Mount the logical volume\n");
134 Status = IoMountVolume(DeviceObject, FALSE);
135 DPRINT("Status %x\n", Status);
136 if (!NT_SUCCESS(Status))
137 {
138 CPRINT("Failed to mount logical volume (Status %x)\n",
139 Status);
140 return(Status);
141 }
142 }
143 DeviceObject = DeviceObject->Vpb->DeviceObject;
144 DPRINT("FsDeviceObject %lx\n", DeviceObject);
145 }
146 RtlCreateUnicodeString(&(FileObject->FileName),
147 RemainingPath);
148 }
149
150 DPRINT("FileObject->FileName %wZ\n",
151 &FileObject->FileName);
152 FileObject->DeviceObject = DeviceObject;
153 DPRINT("FileObject %x DeviceObject %x\n",
154 FileObject,
155 DeviceObject);
156 FileObject->Vpb = DeviceObject->Vpb;
157 FileObject->Type = InternalFileType;
158
159 return(STATUS_SUCCESS);
160 }
161
162
163 /**********************************************************************
164 * NAME EXPORTED
165 * IoCreateStreamFileObject@8
166 *
167 * DESCRIPTION
168 *
169 * ARGUMENTS
170 * FileObject
171 * ?
172 *
173 * DeviceObject
174 * ?
175 *
176 * RETURN VALUE
177 *
178 * NOTE
179 *
180 * REVISIONS
181 *
182 */
183 PFILE_OBJECT STDCALL
184 IoCreateStreamFileObject(PFILE_OBJECT FileObject,
185 PDEVICE_OBJECT DeviceObject)
186 {
187 HANDLE FileHandle;
188 PFILE_OBJECT CreatedFileObject;
189 NTSTATUS Status;
190
191 DPRINT("IoCreateStreamFileObject(FileObject %x, DeviceObject %x)\n",
192 FileObject, DeviceObject);
193
194 assert_irql(PASSIVE_LEVEL);
195
196 Status = ObCreateObject(&FileHandle,
197 STANDARD_RIGHTS_REQUIRED,
198 NULL,
199 IoFileObjectType,
200 (PVOID*)&CreatedFileObject);
201 if (!NT_SUCCESS(Status))
202 {
203 DPRINT("Could not create FileObject\n");
204 return (NULL);
205 }
206
207 if (FileObject != NULL)
208 {
209 DeviceObject = FileObject->DeviceObject;
210 }
211 DeviceObject = IoGetAttachedDevice(DeviceObject);
212
213 DPRINT("DeviceObject %x\n", DeviceObject);
214
215 CreatedFileObject->DeviceObject = DeviceObject->Vpb->DeviceObject;
216 CreatedFileObject->Vpb = DeviceObject->Vpb;
217 CreatedFileObject->Type = InternalFileType;
218 CreatedFileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
219
220 // shouldn't we initialize the lock event, and several other things here too?
221 KeInitializeEvent(&CreatedFileObject->Event, NotificationEvent, FALSE);
222
223 ZwClose(FileHandle);
224
225 return(CreatedFileObject);
226 }
227
228
229 /**********************************************************************
230 * NAME EXPORTED
231 * IoCreateFile@56
232 *
233 * DESCRIPTION
234 * Either causes a new file or directory to be created, or it
235 * opens an existing file, device, directory or volume, giving
236 * the caller a handle for the file object. This handle can be
237 * used by subsequent calls to manipulate data within the file
238 * or the file object's state of attributes.
239 *
240 * ARGUMENTS
241 * FileHandle (OUT)
242 * Points to a variable which receives the file handle
243 * on return;
244 *
245 * DesiredAccess
246 * Desired access to the file;
247 *
248 * ObjectAttributes
249 * Structure describing the file;
250 *
251 * IoStatusBlock (OUT)
252 * Receives information about the operation on return;
253 *
254 * AllocationSize [OPTIONAL]
255 * Initial size of the file in bytes;
256 *
257 * FileAttributes
258 * Attributes to create the file with;
259 *
260 * ShareAccess
261 * Type of shared access the caller would like to the
262 * file;
263 *
264 * CreateDisposition
265 * Specifies what to do, depending on whether the
266 * file already exists;
267 *
268 * CreateOptions
269 * Options for creating a new file;
270 *
271 * EaBuffer [OPTIONAL]
272 * Undocumented;
273 *
274 * EaLength
275 * Undocumented;
276 *
277 * CreateFileType
278 * Type of file (normal, named pipe, mailslot) to create;
279 *
280 * ExtraCreateParameters [OPTIONAL]
281 * Additional creation data for named pipe and mailsots;
282 *
283 * Options
284 * Undocumented.
285 *
286 * RETURN VALUE
287 * Status
288 *
289 * NOTE
290 * Prototype taken from Bo Branten's ntifs.h v15.
291 * Description taken from old NtCreateFile's which is
292 * now a wrapper of this call.
293 *
294 * REVISIONS
295 *
296 */
297 NTSTATUS STDCALL
298 IoCreateFile(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 PIO_STACK_LOCATION StackLoc;
317 IO_STATUS_BLOCK IoSB;
318 IO_SECURITY_CONTEXT SecurityContext;
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! (Status %lx)\n", Status);
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
348 if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
349 FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
350
351 SecurityContext.SecurityQos = NULL; /* ?? */
352 SecurityContext.AccessState = NULL; /* ?? */
353 SecurityContext.DesiredAccess = DesiredAccess;
354 SecurityContext.FullCreateOptions = 0; /* ?? */
355
356 KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
357 KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
358
359 DPRINT("FileObject %x\n", FileObject);
360 DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
361 /*
362 * Create a new IRP to hand to
363 * the FS driver: this may fail
364 * due to resource shortage.
365 */
366 Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
367 if (Irp == NULL)
368 {
369 ZwClose(*FileHandle);
370 return (STATUS_UNSUCCESSFUL);
371 }
372
373 Irp->UserIosb = &IoSB; //return iostatus
374 Irp->AssociatedIrp.SystemBuffer = EaBuffer;
375 Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
376 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
377 Irp->UserEvent = &FileObject->Event;
378 if (AllocationSize)
379 {
380 Irp->Overlay.AllocationSize = *AllocationSize;
381 }
382
383 /*
384 * Get the stack location for the new
385 * IRP and prepare it.
386 */
387 StackLoc = IoGetNextIrpStackLocation(Irp);
388 switch (CreateFileType)
389 {
390 default:
391 case CreateFileTypeNone:
392 StackLoc->MajorFunction = IRP_MJ_CREATE;
393 break;
394
395 case CreateFileTypeNamedPipe:
396 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
397 break;
398
399 case CreateFileTypeMailslot:
400 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
401 break;
402 }
403 StackLoc->MinorFunction = 0;
404 StackLoc->Flags = Options;
405 StackLoc->Control = 0;
406 StackLoc->DeviceObject = FileObject->DeviceObject;
407 StackLoc->FileObject = FileObject;
408 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
409 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
410 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
411 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
412 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
413 StackLoc->Parameters.Create.EaLength = EaLength;
414
415 /*
416 * Now call the driver and
417 * possibly wait if it can
418 * not complete the request
419 * immediately.
420 */
421 Status = IofCallDriver(FileObject->DeviceObject, Irp );
422
423 if (Status == STATUS_PENDING)
424 {
425 KeWaitForSingleObject(&FileObject->Event,
426 Executive,
427 KernelMode,
428 FALSE,
429 NULL);
430 Status = IoSB.Status;
431 }
432 if (!NT_SUCCESS(Status))
433 {
434 DPRINT("Failing create request with status %x\n", Status);
435 ZwClose(*FileHandle);
436 }
437 if (IoStatusBlock)
438 {
439 *IoStatusBlock = IoSB;
440 }
441 assert_irql(PASSIVE_LEVEL);
442
443 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
444
445 return (Status);
446 }
447
448
449 /**********************************************************************
450 * NAME EXPORTED
451 * NtCreateFile@44
452 *
453 * DESCRIPTION
454 * Entry point to call IoCreateFile with
455 * default parameters.
456 *
457 * ARGUMENTS
458 * See IoCreateFile.
459 *
460 * RETURN VALUE
461 * See IoCreateFile.
462 *
463 * REVISIONS
464 * 2000-03-25 (ea)
465 * Code originally in NtCreateFile moved in IoCreateFile.
466 */
467 NTSTATUS STDCALL
468 NtCreateFile(PHANDLE FileHandle,
469 ACCESS_MASK DesiredAccess,
470 POBJECT_ATTRIBUTES ObjectAttributes,
471 PIO_STATUS_BLOCK IoStatusBlock,
472 PLARGE_INTEGER AllocateSize,
473 ULONG FileAttributes,
474 ULONG ShareAccess,
475 ULONG CreateDisposition,
476 ULONG CreateOptions,
477 PVOID EaBuffer,
478 ULONG EaLength)
479 {
480 return IoCreateFile(FileHandle,
481 DesiredAccess,
482 ObjectAttributes,
483 IoStatusBlock,
484 AllocateSize,
485 FileAttributes,
486 ShareAccess,
487 CreateDisposition,
488 CreateOptions,
489 EaBuffer,
490 EaLength,
491 CreateFileTypeNone,
492 NULL,
493 0);
494 }
495
496
497 /**********************************************************************
498 * NAME EXPORTED
499 * NtOpenFile@24
500 *
501 * DESCRIPTION
502 * Opens an existing file (simpler than NtCreateFile).
503 *
504 * ARGUMENTS
505 * FileHandle (OUT)
506 * Variable that receives the file handle on return;
507 *
508 * DesiredAccess
509 * Access desired by the caller to the file;
510 *
511 * ObjectAttributes
512 * Structue describing the file to be opened;
513 *
514 * IoStatusBlock (OUT)
515 * Receives details about the result of the
516 * operation;
517 *
518 * ShareAccess
519 * Type of shared access the caller requires;
520 *
521 * OpenOptions
522 * Options for the file open.
523 *
524 * RETURN VALUE
525 * Status.
526 *
527 * NOTE
528 * Undocumented.
529 */
530 NTSTATUS STDCALL
531 NtOpenFile(PHANDLE FileHandle,
532 ACCESS_MASK DesiredAccess,
533 POBJECT_ATTRIBUTES ObjectAttributes,
534 PIO_STATUS_BLOCK IoStatusBlock,
535 ULONG ShareAccess,
536 ULONG OpenOptions)
537 {
538 return IoCreateFile(FileHandle,
539 DesiredAccess,
540 ObjectAttributes,
541 IoStatusBlock,
542 NULL,
543 0,
544 ShareAccess,
545 FILE_OPEN,
546 OpenOptions,
547 NULL,
548 0,
549 CreateFileTypeNone,
550 NULL,
551 0);
552 }
553
554 /* EOF */