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