branch update for HEAD-2003050101
[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 #define OBJ_KERNEL_HANDLE 0x00000200
207 #define IO_FORCE_ACCESS_CHECK 0x1
208 #define IO_NO_PARAMETER_CHECKING 0x100
209
210 NTSTATUS STDCALL
211 NtSetInformationFile(HANDLE FileHandle,
212                      PIO_STATUS_BLOCK IoStatusBlock,
213                      PVOID FileInformation,
214                      ULONG Length,
215                      FILE_INFORMATION_CLASS FileInformationClass)
216 {
217    PIO_STACK_LOCATION StackPtr;
218    PFILE_OBJECT FileObject;
219    PDEVICE_OBJECT DeviceObject;
220    PIRP Irp;
221    NTSTATUS Status;
222    PVOID SystemBuffer;
223    IO_STATUS_BLOCK IoSB;
224    FILE_OBJECT *RootDir_FileObject = NULL;
225    HANDLE RootDir_FileHandle;
226    
227    assert(IoStatusBlock != NULL)
228    assert(FileInformation != NULL)
229    
230    DPRINT("NtSetInformationFile(Handle %x StatBlk %x FileInfo %x Length %d "
231           "Class %d)\n", FileHandle, IoStatusBlock, FileInformation,
232           Length, FileInformationClass);
233    
234    /*  Get the file object from the file handle  */
235    Status = ObReferenceObjectByHandle(FileHandle,
236                                       FILE_WRITE_ATTRIBUTES,
237                                       IoFileObjectType,
238                                       UserMode,
239                                       (PVOID *)&FileObject,
240                                       NULL);
241    if (!NT_SUCCESS(Status))
242      {
243         return Status;
244      }
245    
246    DPRINT("FileObject %x\n", FileObject);
247
248    //io completion port?
249    if (FileInformationClass == FileCompletionInformation)
250    {
251 #ifdef LIBCAPTIVE
252       KeBugCheck(0);
253 #else /* !LIBCAPTIVE */
254       PKQUEUE Queue;
255
256       if (Length < sizeof(FILE_COMPLETION_INFORMATION))
257       {
258          Status = STATUS_INFO_LENGTH_MISMATCH;
259       }
260       else
261       {
262          Status = ObReferenceObjectByHandle(((PFILE_COMPLETION_INFORMATION)FileInformation)->IoCompletionHandle,
263                                             IO_COMPLETION_MODIFY_STATE,//???
264                                             ExIoCompletionType,
265                                             UserMode,
266                                             (PVOID*)&Queue,
267                                             NULL);
268          if (NT_SUCCESS(Status))
269          {   
270             //FIXME: maybe use lookaside list
271             FileObject->CompletionContext = ExAllocatePool(NonPagedPool, sizeof(IO_COMPLETION_CONTEXT));
272             FileObject->CompletionContext->Key = ((PFILE_COMPLETION_INFORMATION)FileInformation)->CompletionKey;
273             FileObject->CompletionContext->Port = Queue;
274
275             ObDereferenceObject(Queue);
276          }
277       }
278
279       ObDereferenceObject(FileObject);
280       return Status;
281 #endif /* LIBCAPTIVE */
282    }
283
284    DeviceObject = FileObject->DeviceObject;
285    
286    Irp = IoAllocateIrp(DeviceObject->StackSize,
287                        TRUE);
288    if (Irp == NULL)
289      {
290         ObDereferenceObject(FileObject);
291         return STATUS_INSUFFICIENT_RESOURCES;
292      }
293    
294    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
295                                         Length,
296                                         TAG_SYSB);
297    if (SystemBuffer == NULL)
298      {
299         IoFreeIrp(Irp);
300         ObDereferenceObject(FileObject);
301         return(STATUS_INSUFFICIENT_RESOURCES);
302      }
303    
304    MmSafeCopyFromUser(SystemBuffer,
305                       FileInformation,
306                       Length);
307    
308    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
309    Irp->UserIosb = &IoSB;
310    Irp->UserEvent = &FileObject->Event;
311    KeResetEvent( &FileObject->Event );
312    
313    StackPtr = IoGetNextIrpStackLocation(Irp);
314    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
315    StackPtr->MinorFunction = 0;
316    StackPtr->Flags = 0;
317    StackPtr->Control = 0;
318    StackPtr->DeviceObject = DeviceObject;
319    StackPtr->FileObject = FileObject;
320    
321    StackPtr->Parameters.SetFile.Length = Length;
322    StackPtr->Parameters.SetFile.FileInformationClass =
323      FileInformationClass;
324    switch (FileInformationClass)
325      {
326        case FileRenameInformation: {
327 FILE_RENAME_INFORMATION *RenameInformation=(FILE_RENAME_INFORMATION *)FileInformation;
328 OBJECT_ATTRIBUTES file_ObjectAttributes;
329 UNICODE_STRING file_ObjectAttributes_ObjectName_UnicodeString;
330 IO_STATUS_BLOCK file_IoStatusBlock;
331
332          /* Create target 'StackPtr->Parameters.SetFile.FileObject'
333           * by a special way below to open the target directory
334           * from the given full pathname by 'SL_OPEN_TARGET_DIRECTORY'.
335           */
336          RtlInitUnicodeString(&file_ObjectAttributes_ObjectName_UnicodeString, RenameInformation->FileName);
337          InitializeObjectAttributes(
338              &file_ObjectAttributes,    /* InitializedAttributes */
339              &file_ObjectAttributes_ObjectName_UnicodeString,   /* ObjectName */
340              OBJ_KERNEL_HANDLE | (0/* FIXME: when to use it? */ ? 0x2000/* FIXME: meaning? */ : 0),     /* Attributes */
341              RenameInformation->RootDir,        /* RootDirectory */
342              NULL);     /* SecurityDescriptor; ignored */
343          Status=IoCreateFile(
344              &RootDir_FileHandle,       /* FileHandle */
345              FILE_ADD_FILE | 0x100000/* FIXME: meaning? */,     /* DesiredAccess */
346              &file_ObjectAttributes,    /* ObjectAttributes */
347              &file_IoStatusBlock,       /* IoStatusBlock */
348              NULL,      /* AllocationSize; ignored for open */
349              0, /* FileAttributes; ignored for open */
350              FILE_SHARE_READ|FILE_SHARE_WRITE,  /* ShareAccess; 0 means exclusive */
351              FILE_OPEN, /* CreateDisposition */
352              FILE_OPEN_FOR_BACKUP_INTENT/* FIXME: why? meaning? */,     /* CreateOptions */
353              NULL,      /* EaBuffer */
354              0, /* EaLength */
355              CreateFileTypeNone,        /* CreateFileType */
356              NULL,      /* ExtraCreateParameters */
357              IO_NO_PARAMETER_CHECKING|IO_FORCE_ACCESS_CHECK|SL_OPEN_TARGET_DIRECTORY);  /* Options */
358          if (!NT_SUCCESS(Status))
359            {
360               return Status;
361            }
362
363          /*  Get the file object from the file handle  */
364          Status = ObReferenceObjectByHandle(RootDir_FileHandle,
365                                      (FILE_ADD_FILE | (0/* FIXME: when? */ ? FILE_ADD_SUBDIRECTORY : 0)),
366                                      IoFileObjectType,
367                                      KernelMode,
368                                      (PVOID *)&RootDir_FileObject,
369                                      NULL);
370          if (!NT_SUCCESS(Status))
371            {
372               NtClose(RootDir_FileHandle);      /* errors ignored */
373               return Status;
374            }
375          /* 'StackPtr->FileObject' should be the source file,
376           * 'StackPtr->Parameters.SetFile.FileObject' should be the target directory.
377           */
378          StackPtr->Parameters.SetFile.FileObject=RootDir_FileObject;
379          StackPtr->Parameters.SetFile.u.d.ReplaceIfExists=RenameInformation->Replace;
380          StackPtr->Parameters.SetFile.u.d.AdvanceOnly=FALSE;
381          } break;
382        default:;
383      }
384    
385    /*
386     * Pass the IRP to the FSD (and wait for
387     * it if required)
388     */
389    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
390    Status = IoCallDriver(FileObject->DeviceObject,
391                          Irp);
392    if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
393      {
394         KeWaitForSingleObject(&FileObject->Event,
395                               Executive,
396                               KernelMode,
397                               FALSE,
398                               NULL);
399         Status = IoSB.Status;
400      }
401    if (IoStatusBlock)
402      {
403        *IoStatusBlock = IoSB;
404      }
405    if (RootDir_FileObject != NULL)
406      {
407        NtClose(RootDir_FileHandle);     /* errors ignored */
408        ObDereferenceObject(RootDir_FileObject);
409      }
410    ExFreePool(SystemBuffer);
411  
412    return Status;
413 }
414
415 #ifndef LIBCAPTIVE
416
417 NTSTATUS STDCALL
418 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
419                       OUT PFILE_BASIC_INFORMATION FileInformation)
420 {
421   IO_STATUS_BLOCK IoStatusBlock;
422   HANDLE FileHandle;
423   NTSTATUS Status;
424
425   /* Open the file */
426   Status = NtOpenFile (&FileHandle,
427                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
428                        ObjectAttributes,
429                        &IoStatusBlock,
430                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
431                        FILE_SYNCHRONOUS_IO_NONALERT);
432   if (!NT_SUCCESS (Status))
433     {
434       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
435       return Status;
436     }
437
438   /* Get file attributes */
439   Status = NtQueryInformationFile (FileHandle,
440                                    &IoStatusBlock,
441                                    FileInformation,
442                                    sizeof(FILE_BASIC_INFORMATION),
443                                    FileBasicInformation);
444   NtClose (FileHandle);
445   if (!NT_SUCCESS (Status))
446     {
447       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
448     }
449
450   return Status;
451 }
452
453
454 NTSTATUS STDCALL
455 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
456                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
457 {
458   IO_STATUS_BLOCK IoStatusBlock;
459   HANDLE FileHandle;
460   NTSTATUS Status;
461
462   /* Open the file */
463   Status = NtOpenFile (&FileHandle,
464                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
465                        ObjectAttributes,
466                        &IoStatusBlock,
467                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
468                        FILE_SYNCHRONOUS_IO_NONALERT);
469   if (!NT_SUCCESS (Status))
470     {
471       DPRINT ("NtOpenFile() failed (Status %lx)\n", Status);
472       return Status;
473     }
474
475   /* Get file attributes */
476   Status = NtQueryInformationFile (FileHandle,
477                                    &IoStatusBlock,
478                                    FileInformation,
479                                    sizeof(FILE_NETWORK_OPEN_INFORMATION),
480                                    FileNetworkOpenInformation);
481   NtClose (FileHandle);
482   if (!NT_SUCCESS (Status))
483     {
484       DPRINT ("NtQueryInformationFile() failed (Status %lx)\n", Status);
485     }
486
487   return Status;
488 }
489
490
491 NTSTATUS STDCALL
492 NtQueryEaFile(IN HANDLE FileHandle,
493               OUT PIO_STATUS_BLOCK IoStatusBlock,
494               OUT PVOID Buffer,
495               IN ULONG Length,
496               IN BOOLEAN ReturnSingleEntry,
497               IN PVOID EaList OPTIONAL,
498               IN ULONG EaListLength,
499               IN PULONG EaIndex OPTIONAL,
500               IN BOOLEAN RestartScan)
501 {
502    UNIMPLEMENTED;
503    return STATUS_NOT_IMPLEMENTED;
504 }
505
506
507 NTSTATUS STDCALL
508 NtSetEaFile(IN HANDLE FileHandle,
509             IN PIO_STATUS_BLOCK IoStatusBlock,
510             IN PVOID EaBuffer,
511             IN ULONG EaBufferSize)
512 {
513    UNIMPLEMENTED;
514    return STATUS_NOT_IMPLEMENTED;
515 }
516
517 #endif /* LIBCAPTIVE */
518
519 /* EOF */