Fixed a typo.
[reactos.git] / reactos / ntoskrnl / io / create.c
1 /* $Id: create.c,v 1.54 2002/04/01 22:18:01 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 (status %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(OUT PHANDLE FileHandle,
298 IN ACCESS_MASK DesiredAccess,
299 IN POBJECT_ATTRIBUTES ObjectAttributes,
300 OUT PIO_STATUS_BLOCK IoStatusBlock,
301 IN PLARGE_INTEGER AllocationSize OPTIONAL,
302 IN ULONG FileAttributes,
303 IN ULONG ShareAccess,
304 IN ULONG CreateDisposition,
305 IN ULONG CreateOptions,
306 IN PVOID EaBuffer OPTIONAL,
307 IN ULONG EaLength,
308 IN CREATE_FILE_TYPE CreateFileType,
309 IN PVOID ExtraCreateParameters OPTIONAL,
310 IN ULONG Options)
311 {
312 PFILE_OBJECT FileObject;
313 NTSTATUS Status;
314 PIRP Irp;
315 KEVENT Event;
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!\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
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(&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 = &Event;
378
379 /*
380 * Get the stack location for the new
381 * IRP and prepare it.
382 */
383 StackLoc = IoGetNextIrpStackLocation(Irp);
384 switch (CreateFileType)
385 {
386 default:
387 case CreateFileTypeNone:
388 StackLoc->MajorFunction = IRP_MJ_CREATE;
389 break;
390
391 case CreateFileTypeNamedPipe:
392 StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
393 break;
394
395 case CreateFileTypeMailslot:
396 StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
397 break;
398 }
399 StackLoc->MinorFunction = 0;
400 StackLoc->Flags = Options;
401 StackLoc->Control = 0;
402 StackLoc->DeviceObject = FileObject->DeviceObject;
403 StackLoc->FileObject = FileObject;
404 StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
405 StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
406 StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
407 StackLoc->Parameters.Create.FileAttributes = FileAttributes;
408 StackLoc->Parameters.Create.ShareAccess = ShareAccess;
409 StackLoc->Parameters.Create.EaLength = EaLength;
410
411 /*
412 * Now call the driver and
413 * possibly wait if it can
414 * not complete the request
415 * immediately.
416 */
417 Status = IofCallDriver(FileObject->DeviceObject, Irp );
418
419 if (Status == STATUS_PENDING)
420 {
421 KeWaitForSingleObject(&Event,
422 Executive,
423 KernelMode,
424 FALSE,
425 NULL);
426 Status = IoSB.Status;
427 }
428 if (!NT_SUCCESS(Status))
429 {
430 DPRINT("Failing create request with status %x\n", Status);
431 ZwClose(*FileHandle);
432 }
433 if (IoStatusBlock)
434 {
435 *IoStatusBlock = IoSB;
436 }
437 assert_irql(PASSIVE_LEVEL);
438
439 DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
440
441 return (Status);
442 }
443
444
445 /**********************************************************************
446 * NAME EXPORTED
447 * NtCreateFile@44
448 *
449 * DESCRIPTION
450 * Entry point to call IoCreateFile with
451 * default parameters.
452 *
453 * ARGUMENTS
454 * See IoCreateFile.
455 *
456 * RETURN VALUE
457 * See IoCreateFile.
458 *
459 * REVISIONS
460 * 2000-03-25 (ea)
461 * Code originally in NtCreateFile moved in IoCreateFile.
462 */
463 NTSTATUS STDCALL
464 NtCreateFile(PHANDLE FileHandle,
465 ACCESS_MASK DesiredAccess,
466 POBJECT_ATTRIBUTES ObjectAttributes,
467 PIO_STATUS_BLOCK IoStatusBlock,
468 PLARGE_INTEGER AllocateSize,
469 ULONG FileAttributes,
470 ULONG ShareAccess,
471 ULONG CreateDisposition,
472 ULONG CreateOptions,
473 PVOID EaBuffer,
474 ULONG EaLength)
475 {
476 return IoCreateFile(FileHandle,
477 DesiredAccess,
478 ObjectAttributes,
479 IoStatusBlock,
480 AllocateSize,
481 FileAttributes,
482 ShareAccess,
483 CreateDisposition,
484 CreateOptions,
485 EaBuffer,
486 EaLength,
487 CreateFileTypeNone,
488 NULL,
489 0);
490 }
491
492
493 /**********************************************************************
494 * NAME EXPORTED
495 * NtOpenFile@24
496 *
497 * DESCRIPTION
498 * Opens an existing file (simpler than NtCreateFile).
499 *
500 * ARGUMENTS
501 * FileHandle (OUT)
502 * Variable that receives the file handle on return;
503 *
504 * DesiredAccess
505 * Access desired by the caller to the file;
506 *
507 * ObjectAttributes
508 * Structue describing the file to be opened;
509 *
510 * IoStatusBlock (OUT)
511 * Receives details about the result of the
512 * operation;
513 *
514 * ShareAccess
515 * Type of shared access the caller requires;
516 *
517 * OpenOptions
518 * Options for the file open.
519 *
520 * RETURN VALUE
521 * Status.
522 *
523 * NOTE
524 * Undocumented.
525 */
526 NTSTATUS STDCALL
527 NtOpenFile(PHANDLE FileHandle,
528 ACCESS_MASK DesiredAccess,
529 POBJECT_ATTRIBUTES ObjectAttributes,
530 PIO_STATUS_BLOCK IoStatusBlock,
531 ULONG ShareAccess,
532 ULONG OpenOptions)
533 {
534 return IoCreateFile(FileHandle,
535 DesiredAccess,
536 ObjectAttributes,
537 IoStatusBlock,
538 NULL,
539 0,
540 ShareAccess,
541 FILE_OPEN,
542 OpenOptions,
543 NULL,
544 0,
545 CreateFileTypeNone,
546 NULL,
547 0);
548 }
549
550 /* EOF */