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