update for HEAD-2003091401
[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 /*
30  * @implemented
31  */
32 NTSTATUS STDCALL
33 NtQueryInformationFile(HANDLE FileHandle,
34                        PIO_STATUS_BLOCK IoStatusBlock,
35                        PVOID FileInformation,
36                        ULONG Length,
37                        FILE_INFORMATION_CLASS FileInformationClass)
38 {
39    PFILE_OBJECT FileObject;
40    NTSTATUS Status;
41    PIRP Irp;
42    PDEVICE_OBJECT DeviceObject;
43    PIO_STACK_LOCATION StackPtr;
44    PVOID SystemBuffer;
45    IO_STATUS_BLOCK IoSB;
46    
47    assert(IoStatusBlock != NULL);
48    assert(FileInformation != NULL);
49    
50    DPRINT("NtQueryInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
51           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
52           Length, FileInformationClass);
53    
54    Status = ObReferenceObjectByHandle(FileHandle,
55                                       FILE_READ_ATTRIBUTES,
56                                       IoFileObjectType,
57                                       UserMode,
58                                       (PVOID *)&FileObject,
59                                       NULL);
60    if (!NT_SUCCESS(Status))
61      {
62         return(Status);
63      }
64    DPRINT("FileObject %x\n", FileObject);
65    
66    DeviceObject = FileObject->DeviceObject;
67    
68    Irp = IoAllocateIrp(DeviceObject->StackSize,
69                        TRUE);
70    if (Irp == NULL)
71      {
72         ObDereferenceObject(FileObject);
73         return STATUS_INSUFFICIENT_RESOURCES;
74      }
75    
76    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
77                                         Length,
78                                         TAG_SYSB);
79    if (SystemBuffer == NULL)
80      {
81         IoFreeIrp(Irp);
82         ObDereferenceObject(FileObject);
83         return(STATUS_INSUFFICIENT_RESOURCES);
84      }
85    
86    //trigger FileObject/Event dereferencing
87    Irp->Tail.Overlay.OriginalFileObject = FileObject;
88
89    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
90    Irp->UserIosb = &IoSB;
91    Irp->UserEvent = &FileObject->Event;
92    KeResetEvent( &FileObject->Event );
93    
94    StackPtr = IoGetNextIrpStackLocation(Irp);
95    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
96    StackPtr->MinorFunction = 0;
97    StackPtr->Flags = 0;
98    StackPtr->Control = 0;
99    StackPtr->DeviceObject = DeviceObject;
100    StackPtr->FileObject = FileObject;
101    
102    StackPtr->Parameters.QueryFile.FileInformationClass =
103      FileInformationClass;
104    StackPtr->Parameters.QueryFile.Length = Length;
105    
106    Status = IoCallDriver(FileObject->DeviceObject,
107                          Irp);
108    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
109      {
110         KeWaitForSingleObject(&FileObject->Event,
111                               Executive,
112                               KernelMode,
113                               FALSE,
114                               NULL);
115         Status = IoSB.Status;
116      }
117   if (IoStatusBlock)
118     {
119       *IoStatusBlock = IoSB;
120     }
121
122   if (NT_SUCCESS(Status))
123     {
124       DPRINT("Information %lu\n", IoStatusBlock->Information);
125       MmSafeCopyToUser(FileInformation,
126                        SystemBuffer,
127                        IoStatusBlock->Information);
128     }
129    
130    ExFreePool(SystemBuffer);   
131    return(Status);
132 }
133
134
135 /*
136  * @implemented
137  */
138 NTSTATUS STDCALL
139 IoQueryFileInformation(IN PFILE_OBJECT FileObject,
140                        IN FILE_INFORMATION_CLASS FileInformationClass,
141                        IN ULONG Length,
142                        OUT PVOID FileInformation,
143                        OUT PULONG ReturnedLength)
144 {
145    IO_STATUS_BLOCK IoStatusBlock;
146    PIRP Irp;
147    PDEVICE_OBJECT DeviceObject;
148    PIO_STACK_LOCATION StackPtr;
149    NTSTATUS Status;
150    
151    assert(FileInformation != NULL)
152    
153    Status = ObReferenceObjectByPointer(FileObject,
154                                        FILE_READ_ATTRIBUTES,
155                                        IoFileObjectType,
156                                        KernelMode);
157    if (!NT_SUCCESS(Status))
158      {
159         return(Status);
160      }
161    
162    DPRINT("FileObject %x\n", FileObject);
163    
164    DeviceObject = FileObject->DeviceObject;
165    
166    Irp = IoAllocateIrp(DeviceObject->StackSize,
167                        TRUE);
168    if (Irp == NULL)
169      {
170         ObDereferenceObject(FileObject);
171         return STATUS_INSUFFICIENT_RESOURCES;
172      }
173
174    //trigger FileObject/Event dereferencing
175    Irp->Tail.Overlay.OriginalFileObject = FileObject;
176    
177    Irp->AssociatedIrp.SystemBuffer = FileInformation;
178    Irp->UserIosb = &IoStatusBlock;
179    Irp->UserEvent = &FileObject->Event;
180    KeResetEvent( &FileObject->Event );
181    
182    StackPtr = IoGetNextIrpStackLocation(Irp);
183    StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
184    StackPtr->MinorFunction = 0;
185    StackPtr->Flags = 0;
186    StackPtr->Control = 0;
187    StackPtr->DeviceObject = DeviceObject;
188    StackPtr->FileObject = FileObject;
189    
190    StackPtr->Parameters.QueryFile.FileInformationClass =
191      FileInformationClass;
192    StackPtr->Parameters.QueryFile.Length = Length;
193    
194    Status = IoCallDriver(FileObject->DeviceObject,
195                          Irp);
196    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
197      {
198         KeWaitForSingleObject(&FileObject->Event,
199                               Executive,
200                               KernelMode,
201                               FALSE,
202                               NULL);
203         Status = IoStatusBlock.Status;
204      }
205    
206    if (ReturnedLength != NULL)
207      {
208         *ReturnedLength = IoStatusBlock.Information;
209      }
210    
211    
212    return Status;
213 }
214
215
216 /*
217  * @implemented
218  */
219 NTSTATUS STDCALL
220 NtSetInformationFile(HANDLE FileHandle,
221                      PIO_STATUS_BLOCK IoStatusBlock,
222                      PVOID FileInformation,
223                      ULONG Length,
224                      FILE_INFORMATION_CLASS FileInformationClass)
225 {
226    PIO_STACK_LOCATION StackPtr;
227    PFILE_OBJECT FileObject;
228    PDEVICE_OBJECT DeviceObject;
229    PIRP Irp;
230    NTSTATUS Status;
231    PVOID SystemBuffer;
232    IO_STATUS_BLOCK IoSB;
233    
234    assert(IoStatusBlock != NULL)
235    assert(FileInformation != NULL)
236    
237    DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
238           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
239           Length, FileInformationClass);
240    
241    /*  Get the file object from the file handle  */
242    Status = ObReferenceObjectByHandle(FileHandle,
243                                       FILE_WRITE_ATTRIBUTES,
244                                       IoFileObjectType,
245                                       UserMode,
246                                       (PVOID *)&FileObject,
247                                       NULL);
248    if (!NT_SUCCESS(Status))
249      {
250         return Status;
251      }
252    
253    DPRINT("FileObject %x\n", FileObject);
254
255    //io completion port?
256    if (FileInformationClass == FileCompletionInformation)
257    {
258       PKQUEUE Queue;
259
260       if (Length < sizeof(FILE_COMPLETION_INFORMATION))
261       {
262          Status = STATUS_INFO_LENGTH_MISMATCH;
263       }
264       else
265       {
266          Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
267                                             IO_COMPLETION_MODIFY_STATE,//???
268                                             ExIoCompletionType,
269                                             UserMode,
270                                             (PVOID*)&Queue,
271                                             NULL);
272          if (NT_SUCCESS(Status))
273          {   
274             //FIXME: maybe use lookaside list
275             FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
276             FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
277             FileObject->CompletionContext->Port = Queue;
278
279             ObDereferenceObject(Queue);
280          }
281       }
282
283       ObDereferenceObject(FileObject);
284       return Status;
285    }
286
287    DeviceObject = FileObject->DeviceObject;
288    
289    Irp = IoAllocateIrp(DeviceObject->StackSize,
290                        TRUE);
291    if (Irp == NULL)
292      {
293         ObDereferenceObject(FileObject);
294         return STATUS_INSUFFICIENT_RESOURCES;
295      }
296    
297    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
298                                         Length,
299                                         TAG_SYSB);
300    if (SystemBuffer == NULL)
301      {
302         IoFreeIrp(Irp);
303         ObDereferenceObject(FileObject);
304         return(STATUS_INSUFFICIENT_RESOURCES);
305      }
306    
307    MmSafeCopyFromUser(SystemBuffer,
308                       FileInformation,
309                       Length);
310    
311    //trigger FileObject/Event dereferencing
312    Irp->Tail.Overlay.OriginalFileObject = FileObject;
313
314    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
315    Irp->UserIosb = &IoSB;
316    Irp->UserEvent = &FileObject->Event;
317    KeResetEvent( &FileObject->Event );
318    
319    StackPtr = IoGetNextIrpStackLocation(Irp);
320    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
321    StackPtr->MinorFunction = 0;
322    StackPtr->Flags = 0;
323    StackPtr->Control = 0;
324    StackPtr->DeviceObject = DeviceObject;
325    StackPtr->FileObject = FileObject;
326    
327    StackPtr->Parameters.SetFile.FileInformationClass =
328      FileInformationClass;
329    StackPtr->Parameters.SetFile.Length = Length;
330    
331    /*
332     * Pass the IRP to the FSD (and wait for
333     * it if required)
334     */
335    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
336    Status = IoCallDriver(FileObject->DeviceObject,
337                          Irp);
338    if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
339      {
340         KeWaitForSingleObject(&FileObject->Event,
341                               Executive,
342                               KernelMode,
343                               FALSE,
344                               NULL);
345         Status = IoSB.Status;
346      }
347    if (IoStatusBlock)
348      {
349        *IoStatusBlock = IoSB;
350      }
351    ExFreePool(SystemBuffer);
352  
353    return Status;
354 }
355
356
357 NTSTATUS STDCALL
358 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
359                       OUT PFILE_BASIC_INFORMATION FileInformation)
360 {
361   IO_STATUS_BLOCK IoStatusBlock;
362   HANDLE FileHandle;
363   NTSTATUS Status;
364
365   /* Open the file */
366   Status = NtOpenFile (&FileHandle,
367                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
368                        ObjectAttributes,
369                        &IoStatusBlock,
370                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
371                        FILE_SYNCHRONOUS_IO_NONALERT);
372   if (!NT_SUCCESS (Status))
373     {
374       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
375       return Status;
376     }
377
378   /* Get file attributes */
379   Status = NtQueryInformationFile (FileHandle,
380                                    &IoStatusBlock,
381                                    FileInformation,
382                                    sizeof(FILE_BASIC_INFORMATION),
383                                    FileBasicInformation);
384   NtClose (FileHandle);
385   if (!NT_SUCCESS (Status))
386     {
387       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
388     }
389
390   return Status;
391 }
392
393
394 NTSTATUS STDCALL
395 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
396                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
397 {
398   IO_STATUS_BLOCK IoStatusBlock;
399   HANDLE FileHandle;
400   NTSTATUS Status;
401
402   /* Open the file */
403   Status = NtOpenFile (&FileHandle,
404                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
405                        ObjectAttributes,
406                        &IoStatusBlock,
407                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
408                        FILE_SYNCHRONOUS_IO_NONALERT);
409   if (!NT_SUCCESS (Status))
410     {
411       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
412       return Status;
413     }
414
415   /* Get file attributes */
416   Status = NtQueryInformationFile (FileHandle,
417                                    &IoStatusBlock,
418                                    FileInformation,
419                                    sizeof(FILE_NETWORK_OPEN_INFORMATION),
420                                    FileNetworkOpenInformation);
421   NtClose (FileHandle);
422   if (!NT_SUCCESS (Status))
423     {
424       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
425     }
426
427   return Status;
428 }
429
430
431 /*
432  * @unimplemented
433  */
434 NTSTATUS STDCALL
435 NtQueryEaFile(IN HANDLE FileHandle,
436               OUT PIO_STATUS_BLOCK IoStatusBlock,
437               OUT PVOID Buffer,
438               IN ULONG Length,
439               IN BOOLEAN ReturnSingleEntry,
440               IN PVOID EaList OPTIONAL,
441               IN ULONG EaListLength,
442               IN PULONG EaIndex OPTIONAL,
443               IN BOOLEAN RestartScan)
444 {
445    UNIMPLEMENTED;
446    return STATUS_NOT_IMPLEMENTED;
447 }
448
449
450 /*
451  * @unimplemented
452  */
453 NTSTATUS STDCALL
454 NtSetEaFile(IN HANDLE FileHandle,
455             IN PIO_STATUS_BLOCK IoStatusBlock,
456             IN PVOID EaBuffer,
457             IN ULONG EaBufferSize)
458 {
459    UNIMPLEMENTED;
460    return STATUS_NOT_IMPLEMENTED;
461 }
462
463 /* EOF */