NtSetInformationFile()/FileRenameInformation:
[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    DeviceObject = FileObject->DeviceObject;
249    
250    Irp = IoAllocateIrp(DeviceObject->StackSize,
251                        TRUE);
252    if (Irp == NULL)
253      {
254         ObDereferenceObject(FileObject);
255         return STATUS_INSUFFICIENT_RESOURCES;
256      }
257    
258    SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
259                                         Length,
260                                         TAG_SYSB);
261    if (SystemBuffer == NULL)
262      {
263         IoFreeIrp(Irp);
264         ObDereferenceObject(FileObject);
265         return(STATUS_INSUFFICIENT_RESOURCES);
266      }
267    
268    MmSafeCopyFromUser(SystemBuffer,
269                       FileInformation,
270                       Length);
271    
272    Irp->AssociatedIrp.SystemBuffer = SystemBuffer;
273    Irp->UserIosb = &IoSB;
274    Irp->UserEvent = &FileObject->Event;
275    KeResetEvent( &FileObject->Event );
276    
277    StackPtr = IoGetNextIrpStackLocation(Irp);
278    StackPtr->MajorFunction = IRP_MJ_SET_INFORMATION;
279    StackPtr->MinorFunction = 0;
280    StackPtr->Flags = 0;
281    StackPtr->Control = 0;
282    StackPtr->DeviceObject = DeviceObject;
283    StackPtr->FileObject = FileObject;
284    
285    StackPtr->Parameters.SetFile.Length = Length;
286    StackPtr->Parameters.SetFile.FileInformationClass =
287      FileInformationClass;
288    switch (FileInformationClass)
289      {
290        case FileRenameInformation: {
291 FILE_RENAME_INFORMATION *RenameInformation=(FILE_RENAME_INFORMATION *)FileInformation;
292 OBJECT_ATTRIBUTES file_ObjectAttributes;
293 UNICODE_STRING file_ObjectAttributes_ObjectName_UnicodeString;
294 IO_STATUS_BLOCK file_IoStatusBlock;
295
296          /* Create target 'StackPtr->Parameters.SetFile.FileObject'
297           * by a special way below to open the target directory
298           * from the given full pathname by 'SL_OPEN_TARGET_DIRECTORY'.
299           */
300          RtlInitUnicodeString(&file_ObjectAttributes_ObjectName_UnicodeString, RenameInformation->FileName);
301          InitializeObjectAttributes(
302              &file_ObjectAttributes,    /* InitializedAttributes */
303              &file_ObjectAttributes_ObjectName_UnicodeString,   /* ObjectName */
304              OBJ_KERNEL_HANDLE | (0/* FIXME: when to use it? */ ? 0x2000/* FIXME: meaning? */ : 0),     /* Attributes */
305              RenameInformation->RootDir,        /* RootDirectory */
306              NULL);     /* SecurityDescriptor; ignored */
307          Status=IoCreateFile(
308              &RootDir_FileHandle,       /* FileHandle */
309              FILE_ADD_FILE | 0x100000/* FIXME: meaning? */,     /* DesiredAccess */
310              &file_ObjectAttributes,    /* ObjectAttributes */
311              &file_IoStatusBlock,       /* IoStatusBlock */
312              NULL,      /* AllocationSize; ignored for open */
313              0, /* FileAttributes; ignored for open */
314              FILE_SHARE_READ|FILE_SHARE_WRITE,  /* ShareAccess; 0 means exclusive */
315              FILE_OPEN, /* CreateDisposition */
316              FILE_OPEN_FOR_BACKUP_INTENT/* FIXME: why? meaning? */,     /* CreateOptions */
317              NULL,      /* EaBuffer */
318              0, /* EaLength */
319              CreateFileTypeNone,        /* CreateFileType */
320              NULL,      /* ExtraCreateParameters */
321              IO_NO_PARAMETER_CHECKING|IO_FORCE_ACCESS_CHECK|SL_OPEN_TARGET_DIRECTORY);  /* Options */
322          if (!NT_SUCCESS(Status))
323            {
324               return Status;
325            }
326
327          /*  Get the file object from the file handle  */
328          Status = ObReferenceObjectByHandle(RootDir_FileHandle,
329                                      (FILE_ADD_FILE | (0/* FIXME: when? */ ? FILE_ADD_SUBDIRECTORY : 0)),
330                                      IoFileObjectType,
331                                      KernelMode,
332                                      (PVOID *)&RootDir_FileObject,
333                                      NULL);
334          if (!NT_SUCCESS(Status))
335            {
336               NtClose(RootDir_FileHandle);      /* errors ignored */
337               return Status;
338            }
339          /* 'StackPtr->FileObject' should be the source file,
340           * 'StackPtr->Parameters.SetFile.FileObject' should be the target directory.
341           */
342          StackPtr->Parameters.SetFile.FileObject=RootDir_FileObject;
343          StackPtr->Parameters.SetFile.u.d.ReplaceIfExists=RenameInformation->Replace;
344          StackPtr->Parameters.SetFile.u.d.AdvanceOnly=FALSE;
345          } break;
346        default:;
347      }
348    
349    /*
350     * Pass the IRP to the FSD (and wait for
351     * it if required)
352     */
353    DPRINT("FileObject->DeviceObject %x\n", FileObject->DeviceObject);
354    Status = IoCallDriver(FileObject->DeviceObject,
355                          Irp);
356    if (Status == STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
357      {
358         KeWaitForSingleObject(&FileObject->Event,
359                               Executive,
360                               KernelMode,
361                               FALSE,
362                               NULL);
363         Status = IoSB.Status;
364      }
365    if (IoStatusBlock)
366      {
367        *IoStatusBlock = IoSB;
368      }
369    if (RootDir_FileObject != NULL)
370      {
371        NtClose(RootDir_FileHandle);     /* errors ignored */
372        ObDereferenceObject(RootDir_FileObject);
373      }
374    ExFreePool(SystemBuffer);
375  
376    return Status;
377 }
378
379 #ifndef LIBCAPTIVE
380
381 NTSTATUS STDCALL
382 NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
383                       OUT PFILE_BASIC_INFORMATION FileInformation)
384 {
385    UNIMPLEMENTED;
386    return STATUS_NOT_IMPLEMENTED;
387 }
388
389
390 NTSTATUS STDCALL
391 NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
392                           OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
393 {
394    UNIMPLEMENTED;
395    return STATUS_NOT_IMPLEMENTED;
396 }
397
398
399 NTSTATUS STDCALL
400 NtQueryEaFile(IN HANDLE FileHandle,
401               OUT PIO_STATUS_BLOCK IoStatusBlock,
402               OUT PVOID Buffer,
403               IN ULONG Length,
404               IN BOOLEAN ReturnSingleEntry,
405               IN PVOID EaList OPTIONAL,
406               IN ULONG EaListLength,
407               IN PULONG EaIndex OPTIONAL,
408               IN BOOLEAN RestartScan)
409 {
410    UNIMPLEMENTED;
411    return STATUS_NOT_IMPLEMENTED;
412 }
413
414
415 NTSTATUS STDCALL
416 NtSetEaFile(IN HANDLE FileHandle,
417             IN PIO_STATUS_BLOCK IoStatusBlock,
418             IN PVOID EaBuffer,
419             IN ULONG EaBufferSize)
420 {
421    UNIMPLEMENTED;
422    return STATUS_NOT_IMPLEMENTED;
423 }
424
425 #endif /* LIBCAPTIVE */
426
427 /* EOF */