e40bb09e203b21946833153aa6a777ccfe9c3d1b
[reactos.git] / ntoskrnl / io / file.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/io/file.c
6  * PURPOSE:         Graceful system shutdown if a bug is detected
7  * PROGRAMMER:      David Welch (welch@mcmail.com)
8  * UPDATE HISTORY:
9  *                  Created 22/05/98
10  */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/mm.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21
22 /* GLOBALS *******************************************************************/
23
24 #define TAG_SYSB   TAG('S', 'Y', 'S', 'B')
25
26
27 /* FUNCTIONS *****************************************************************/
28
29 NTSTATUS STDCALL
30 NtQueryInformationFile(HANDLE FileHandle,
31                        PIO_STATUS_BLOCK IoStatusBlock,
32                        PVOID FileInformation,
33                        ULONG Length,
34                        FILE_INFORMATION_CLASS FileInformationClass)
35 {
36    PFILE_OBJECT FileObject;
37    NTSTATUS Status;
38    PIRP Irp;
39    PDEVICE_OBJECT DeviceObject;
40    PIO_STACK_LOCATION StackPtr;
41    PVOID SystemBuffer;
42    IO_STATUS_BLOCK IoSB;
43    
44    assert(IoStatusBlock != NULL);
45    assert(FileInformation != NULL);
46    
47    DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
48           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
49           Length, FileInformationClass);
50    
51    Status = ObReferenceObjectByHandle(FileHandle,
52                                       FILE_READ_ATTRIBUTES,
53                                       IoFileObjectType,
54                                       UserMode,
55                                       (PVOID *)&FileObject,
56                                       NULL);
57    if (!NT_SUCCESS(Status))
58      {
59         return(Status);
60      }
61    DPRINT("FileObject %x\n", FileObject);
62    
63    DeviceObject = FileObject->DeviceObject;
64    
65    Irp = IoAllocateIrp(DeviceObject->StackSize,
66                        TRUE);
67    if (Irp == NULL)
68      {
69         ObDereferenceObject(FileObject);
70         return STATUS_INSUFFICIENT_RESOURCES;
71      }
72    
73    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
74                                         Length,
75                                         TAG_SYSB);
76    if (SystemBuffer == NULL)
77      {
78         IoFreeIrp(Irp);
79         ObDereferenceObject(FileObject);
80         return(STATUS_INSUFFICIENT_RESOURCES);
81      }
82    
83    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
84    Irp->UserIosb = &IoSB;
85    Irp->UserEvent = &FileObject->Event;
86    KeResetEvent( &FileObject->Event );
87    
88    StackPtr = IoGetNextIrpStackLocation(Irp);
89    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
90    StackPtr->MinorFunction = 0;
91    StackPtr->Flags = 0;
92    StackPtr->Control = 0;
93    StackPtr->DeviceObject = DeviceObject;
94    StackPtr->FileObject = FileObject;
95    
96    StackPtr->Parameters.QueryFile.FileInformationClass =
97      FileInformationClass;
98    StackPtr->Parameters.QueryFile.Length = Length;
99    
100    Status = IoCallDriver(FileObject->DeviceObject,
101                          Irp);
102    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
103      {
104         KeWaitForSingleObject(&FileObject->Event,
105                               Executive,
106                               KernelMode,
107                               FALSE,
108                               NULL);
109         Status = IoSB.Status;
110      }
111   if (IoStatusBlock)
112     {
113       *IoStatusBlock = IoSB;
114     }
115
116   if (NT_SUCCESS(Status))
117     {
118       DPRINT("Information %lu\n", IoStatusBlock->Information);
119       MmSafeCopyToUser(FileInformation,
120                        SystemBuffer,
121                        IoStatusBlock->Information);
122     }
123    
124    ExFreePool(SystemBuffer);   
125    return(Status);
126 }
127
128 #ifndef LIBCAPTIVE
129
130 NTSTATUS STDCALL
131 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
132                        IN FILE_INFORMATION_CLASS FileInformationClass,
133                        IN ULONG Length,
134                        OUT PVOID FileInformation,
135                        OUT PULONG ReturnedLength)
136 {
137    IO_STATUS_BLOCK IoStatusBlock;
138    PIRP Irp;
139    PDEVICE_OBJECT DeviceObject;
140    PIO_STACK_LOCATION StackPtr;
141    NTSTATUS Status;
142    
143    assert(FileInformation != NULL)
144    
145    Status = ObReferenceObjectByPointer(FileObject,
146                                        FILE_READ_ATTRIBUTES,
147                                        IoFileObjectType,
148                                        KernelMode);
149    if (!NT_SUCCESS(Status))
150      {
151         return(Status);
152      }
153    
154    DPRINT("FileObject %x\n", FileObject);
155    
156    DeviceObject = FileObject->DeviceObject;
157    
158    Irp = IoAllocateIrp(DeviceObject->StackSize,
159                        TRUE);
160    if (Irp == NULL)
161      {
162         ObDereferenceObject(FileObject);
163         return STATUS_INSUFFICIENT_RESOURCES;
164      }
165    
166    Irp->AssociatedIrp.SystemBuffer = FileInformation;
167    Irp->UserIosb = &IoStatusBlock;
168    Irp->UserEvent = &FileObject->Event;
169    KeResetEvent( &FileObject->Event );
170    
171    StackPtr = IoGetNextIrpStackLocation(Irp);
172    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
173    StackPtr->MinorFunction = 0;
174    StackPtr->Flags = 0;
175    StackPtr->Control = 0;
176    StackPtr->DeviceObject = DeviceObject;
177    StackPtr->FileObject = FileObject;
178    
179    StackPtr->Parameters.QueryFile.FileInformationClass =
180      FileInformationClass;
181    StackPtr->Parameters.QueryFile.Length = Length;
182    
183    Status = IoCallDriver(FileObject->DeviceObject,
184                          Irp);
185    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
186      {
187         KeWaitForSingleObject(&FileObject->Event,
188                               Executive,
189                               KernelMode,
190                               FALSE,
191                               NULL);
192         Status = IoStatusBlock.Status;
193      }
194    
195    if (ReturnedLength != NULL)
196      {
197         *ReturnedLength = IoStatusBlock.Information;
198      }
199    
200    
201    return Status;
202 }
203
204 #endif /* LIBCAPTIVE */
205
206 NTSTATUS STDCALL
207 NtSetInformationFile(HANDLE FileHandle,
208                      PIO_STATUS_BLOCK IoStatusBlock,
209                      PVOID FileInformation,
210                      ULONG Length,
211                      FILE_INFORMATION_CLASS FileInformationClass)
212 {
213    PIO_STACK_LOCATION StackPtr;
214    PFILE_OBJECT FileObject;
215    PDEVICE_OBJECT DeviceObject;
216    PIRP Irp;
217    NTSTATUS Status;
218    PVOID SystemBuffer;
219    IO_STATUS_BLOCK IoSB;
220    FILE_OBJECT *RootDir_FileObject = NULL;
221    
222    assert(IoStatusBlock != NULL)
223    assert(FileInformation != NULL)
224    
225    DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
226           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
227           Length, FileInformationClass);
228    
229    /*  Get the file object from the file handle  */
230    Status = ObReferenceObjectByHandle(FileHandle,
231                                       FILE_WRITE_ATTRIBUTES,
232                                       IoFileObjectType,
233                                       UserMode,
234                                       (PVOID *)&FileObject,
235                                       NULL);
236    if (!NT_SUCCESS(Status))
237      {
238         return Status;
239      }
240    
241    DPRINT("FileObject %x\n", FileObject);
242    
243    DeviceObject = FileObject->DeviceObject;
244    
245    Irp = IoAllocateIrp(DeviceObject->StackSize,
246                        TRUE);
247    if (Irp == NULL)
248      {
249         ObDereferenceObject(FileObject);
250         return STATUS_INSUFFICIENT_RESOURCES;
251      }
252    
253    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
254                                         Length,
255                                         TAG_SYSB);
256    if (SystemBuffer == NULL)
257      {
258         IoFreeIrp(Irp);
259         ObDereferenceObject(FileObject);
260         return(STATUS_INSUFFICIENT_RESOURCES);
261      }
262    
263    MmSafeCopyFromUser(SystemBuffer,
264                       FileInformation,
265                       Length);
266    
267    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
268    Irp->UserIosb = &IoSB;
269    Irp->UserEvent = &FileObject->Event;
270    KeResetEvent( &FileObject->Event );
271    
272    StackPtr = IoGetNextIrpStackLocation(Irp);
273    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
274    StackPtr->MinorFunction = 0;
275    StackPtr->Flags = 0;
276    StackPtr->Control = 0;
277    StackPtr->DeviceObject = DeviceObject;
278    StackPtr->FileObject = FileObject;
279    
280    StackPtr->Parameters.SetFile.Length = Length;
281    StackPtr->Parameters.SetFile.FileInformationClass =
282      FileInformationClass;
283    switch (FileInformationClass)
284      {
285        case FileRenameInformation:
286          if (!((FILE_RENAME_INFORMATION *)FileInformation)->RootDir)
287            StackPtr->Parameters.SetFile.FileObject=NULL;
288          else
289            {
290              /*  Get the file object from the file handle  */
291              Status = ObReferenceObjectByHandle(((FILE_RENAME_INFORMATION *)FileInformation)->RootDir,
292                                                 (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY),
293                                                 IoFileObjectType,
294                                                 KernelMode,     /* FIXME: or UserMode ? */
295                                                 (PVOID *)&RootDir_FileObject,
296                                                 NULL);
297              if (!NT_SUCCESS(Status))
298                {
299                   return Status;
300                }
301              StackPtr->Parameters.SetFile.FileObject=RootDir_FileObject;
302            }
303          StackPtr->Parameters.SetFile.u.d.ReplaceIfExists=((FILE_RENAME_INFORMATION *)FileInformation)->Replace;
304          StackPtr->Parameters.SetFile.u.d.AdvanceOnly=FALSE;
305          break;
306        default:;
307      }
308    
309    /*
310     * Pass the IRP to the FSD (and wait for
311     * it if required)
312     */
313    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
314    Status = IoCallDriver(FileObject->DeviceObject,
315                          Irp);
316    if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
317      {
318         KeWaitForSingleObject(&FileObject->Event,
319                               Executive,
320                               KernelMode,
321                               FALSE,
322                               NULL);
323         Status = IoSB.Status;
324      }
325    if (IoStatusBlock)
326      {
327        *IoStatusBlock = IoSB;
328      }
329    if (RootDir_FileObject != NULL)
330      ObDereferenceObject(RootDir_FileObject);
331    ExFreePool(SystemBuffer);
332  
333    return Status;
334 }
335
336 #ifndef LIBCAPTIVE
337
338 NTSTATUS STDCALL
339 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
340                       OUT PFILE_BASIC_INFORMATION FileInformation)
341 {
342    UNIMPLEMENTED;
343    return STATUS_NOT_IMPLEMENTED;
344 }
345
346
347 NTSTATUS STDCALL
348 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
349                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
350 {
351    UNIMPLEMENTED;
352    return STATUS_NOT_IMPLEMENTED;
353 }
354
355
356 NTSTATUS STDCALL
357 NtQueryEaFile(IN HANDLE FileHandle,
358               OUT PIO_STATUS_BLOCK IoStatusBlock,
359               OUT PVOID Buffer,
360               IN ULONG Length,
361               IN BOOLEAN ReturnSingleEntry,
362               IN PVOID EaList OPTIONAL,
363               IN ULONG EaListLength,
364               IN PULONG EaIndex OPTIONAL,
365               IN BOOLEAN RestartScan)
366 {
367    UNIMPLEMENTED;
368    return STATUS_NOT_IMPLEMENTED;
369 }
370
371
372 NTSTATUS STDCALL
373 NtSetEaFile(IN HANDLE FileHandle,
374             IN PIO_STATUS_BLOCK IoStatusBlock,
375             IN PVOID EaBuffer,
376             IN ULONG EaBufferSize)
377 {
378    UNIMPLEMENTED;
379    return STATUS_NOT_IMPLEMENTED;
380 }
381
382 #endif /* LIBCAPTIVE */
383
384 /* EOF */