NtQueryDirectoryFile(): +support FileBothDirInformation; not just FileIdBothDirInform...
[reactos.git] / ntoskrnl / io / dir.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS kernel
5  * FILE:            ntoskrnl/io/dir.c
6  * PURPOSE:         Directory functions
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
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 /* FUNCTIONS *****************************************************************/
21
22 #ifndef LIBCAPTIVE
23
24
25 NTSTATUS
26 STDCALL
27 NtNotifyChangeDirectoryFile (
28         IN      HANDLE                  FileHandle,
29         IN      HANDLE                  Event           OPTIONAL, 
30         IN      PIO_APC_ROUTINE         ApcRoutine      OPTIONAL, 
31         IN      PVOID                   ApcContext      OPTIONAL, 
32         OUT     PIO_STATUS_BLOCK        IoStatusBlock,
33         OUT     PVOID                   Buffer,
34         IN      ULONG                   BufferSize,
35         IN      ULONG                   CompletionFilter,
36         IN      BOOLEAN                 WatchTree
37         )
38 {
39         UNIMPLEMENTED;
40 }
41
42 #endif /* LIBCAPTIVE */
43
44 NTSTATUS
45 STDCALL 
46 NtQueryDirectoryFile(
47         IN      HANDLE                  FileHandle,
48         IN      HANDLE                  PEvent          OPTIONAL,
49         IN      PIO_APC_ROUTINE         ApcRoutine      OPTIONAL,
50         IN      PVOID                   ApcContext      OPTIONAL,
51         OUT     PIO_STATUS_BLOCK        IoStatusBlock,
52         OUT     PVOID                   FileInformation,
53         IN      ULONG                   Length,
54         IN      FILE_INFORMATION_CLASS  FileInformationClass,
55         IN      BOOLEAN                 ReturnSingleEntry,
56         IN      PUNICODE_STRING         FileName        OPTIONAL,
57         IN      BOOLEAN                 RestartScan
58         )
59 /*
60  * FUNCTION: Queries a directory file.
61  * ARGUMENTS:
62  *        FileHandle = Handle to a directory file
63  *        EventHandle  = Handle to the event signaled on completion
64  *        ApcRoutine = Asynchroneous procedure callback, called on completion
65  *        ApcContext = Argument to the apc.
66  *        IoStatusBlock = Caller supplies storage for extended status information.
67  *        FileInformation = Caller supplies storage for the resulting information.
68  *
69  *              FileNameInformation             FILE_NAMES_INFORMATION
70  *              FileDirectoryInformation        FILE_DIRECTORY_INFORMATION
71  *              FileFullDirectoryInformation    FILE_FULL_DIRECTORY_INFORMATION
72  *              FileBothDirectoryInformation    FILE_BOTH_DIR_INFORMATION
73  *
74  *        Length = Size of the storage supplied
75  *        FileInformationClass = Indicates the type of information requested.  
76  *        ReturnSingleEntry = Specify true if caller only requests the first 
77  *                            directory found.
78  *        FileName = Initial directory name to query, that may contain wild 
79  *                   cards.
80  *        RestartScan = Number of times the action should be repeated
81  * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
82  *                   STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
83  *                   STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
84  */
85 {
86    PIRP Irp;
87    PDEVICE_OBJECT DeviceObject;
88    PFILE_OBJECT FileObject;
89    NTSTATUS Status;
90    PIO_STACK_LOCATION IoStack;
91    IO_STATUS_BLOCK IoSB;
92    
93    DPRINT("NtQueryDirectoryFile()\n");
94    
95    Status = ObReferenceObjectByHandle(FileHandle,
96                                       FILE_LIST_DIRECTORY,
97                                       IoFileObjectType,
98                                       UserMode,
99                                       (PVOID *)&FileObject,
100                                       NULL);
101    
102    if (Status != STATUS_SUCCESS)
103      {
104         ObDereferenceObject(FileObject);
105         return(Status);
106      }
107    DeviceObject = FileObject->DeviceObject;
108    
109    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
110    if (Irp==NULL)
111      {
112         ObDereferenceObject(FileObject);
113         return STATUS_UNSUCCESSFUL;
114      }
115    
116    
117    Irp->UserIosb = &IoSB;
118    Irp->UserEvent = &FileObject->Event;
119    KeResetEvent( &FileObject->Event );
120    Irp->UserBuffer=FileInformation;
121    
122    IoStack = IoGetNextIrpStackLocation(Irp);
123    
124    IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
125    IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
126    IoStack->Flags = 0;
127    IoStack->Control = 0;
128    IoStack->DeviceObject = DeviceObject;
129    IoStack->FileObject = FileObject;
130    
131    if (RestartScan)
132      {
133         IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
134      }
135    if (ReturnSingleEntry)
136      {
137         IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
138      }
139    /* SL_INDEX_SPECIFIED may take precedense over SL_RESTART_SCAN
140     * and 'FileInformation' may not be valid if !RestartScan.
141     * ext2fsd.sys-V0.10A requires unspecified SL_INDEX_SPECIFIED
142     * as it would otherwise expect direct pointer to EXT2 directory data block
143     * which we have no information about. FIXME: Why W32 filesystems required
144     * SL_INDEX_SPECIFIED? Is it still valid?
145     */
146    if (!RestartScan)
147      {
148         switch (FileInformationClass) {
149            case FileIdBothDirectoryInformation:
150               IoStack->Parameters.QueryDirectory.FileIndex = ((FILE_ID_BOTH_DIR_INFORMATION *)FileInformation)->FileIndex;
151               break;
152            case FileBothDirectoryInformation:
153               IoStack->Parameters.QueryDirectory.FileIndex = ((FILE_BOTH_DIR_INFORMATION *)FileInformation)->FileIndex;
154               break;
155            default: KeBugCheck(0); /* FIXME: such 'FileInformationClass' NOT IMPLEMENTED YET */
156            }
157         if (IoStack->Parameters.QueryDirectory.FileIndex)
158            IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
159      }
160    
161    IoStack->Parameters.QueryDirectory.FileInformationClass = 
162      FileInformationClass;
163    IoStack->Parameters.QueryDirectory.FileName = FileName;
164    IoStack->Parameters.QueryDirectory.Length = Length;
165    
166    Status = IoCallDriver(FileObject->DeviceObject,Irp);
167    if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
168      {
169         if (FileObject->Flags & FO_ALERTABLE_IO)
170           {
171              KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,TRUE,NULL);
172           }
173         else
174           {
175              KeWaitForSingleObject(&FileObject->Event,Executive,KernelMode,FALSE,NULL);
176           }
177         Status = IoSB.Status;
178      }
179    if (IoStatusBlock)
180      {
181        *IoStatusBlock = IoSB;
182      }
183    return(Status);
184 }
185
186 #ifndef LIBCAPTIVE
187
188 NTSTATUS STDCALL NtQueryOleDirectoryFile(VOID)
189 {
190    UNIMPLEMENTED;
191 }
192
193 #endif /* LIBCAPTIVE */
194
195 /* EOF */