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