IopCreateFile(): +Initialized 'RelatedFileObject' field to NULL
[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   FileObject->RelatedFileObject = NULL;
162
163   return(STATUS_SUCCESS);
164 }
165
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
233 /**********************************************************************
234  * NAME                                                 EXPORTED
235  *      IoCreateFile@56
236  *      
237  * DESCRIPTION
238  *      Either causes a new file or directory to be created, or it
239  *      opens an existing file, device, directory or volume, giving
240  *      the caller a handle for the file object. This handle can be
241  *      used by subsequent calls to manipulate data within the file
242  *      or the file object's state of attributes.
243  *      
244  * ARGUMENTS
245  *      FileHandle (OUT)
246  *              Points to a variable which receives the file handle
247  *              on return;
248  *              
249  *      DesiredAccess
250  *              Desired access to the file;
251  *              
252  *      ObjectAttributes
253  *              Structure describing the file;
254  *              
255  *      IoStatusBlock (OUT)
256  *              Receives information about the operation on return;
257  *              
258  *      AllocationSize [OPTIONAL]
259  *              Initial size of the file in bytes;
260  *              
261  *      FileAttributes
262  *              Attributes to create the file with;
263  *              
264  *      ShareAccess
265  *              Type of shared access the caller would like to the
266  *              file;
267  *              
268  *      CreateDisposition
269  *              Specifies what to do, depending on whether the
270  *              file already exists;
271  *              
272  *      CreateOptions
273  *              Options for creating a new file;
274  *              
275  *      EaBuffer [OPTIONAL]
276  *              Undocumented;
277  *              
278  *      EaLength
279  *              Undocumented;
280  *              
281  *      CreateFileType
282  *              Type of file (normal, named pipe, mailslot) to create;
283  *              
284  *      ExtraCreateParameters [OPTIONAL]
285  *              Additional creation data for named pipe and mailsots;
286  *              
287  *      Options
288  *              Undocumented.
289  *              
290  * RETURN VALUE
291  *      Status
292  *
293  * NOTE
294  *      Prototype taken from Bo Branten's ntifs.h v15.
295  *      Description taken from old NtCreateFile's which is
296  *      now a wrapper of this call.
297  *      
298  * REVISIONS
299  * 
300  */
301 NTSTATUS STDCALL
302 IoCreateFile(OUT        PHANDLE                 FileHandle,
303              IN ACCESS_MASK             DesiredAccess,
304              IN POBJECT_ATTRIBUTES      ObjectAttributes,
305              OUT        PIO_STATUS_BLOCK        IoStatusBlock,
306              IN PLARGE_INTEGER          AllocationSize          OPTIONAL,
307              IN ULONG                   FileAttributes,
308              IN ULONG                   ShareAccess,
309              IN ULONG                   CreateDisposition,
310              IN ULONG                   CreateOptions,
311              IN PVOID                   EaBuffer                OPTIONAL,
312              IN ULONG                   EaLength,
313              IN CREATE_FILE_TYPE        CreateFileType,
314              IN PVOID                   ExtraCreateParameters   OPTIONAL,
315              IN ULONG                   Options)
316 {
317    PFILE_OBJECT         FileObject;
318    NTSTATUS             Status;
319    PIRP                 Irp;
320    PIO_STACK_LOCATION   StackLoc;
321    IO_STATUS_BLOCK      IoSB;
322    IO_SECURITY_CONTEXT  SecurityContext;
323    
324    DPRINT("IoCreateFile(FileHandle %x, DesiredAccess %x, "
325           "ObjectAttributes %x ObjectAttributes->ObjectName->Buffer %S)\n",
326           FileHandle,DesiredAccess,ObjectAttributes,
327           ObjectAttributes->ObjectName->Buffer);
328    
329    assert_irql(PASSIVE_LEVEL);
330    
331    *FileHandle = 0;
332
333    Status = ObCreateObject(FileHandle,
334                            DesiredAccess,
335                            ObjectAttributes,
336                            IoFileObjectType,
337                            (PVOID*)&FileObject);
338    if (!NT_SUCCESS(Status))
339      {
340         DPRINT("ObCreateObject() failed! (Status %lx)\n", Status);
341         return(Status);
342      }
343    if (CreateOptions & FILE_SYNCHRONOUS_IO_ALERT)
344      {
345         FileObject->Flags |= (FO_ALERTABLE_IO | FO_SYNCHRONOUS_IO);
346      }
347    if (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT)
348      {
349         FileObject->Flags |= FO_SYNCHRONOUS_IO;
350      }
351
352    if( CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING )
353      FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
354
355    SecurityContext.SecurityQos = NULL; /* ?? */
356    SecurityContext.AccessState = NULL; /* ?? */
357    SecurityContext.DesiredAccess = DesiredAccess;
358    SecurityContext.FullCreateOptions = 0; /* ?? */
359    
360    KeInitializeEvent(&FileObject->Lock, NotificationEvent, TRUE);
361    KeInitializeEvent(&FileObject->Event, NotificationEvent, FALSE);
362    
363    DPRINT("FileObject %x\n", FileObject);
364    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
365    /*
366     * Create a new IRP to hand to
367     * the FS driver: this may fail
368     * due to resource shortage.
369     */
370    Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, FALSE);
371    if (Irp == NULL)
372      {
373         ZwClose(*FileHandle);
374         return (STATUS_UNSUCCESSFUL);
375      }
376      
377    Irp->UserIosb = &IoSB;   //return iostatus
378    Irp->AssociatedIrp.SystemBuffer = EaBuffer;
379    Irp->Tail.Overlay.AuxiliaryBuffer = (PCHAR)ExtraCreateParameters;
380    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
381    Irp->UserEvent = &FileObject->Event;
382    if (AllocationSize)
383    {
384       Irp->Overlay.AllocationSize = *AllocationSize;
385    }
386    
387    /*
388     * Get the stack location for the new
389     * IRP and prepare it.
390     */
391    StackLoc = IoGetNextIrpStackLocation(Irp);
392    switch (CreateFileType)
393      {
394         default:
395         case CreateFileTypeNone:
396           StackLoc->MajorFunction = IRP_MJ_CREATE;
397           break;
398         
399         case CreateFileTypeNamedPipe:
400           StackLoc->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
401           break;
402
403         case CreateFileTypeMailslot:
404           StackLoc->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
405           break;
406      }
407    StackLoc->MinorFunction = 0;
408    StackLoc->Flags = Options;
409    StackLoc->Control = 0;
410    StackLoc->DeviceObject = FileObject->DeviceObject;
411    StackLoc->FileObject = FileObject;
412    StackLoc->Parameters.Create.SecurityContext = &SecurityContext;
413    StackLoc->Parameters.Create.Options = (CreateOptions & FILE_VALID_OPTION_FLAGS);
414    StackLoc->Parameters.Create.Options |= (CreateDisposition << 24);
415    StackLoc->Parameters.Create.FileAttributes = FileAttributes;
416    StackLoc->Parameters.Create.ShareAccess = ShareAccess;
417    StackLoc->Parameters.Create.EaLength = EaLength;
418    
419    /*
420     * Now call the driver and 
421     * possibly wait if it can
422     * not complete the request
423     * immediately.
424     */
425    Status = IofCallDriver(FileObject->DeviceObject, Irp );
426    
427    if (Status == STATUS_PENDING)
428      {
429         KeWaitForSingleObject(&FileObject->Event,
430                               Executive,
431                               KernelMode,
432                               FALSE,
433                               NULL);
434         Status = IoSB.Status;
435      }
436    if (!NT_SUCCESS(Status))
437      {
438         DPRINT("Failing create request with status %x\n", Status);
439         FileObject->DeviceObject = NULL;
440         FileObject->Vpb = NULL;
441
442         ZwClose(*FileHandle);
443      }
444    if (IoStatusBlock)
445      {
446        *IoStatusBlock = IoSB;
447      }
448    assert_irql(PASSIVE_LEVEL);
449
450    DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
451
452    return (Status);
453 }
454
455 #ifndef LIBCAPTIVE
456
457 /**********************************************************************
458  * NAME                                                 EXPORTED
459  *      NtCreateFile@44
460  * 
461  * DESCRIPTION
462  *      Entry point to call IoCreateFile with
463  *      default parameters.
464  *
465  * ARGUMENTS
466  *      See IoCreateFile.
467  * 
468  * RETURN VALUE
469  *      See IoCreateFile.
470  *
471  * REVISIONS
472  *      2000-03-25 (ea)
473  *              Code originally in NtCreateFile moved in IoCreateFile.
474  */
475 NTSTATUS STDCALL
476 NtCreateFile(PHANDLE FileHandle,
477              ACCESS_MASK DesiredAccess,
478              POBJECT_ATTRIBUTES ObjectAttributes,
479              PIO_STATUS_BLOCK IoStatusBlock,
480              PLARGE_INTEGER AllocateSize,
481              ULONG FileAttributes,
482              ULONG ShareAccess,
483              ULONG CreateDisposition,
484              ULONG CreateOptions,
485              PVOID EaBuffer,
486              ULONG EaLength)
487 {
488    return IoCreateFile(FileHandle,
489                        DesiredAccess,
490                        ObjectAttributes,
491                        IoStatusBlock,
492                        AllocateSize,
493                        FileAttributes,
494                        ShareAccess,
495                        CreateDisposition,
496                        CreateOptions,
497                        EaBuffer,
498                        EaLength,
499                        CreateFileTypeNone,
500                        NULL,
501                        0);
502 }
503
504
505 /**********************************************************************
506  * NAME                                                 EXPORTED
507  *      NtOpenFile@24
508  *      
509  * DESCRIPTION
510  *      Opens an existing file (simpler than NtCreateFile).
511  *
512  * ARGUMENTS
513  *      FileHandle (OUT)
514  *              Variable that receives the file handle on return;
515  *              
516  *      DesiredAccess
517  *              Access desired by the caller to the file;
518  *              
519  *      ObjectAttributes
520  *              Structue describing the file to be opened;
521  *              
522  *      IoStatusBlock (OUT)
523  *              Receives details about the result of the
524  *              operation;
525  *              
526  *      ShareAccess
527  *              Type of shared access the caller requires;
528  *              
529  *      OpenOptions
530  *              Options for the file open.
531  *
532  * RETURN VALUE
533  *      Status.
534  *      
535  * NOTE
536  *      Undocumented.
537  */
538 NTSTATUS STDCALL
539 NtOpenFile(PHANDLE FileHandle,
540            ACCESS_MASK DesiredAccess,
541            POBJECT_ATTRIBUTES ObjectAttributes,
542            PIO_STATUS_BLOCK IoStatusBlock,
543            ULONG ShareAccess,
544            ULONG OpenOptions)
545 {
546    return IoCreateFile(FileHandle,
547                        DesiredAccess,
548                        ObjectAttributes,
549                        IoStatusBlock,
550                        NULL,
551                        0,
552                        ShareAccess,
553                        FILE_OPEN,
554                        OpenOptions,
555                        NULL,
556                        0,
557                        CreateFileTypeNone,
558                        NULL,
559                        0);
560 }
561
562 #endif /* LIBCAPTIVE */
563
564 /* EOF */