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