branch update for HEAD-2002110701
[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         FileObject->DeviceObject = NULL;
441         FileObject->Vpb = NULL;
442
443         ZwClose(*FileHandle);
444      }
445    if (IoStatusBlock)
446      {
447        *IoStatusBlock = IoSB;
448      }
449    assert_irql(PASSIVE_LEVEL);
450
451    DPRINT("Finished IoCreateFile() (*FileHandle) %x\n", (*FileHandle));
452
453    return (Status);
454 }
455
456 #ifndef LIBCAPTIVE
457
458 /**********************************************************************
459  * NAME                                                 EXPORTED
460  *      NtCreateFile@44
461  * 
462  * DESCRIPTION
463  *      Entry point to call IoCreateFile with
464  *      default parameters.
465  *
466  * ARGUMENTS
467  *      See IoCreateFile.
468  * 
469  * RETURN VALUE
470  *      See IoCreateFile.
471  *
472  * REVISIONS
473  *      2000-03-25 (ea)
474  *              Code originally in NtCreateFile moved in IoCreateFile.
475  */
476 NTSTATUS STDCALL
477 NtCreateFile(PHANDLE FileHandle,
478              ACCESS_MASK DesiredAccess,
479              POBJECT_ATTRIBUTES ObjectAttributes,
480              PIO_STATUS_BLOCK IoStatusBlock,
481              PLARGE_INTEGER AllocateSize,
482              ULONG FileAttributes,
483              ULONG ShareAccess,
484              ULONG CreateDisposition,
485              ULONG CreateOptions,
486              PVOID EaBuffer,
487              ULONG EaLength)
488 {
489    return IoCreateFile(FileHandle,
490                        DesiredAccess,
491                        ObjectAttributes,
492                        IoStatusBlock,
493                        AllocateSize,
494                        FileAttributes,
495                        ShareAccess,
496                        CreateDisposition,
497                        CreateOptions,
498                        EaBuffer,
499                        EaLength,
500                        CreateFileTypeNone,
501                        NULL,
502                        0);
503 }
504
505
506 /**********************************************************************
507  * NAME                                                 EXPORTED
508  *      NtOpenFile@24
509  *      
510  * DESCRIPTION
511  *      Opens an existing file (simpler than NtCreateFile).
512  *
513  * ARGUMENTS
514  *      FileHandle (OUT)
515  *              Variable that receives the file handle on return;
516  *              
517  *      DesiredAccess
518  *              Access desired by the caller to the file;
519  *              
520  *      ObjectAttributes
521  *              Structue describing the file to be opened;
522  *              
523  *      IoStatusBlock (OUT)
524  *              Receives details about the result of the
525  *              operation;
526  *              
527  *      ShareAccess
528  *              Type of shared access the caller requires;
529  *              
530  *      OpenOptions
531  *              Options for the file open.
532  *
533  * RETURN VALUE
534  *      Status.
535  *      
536  * NOTE
537  *      Undocumented.
538  */
539 NTSTATUS STDCALL
540 NtOpenFile(PHANDLE FileHandle,
541            ACCESS_MASK DesiredAccess,
542            POBJECT_ATTRIBUTES ObjectAttributes,
543            PIO_STATUS_BLOCK IoStatusBlock,
544            ULONG ShareAccess,
545            ULONG OpenOptions)
546 {
547    return IoCreateFile(FileHandle,
548                        DesiredAccess,
549                        ObjectAttributes,
550                        IoStatusBlock,
551                        NULL,
552                        0,
553                        ShareAccess,
554                        FILE_OPEN,
555                        OpenOptions,
556                        NULL,
557                        0,
558                        CreateFileTypeNone,
559                        NULL,
560                        0);
561 }
562
563 #endif /* LIBCAPTIVE */
564
565 /* EOF */