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