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