[NTFS] Fix IRP_MJ_QUERY_INFORMATION/FileNameInformation, which should handle buffers...
[reactos.git] / reactos / drivers / filesystems / ntfs / finfo.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/dirctl.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMERS: Eric Kohl
24 * Hervé Poussineau (hpoussin@reactos.org)
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "ntfs.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* FUNCTIONS ****************************************************************/
35
36 /*
37 * FUNCTION: Retrieve the standard file information
38 */
39 static
40 NTSTATUS
41 NtfsGetStandardInformation(PNTFS_FCB Fcb,
42 PDEVICE_OBJECT DeviceObject,
43 PFILE_STANDARD_INFORMATION StandardInfo,
44 PULONG BufferLength)
45 {
46 UNREFERENCED_PARAMETER(DeviceObject);
47
48 DPRINT("NtfsGetStandardInformation() called\n");
49
50 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
51 return STATUS_BUFFER_OVERFLOW;
52
53 /* PRECONDITION */
54 ASSERT(StandardInfo != NULL);
55 ASSERT(Fcb != NULL);
56
57 RtlZeroMemory(StandardInfo,
58 sizeof(FILE_STANDARD_INFORMATION));
59
60 StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize;
61 StandardInfo->EndOfFile = Fcb->RFCB.FileSize;
62 StandardInfo->NumberOfLinks = 0;
63 StandardInfo->DeletePending = FALSE;
64 StandardInfo->Directory = NtfsFCBIsDirectory(Fcb);
65
66 *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
67
68 return STATUS_SUCCESS;
69 }
70
71
72 static
73 NTSTATUS
74 NtfsGetPositionInformation(PFILE_OBJECT FileObject,
75 PFILE_POSITION_INFORMATION PositionInfo,
76 PULONG BufferLength)
77 {
78 UNREFERENCED_PARAMETER(FileObject);
79
80 DPRINT("NtfsGetPositionInformation() called\n");
81
82 if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
83 return STATUS_BUFFER_OVERFLOW;
84
85 PositionInfo->CurrentByteOffset.QuadPart = 0;
86 // FileObject->CurrentByteOffset.QuadPart;
87
88 DPRINT("Getting position %I64x\n",
89 PositionInfo->CurrentByteOffset.QuadPart);
90
91 *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
92
93 return STATUS_SUCCESS;
94 }
95
96
97 static
98 NTSTATUS
99 NtfsGetBasicInformation(PFILE_OBJECT FileObject,
100 PNTFS_FCB Fcb,
101 PDEVICE_OBJECT DeviceObject,
102 PFILE_BASIC_INFORMATION BasicInfo,
103 PULONG BufferLength)
104 {
105 DPRINT("NtfsGetBasicInformation() called\n");
106
107 if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
108 return STATUS_BUFFER_OVERFLOW;
109
110 #if 0
111 CdfsDateTimeToFileTime(Fcb,
112 &BasicInfo->CreationTime);
113 CdfsDateTimeToFileTime(Fcb,
114 &BasicInfo->LastAccessTime);
115 CdfsDateTimeToFileTime(Fcb,
116 &BasicInfo->LastWriteTime);
117 CdfsDateTimeToFileTime(Fcb,
118 &BasicInfo->ChangeTime);
119
120 CdfsFileFlagsToAttributes(Fcb,
121 &BasicInfo->FileAttributes);
122 #else
123 UNREFERENCED_PARAMETER(FileObject);
124 UNREFERENCED_PARAMETER(Fcb);
125 UNREFERENCED_PARAMETER(DeviceObject);
126 UNREFERENCED_PARAMETER(BasicInfo);
127 #endif
128
129 *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
130
131 return STATUS_SUCCESS;
132 }
133
134
135 /*
136 * FUNCTION: Retrieve the file name information
137 */
138 static
139 NTSTATUS
140 NtfsGetNameInformation(PFILE_OBJECT FileObject,
141 PNTFS_FCB Fcb,
142 PDEVICE_OBJECT DeviceObject,
143 PFILE_NAME_INFORMATION NameInfo,
144 PULONG BufferLength)
145 {
146 ULONG BytesToCopy;
147
148 UNREFERENCED_PARAMETER(FileObject);
149 UNREFERENCED_PARAMETER(DeviceObject);
150
151 DPRINT("NtfsGetNameInformation() called\n");
152
153 ASSERT(NameInfo != NULL);
154 ASSERT(Fcb != NULL);
155
156 /* If buffer can't hold at least the file name length, bail out */
157 if (*BufferLength < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
158 return STATUS_BUFFER_OVERFLOW;
159
160 /* Save file name length, and as much file len, as buffer length allows */
161 NameInfo->FileNameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
162
163 /* Calculate amount of bytes to copy not to overflow the buffer */
164 BytesToCopy = min(NameInfo->FileNameLength,
165 *BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
166
167 /* Fill in the bytes */
168 RtlCopyMemory(NameInfo->FileName, Fcb->PathName, BytesToCopy);
169
170 /* Check if we could write more but are not able to */
171 if (*BufferLength < NameInfo->FileNameLength + (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
172 {
173 /* Return number of bytes written */
174 *BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
175 return STATUS_BUFFER_OVERFLOW;
176 }
177
178 /* We filled up as many bytes, as needed */
179 *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + NameInfo->FileNameLength);
180
181 return STATUS_SUCCESS;
182 }
183
184
185 static
186 NTSTATUS
187 NtfsGetInternalInformation(PNTFS_FCB Fcb,
188 PFILE_INTERNAL_INFORMATION InternalInfo,
189 PULONG BufferLength)
190 {
191 DPRINT("NtfsGetInternalInformation() called\n");
192
193 ASSERT(InternalInfo);
194 ASSERT(Fcb);
195
196 if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
197 return STATUS_BUFFER_OVERFLOW;
198
199 /* FIXME: get a real index, that can be used in a create operation */
200 InternalInfo->IndexNumber.QuadPart = 0;
201
202 *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
203
204 return STATUS_SUCCESS;
205 }
206
207
208 /*
209 * FUNCTION: Retrieve the specified file information
210 */
211 NTSTATUS
212 NTAPI
213 NtfsFsdQueryInformation(PDEVICE_OBJECT DeviceObject,
214 PIRP Irp)
215 {
216 FILE_INFORMATION_CLASS FileInformationClass;
217 PIO_STACK_LOCATION Stack;
218 PFILE_OBJECT FileObject;
219 PNTFS_FCB Fcb;
220 PVOID SystemBuffer;
221 ULONG BufferLength;
222 NTSTATUS Status = STATUS_SUCCESS;
223
224 DPRINT("NtfsQueryInformation() called\n");
225
226 Stack = IoGetCurrentIrpStackLocation(Irp);
227 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
228 FileObject = Stack->FileObject;
229 Fcb = FileObject->FsContext;
230
231 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
232 BufferLength = Stack->Parameters.QueryFile.Length;
233
234 switch (FileInformationClass)
235 {
236 case FileStandardInformation:
237 Status = NtfsGetStandardInformation(Fcb,
238 DeviceObject,
239 SystemBuffer,
240 &BufferLength);
241 break;
242
243 case FilePositionInformation:
244 Status = NtfsGetPositionInformation(FileObject,
245 SystemBuffer,
246 &BufferLength);
247 break;
248
249 case FileBasicInformation:
250 Status = NtfsGetBasicInformation(FileObject,
251 Fcb,
252 DeviceObject,
253 SystemBuffer,
254 &BufferLength);
255 break;
256
257 case FileNameInformation:
258 Status = NtfsGetNameInformation(FileObject,
259 Fcb,
260 DeviceObject,
261 SystemBuffer,
262 &BufferLength);
263 break;
264
265 case FileInternalInformation:
266 Status = NtfsGetInternalInformation(Fcb,
267 SystemBuffer,
268 &BufferLength);
269 break;
270
271 case FileAlternateNameInformation:
272 case FileAllInformation:
273 Status = STATUS_NOT_IMPLEMENTED;
274 break;
275
276 default:
277 DPRINT("Unimplemented information class %u\n", FileInformationClass);
278 Status = STATUS_INVALID_PARAMETER;
279 }
280
281 Irp->IoStatus.Status = Status;
282
283 if (NT_SUCCESS(Status))
284 Irp->IoStatus.Information =
285 Stack->Parameters.QueryFile.Length - BufferLength;
286 else
287 Irp->IoStatus.Information = 0;
288
289 IoCompleteRequest(Irp, IO_NO_INCREMENT);
290
291 return Status;
292 }
293
294 /* EOF */