098356f3aff6f960d726010077f854f425d59c4f
[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
129 NTSTATUS STDCALL
130 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
131                        IN FILE_INFORMATION_CLASS FileInformationClass,
132                        IN ULONG Length,
133                        OUT PVOID FileInformation,
134                        OUT PULONG ReturnedLength)
135 {
136    IO_STATUS_BLOCK IoStatusBlock;
137    PIRP Irp;
138    PDEVICE_OBJECT DeviceObject;
139    PIO_STACK_LOCATION StackPtr;
140    NTSTATUS Status;
141    
142    assert(FileInformation != NULL)
143    
144    Status = ObReferenceObjectByPointer(FileObject,
145                                        FILE_READ_ATTRIBUTES,
146                                        IoFileObjectType,
147                                        KernelMode);
148    if (!NT_SUCCESS(Status))
149      {
150         return(Status);
151      }
152    
153    DPRINT("FileObject %x\n", FileObject);
154    
155    DeviceObject = FileObject->DeviceObject;
156    
157    Irp = IoAllocateIrp(DeviceObject->StackSize,
158                        TRUE);
159    if (Irp == NULL)
160      {
161         ObDereferenceObject(FileObject);
162         return STATUS_INSUFFICIENT_RESOURCES;
163      }
164    
165    Irp->AssociatedIrp.SystemBuffer = FileInformation;
166    Irp->UserIosb = &IoStatusBlock;
167    Irp->UserEvent = &FileObject->Event;
168    KeResetEvent( &FileObject->Event );
169    
170    StackPtr = IoGetNextIrpStackLocation(Irp);
171    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
172    StackPtr->MinorFunction = 0;
173    StackPtr->Flags = 0;
174    StackPtr->Control = 0;
175    StackPtr->DeviceObject = DeviceObject;
176    StackPtr->FileObject = FileObject;
177    
178    StackPtr->Parameters.QueryFile.FileInformationClass =
179      FileInformationClass;
180    StackPtr->Parameters.QueryFile.Length = Length;
181    
182    Status = IoCallDriver(FileObject->DeviceObject,
183                          Irp);
184    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
185      {
186         KeWaitForSingleObject(&FileObject->Event,
187                               Executive,
188                               KernelMode,
189                               FALSE,
190                               NULL);
191         Status = IoStatusBlock.Status;
192      }
193    
194    if (ReturnedLength != NULL)
195      {
196         *ReturnedLength = IoStatusBlock.Information;
197      }
198    
199    
200    return Status;
201 }
202
203
204 NTSTATUS STDCALL
205 NtSetInformationFile(HANDLE FileHandle,
206                      PIO_STATUS_BLOCK IoStatusBlock,
207                      PVOID FileInformation,
208                      ULONG Length,
209                      FILE_INFORMATION_CLASS FileInformationClass)
210 {
211    PIO_STACK_LOCATION StackPtr;
212    PFILE_OBJECT FileObject;
213    PDEVICE_OBJECT DeviceObject;
214    PIRP Irp;
215    NTSTATUS Status;
216    PVOID SystemBuffer;
217    IO_STATUS_BLOCK IoSB;
218    
219    assert(IoStatusBlock != NULL)
220    assert(FileInformation != NULL)
221    
222    DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
223           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
224           Length, FileInformationClass);
225    
226    /*  Get the file object from the file handle  */
227    Status = ObReferenceObjectByHandle(FileHandle,
228                                       FILE_WRITE_ATTRIBUTES,
229                                       IoFileObjectType,
230                                       UserMode,
231                                       (PVOID *)&FileObject,
232                                       NULL);
233    if (!NT_SUCCESS(Status))
234      {
235         return Status;
236      }
237    
238    DPRINT("FileObject %x\n", FileObject);
239
240    //io completion port?
241    if (FileInformationClass == FileCompletionInformation)
242    {
243       PKQUEUE Queue;
244
245       if (Length < sizeof(FILE_COMPLETION_INFORMATION))
246       {
247          Status = STATUS_INFO_LENGTH_MISMATCH;
248       }
249       else
250       {
251          Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
252                                             IO_COMPLETION_MODIFY_STATE,//???
253                                             ExIoCompletionType,
254                                             UserMode,
255                                             (PVOID*)&Queue,
256                                             NULL);
257          if (NT_SUCCESS(Status))
258          {   
259             //FIXME: maybe use lookaside list
260             FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
261             FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
262             FileObject->CompletionContext->Port = Queue;
263
264             ObDereferenceObject(Queue);
265          }
266       }
267
268       ObDereferenceObject(FileObject);
269       return Status;
270    }
271
272    DeviceObject = FileObject->DeviceObject;
273    
274    Irp = IoAllocateIrp(DeviceObject->StackSize,
275                        TRUE);
276    if (Irp == NULL)
277      {
278         ObDereferenceObject(FileObject);
279         return STATUS_INSUFFICIENT_RESOURCES;
280      }
281    
282    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
283                                         Length,
284                                         TAG_SYSB);
285    if (SystemBuffer == NULL)
286      {
287         IoFreeIrp(Irp);
288         ObDereferenceObject(FileObject);
289         return(STATUS_INSUFFICIENT_RESOURCES);
290      }
291    
292    MmSafeCopyFromUser(SystemBuffer,
293                       FileInformation,
294                       Length);
295    
296    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
297    Irp->UserIosb = &IoSB;
298    Irp->UserEvent = &FileObject->Event;
299    KeResetEvent( &FileObject->Event );
300    
301    StackPtr = IoGetNextIrpStackLocation(Irp);
302    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
303    StackPtr->MinorFunction = 0;
304    StackPtr->Flags = 0;
305    StackPtr->Control = 0;
306    StackPtr->DeviceObject = DeviceObject;
307    StackPtr->FileObject = FileObject;
308    
309    StackPtr->Parameters.SetFile.FileInformationClass =
310      FileInformationClass;
311    StackPtr->Parameters.SetFile.Length = Length;
312    
313    /*
314     * Pass the IRP to the FSD (and wait for
315     * it if required)
316     */
317    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
318    Status = IoCallDriver(FileObject->DeviceObject,
319                          Irp);
320    if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
321      {
322         KeWaitForSingleObject(&FileObject->Event,
323                               Executive,
324                               KernelMode,
325                               FALSE,
326                               NULL);
327         Status = IoSB.Status;
328      }
329    if (IoStatusBlock)
330      {
331        *IoStatusBlock = IoSB;
332      }
333    ExFreePool(SystemBuffer);
334  
335    return Status;
336 }
337
338
339 NTSTATUS STDCALL
340 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
341                       OUT PFILE_BASIC_INFORMATION FileInformation)
342 {
343   IO_STATUS_BLOCK IoStatusBlock;
344   HANDLE FileHandle;
345   NTSTATUS Status;
346
347   /* Open the file */
348   Status = NtOpenFile (&FileHandle,
349                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
350                        ObjectAttributes,
351                        &IoStatusBlock,
352                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
353                        FILE_SYNCHRONOUS_IO_NONALERT);
354   if (!NT_SUCCESS (Status))
355     {
356       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
357       return Status;
358     }
359
360   /* Get file attributes */
361   Status = NtQueryInformationFile (FileHandle,
362                                    &IoStatusBlock,
363                                    FileInformation,
364                                    sizeof(FILE_BASIC_INFORMATION),
365                                    FileBasicInformation);
366   NtClose (FileHandle);
367   if (!NT_SUCCESS (Status))
368     {
369       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
370     }
371
372   return Status;
373 }
374
375
376 NTSTATUS STDCALL
377 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
378                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
379 {
380   IO_STATUS_BLOCK IoStatusBlock;
381   HANDLE FileHandle;
382   NTSTATUS Status;
383
384   /* Open the file */
385   Status = NtOpenFile (&FileHandle,
386                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
387                        ObjectAttributes,
388                        &IoStatusBlock,
389                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
390                        FILE_SYNCHRONOUS_IO_NONALERT);
391   if (!NT_SUCCESS (Status))
392     {
393       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
394       return Status;
395     }
396
397   /* Get file attributes */
398   Status = NtQueryInformationFile (FileHandle,
399                                    &IoStatusBlock,
400                                    FileInformation,
401                                    sizeof(FILE_NETWORK_OPEN_INFORMATION),
402                                    FileNetworkOpenInformation);
403   NtClose (FileHandle);
404   if (!NT_SUCCESS (Status))
405     {
406       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
407     }
408
409   return Status;
410 }
411
412
413 NTSTATUS STDCALL
414 NtQueryEaFile(IN HANDLE FileHandle,
415               OUT PIO_STATUS_BLOCK IoStatusBlock,
416               OUT PVOID Buffer,
417               IN ULONG Length,
418               IN BOOLEAN ReturnSingleEntry,
419               IN PVOID EaList OPTIONAL,
420               IN ULONG EaListLength,
421               IN PULONG EaIndex OPTIONAL,
422               IN BOOLEAN RestartScan)
423 {
424    UNIMPLEMENTED;
425    return STATUS_NOT_IMPLEMENTED;
426 }
427
428
429 NTSTATUS STDCALL
430 NtSetEaFile(IN HANDLE FileHandle,
431             IN PIO_STATUS_BLOCK IoStatusBlock,
432             IN PVOID EaBuffer,
433             IN ULONG EaBufferSize)
434 {
435    UNIMPLEMENTED;
436    return STATUS_NOT_IMPLEMENTED;
437 }
438
439 /* EOF */