[FASTFAT] Start implementing FAT32 statistics support
[reactos.git] / drivers / filesystems / npfs / fileinfo.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/fileinfo.c
5 * PURPOSE: Pipes Information
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FILEINFO)
15
16 /* FUNCTIONS ******************************************************************/
17
18 NTSTATUS
19 NTAPI
20 NpSetBasicInfo(IN PNP_CCB Ccb,
21 IN PFILE_BASIC_INFORMATION Buffer)
22 {
23 PAGED_CODE();
24 return STATUS_SUCCESS;
25 }
26
27 NTSTATUS
28 NTAPI
29 NpSetPipeInfo(IN PNP_FCB Fcb,
30 IN PNP_CCB Ccb,
31 IN PFILE_PIPE_INFORMATION Buffer,
32 IN ULONG NamedPipeEnd,
33 IN PLIST_ENTRY List)
34 {
35 NTSTATUS Status;
36 PNP_DATA_QUEUE ReadQueue, WriteQueue;
37 PAGED_CODE();
38
39 if (Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE && Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE)
40 {
41 return STATUS_INVALID_PARAMETER;
42 }
43
44 if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
45 {
46 if (NamedPipeEnd != FILE_PIPE_SERVER_END)
47 {
48 NpBugCheck(NamedPipeEnd, 0, 0);
49 }
50 ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
51 WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
52 }
53 else
54 {
55 ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
56 WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
57 }
58
59 if (Buffer->CompletionMode != FILE_PIPE_COMPLETE_OPERATION ||
60 Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION ||
61 (ReadQueue->QueueState != ReadEntries &&
62 WriteQueue->QueueState != WriteEntries))
63 {
64 Ccb->ReadMode[NamedPipeEnd] = Buffer->ReadMode & 0xFF;
65 Ccb->CompletionMode[NamedPipeEnd] = Buffer->CompletionMode & 0xFF;
66
67 NpCheckForNotify(Fcb->ParentDcb, FALSE, List);
68 Status = STATUS_SUCCESS;
69 }
70 else
71 {
72 Status = STATUS_PIPE_BUSY;
73 }
74
75 return Status;
76 }
77
78 NTSTATUS
79 NTAPI
80 NpCommonSetInformation(IN PDEVICE_OBJECT DeviceObject,
81 IN PIRP Irp,
82 IN PLIST_ENTRY List)
83 {
84 NODE_TYPE_CODE NodeTypeCode;
85 PIO_STACK_LOCATION IoStack;
86 ULONG InfoClass;
87 PVOID Buffer;
88 PNP_FCB Fcb;
89 PNP_CCB Ccb;
90 ULONG NamedPipeEnd;
91 PAGED_CODE();
92
93 IoStack = IoGetCurrentIrpStackLocation(Irp);
94
95 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
96 (PVOID*)&Fcb,
97 &Ccb,
98 &NamedPipeEnd);
99 if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED;
100 if (NodeTypeCode != NPFS_NTC_CCB) return STATUS_INVALID_PARAMETER;
101
102 InfoClass = IoStack->Parameters.QueryFile.FileInformationClass;
103 Buffer = Irp->AssociatedIrp.SystemBuffer;
104
105 if (InfoClass == FileBasicInformation) return NpSetBasicInfo(Ccb, Buffer);
106
107 if (InfoClass != FilePipeInformation) return STATUS_INVALID_PARAMETER;
108
109 return NpSetPipeInfo(Fcb, Ccb, Buffer, NamedPipeEnd, List);
110 }
111
112 NTSTATUS
113 NTAPI
114 NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
115 IN PIRP Irp)
116 {
117 NTSTATUS Status;
118 LIST_ENTRY DeferredList;
119 PAGED_CODE();
120
121 InitializeListHead(&DeferredList);
122
123 FsRtlEnterFileSystem();
124 NpAcquireExclusiveVcb();
125
126 Status = NpCommonSetInformation(DeviceObject, Irp, &DeferredList);
127
128 NpReleaseVcb();
129 NpCompleteDeferredIrps(&DeferredList);
130 FsRtlExitFileSystem();
131
132 if (Status != STATUS_PENDING)
133 {
134 Irp->IoStatus.Status = Status;
135 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
136 }
137
138 return Status;
139 }
140
141 NTSTATUS
142 NTAPI
143 NpQueryBasicInfo(IN PNP_CCB Ccb,
144 IN PVOID Buffer,
145 IN OUT PULONG Length)
146 {
147 PFILE_BASIC_INFORMATION InfoBuffer = Buffer;
148
149 *Length -= sizeof(*InfoBuffer);
150
151 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
152 InfoBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
153
154 return STATUS_SUCCESS;
155 }
156
157 NTSTATUS
158 NTAPI
159 NpQueryStandardInfo(IN PNP_CCB Ccb,
160 IN PVOID Buffer,
161 IN OUT PULONG Length,
162 IN ULONG NamedPipeEnd)
163 {
164 PNP_DATA_QUEUE DataQueue;
165 PFILE_STANDARD_INFORMATION InfoBuffer = Buffer;
166
167 *Length -= sizeof(*InfoBuffer);
168
169 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
170
171 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
172 {
173 DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
174 }
175 else
176 {
177 DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
178 }
179
180 InfoBuffer->AllocationSize.LowPart = Ccb->DataQueue[FILE_PIPE_INBOUND].Quota +
181 Ccb->DataQueue[FILE_PIPE_OUTBOUND].Quota;
182 InfoBuffer->AllocationSize.HighPart = 0;
183
184 if (DataQueue->QueueState == WriteEntries)
185 {
186 InfoBuffer->EndOfFile.HighPart = 0;
187 InfoBuffer->EndOfFile.LowPart = DataQueue->BytesInQueue -
188 DataQueue->ByteOffset;
189 }
190
191 InfoBuffer->Directory = FALSE;
192 InfoBuffer->NumberOfLinks = 1;
193 InfoBuffer->DeletePending = TRUE;
194
195 return STATUS_SUCCESS;
196 }
197
198 NTSTATUS
199 NTAPI
200 NpQueryEaInfo(IN PNP_CCB Ccb,
201 IN PVOID Buffer,
202 IN OUT PULONG Length)
203 {
204 PFILE_EA_INFORMATION InfoBuffer = Buffer;
205
206 *Length -= sizeof(*InfoBuffer);
207
208 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
209
210 return STATUS_SUCCESS;
211 }
212
213 NTSTATUS
214 NTAPI
215 NpQueryNameInfo(IN PNP_CCB Ccb,
216 IN PVOID Buffer,
217 IN OUT PULONG Length)
218 {
219 PFILE_NAME_INFORMATION InfoBuffer = Buffer;
220 USHORT NameLength;
221 NTSTATUS Status;
222 PWCHAR Name;
223
224 *Length -= sizeof(*InfoBuffer);
225
226 if (Ccb->NodeType == NPFS_NTC_ROOT_DCB_CCB)
227 {
228 NameLength = NpVcb->RootDcb->FullName.Length;
229 Name = NpVcb->RootDcb->FullName.Buffer;
230 }
231 else
232 {
233 NameLength = Ccb->Fcb->FullName.Length;
234 Name = Ccb->Fcb->FullName.Buffer;
235 }
236
237 if (*Length < NameLength)
238 {
239 Status = STATUS_BUFFER_OVERFLOW;
240 NameLength = (USHORT)*Length;
241 }
242 else
243 {
244 Status = STATUS_SUCCESS;
245 }
246
247 RtlCopyMemory(InfoBuffer->FileName, Name, NameLength);
248 InfoBuffer->FileNameLength = NameLength;
249
250 *Length -= NameLength;
251 return Status;
252 }
253
254 NTSTATUS
255 NTAPI
256 NpQueryInternalInfo(IN PNP_CCB Ccb,
257 IN PVOID Buffer,
258 IN OUT PULONG Length)
259 {
260 PFILE_INTERNAL_INFORMATION InfoBuffer = Buffer;
261
262 *Length -= sizeof(*InfoBuffer);
263
264 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
265
266 return STATUS_SUCCESS;
267 }
268
269 NTSTATUS
270 NTAPI
271 NpQueryPositionInfo(IN PNP_CCB Ccb,
272 IN PVOID Buffer,
273 IN OUT PULONG Length,
274 IN ULONG NamedPipeEnd)
275 {
276 PNP_DATA_QUEUE DataQueue;
277 PFILE_POSITION_INFORMATION InfoBuffer = Buffer;
278
279 *Length -= sizeof(*InfoBuffer);
280
281 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
282
283 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
284 {
285 DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
286 }
287 else
288 {
289 DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
290 }
291
292 if (DataQueue->QueueState == WriteEntries)
293 {
294 InfoBuffer->CurrentByteOffset.QuadPart = DataQueue->BytesInQueue -
295 DataQueue->ByteOffset;
296 }
297
298 return STATUS_SUCCESS;
299 }
300
301 NTSTATUS
302 NTAPI
303 NpQueryPipeLocalInfo(IN PNP_FCB Fcb,
304 IN PNP_CCB Ccb,
305 IN PVOID Buffer,
306 IN OUT PULONG Length,
307 IN ULONG NamedPipeEnd)
308 {
309 PFILE_PIPE_LOCAL_INFORMATION InfoBuffer = Buffer;
310 PNP_DATA_QUEUE InQueue, OutQueue;
311
312 *Length -= sizeof(*InfoBuffer);
313
314 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
315
316 InQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
317 OutQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
318
319 InfoBuffer->NamedPipeType = Fcb->NamedPipeType;
320 InfoBuffer->NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
321 InfoBuffer->MaximumInstances = Fcb->MaximumInstances;
322 InfoBuffer->CurrentInstances = Fcb->CurrentInstances;
323 InfoBuffer->InboundQuota = InQueue->Quota;
324 InfoBuffer->OutboundQuota = OutQueue->Quota;
325 InfoBuffer->NamedPipeState = Ccb->NamedPipeState;
326 InfoBuffer->NamedPipeEnd = NamedPipeEnd;
327
328 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
329 {
330 if (InQueue->QueueState == WriteEntries)
331 {
332 InfoBuffer->ReadDataAvailable = InQueue->BytesInQueue - InQueue->ByteOffset;
333 }
334 InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - OutQueue->QuotaUsed;
335 }
336 else
337 {
338 if (OutQueue->QueueState == WriteEntries)
339 {
340 InfoBuffer->ReadDataAvailable = OutQueue->BytesInQueue - OutQueue->ByteOffset;
341 }
342 InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - InQueue->QuotaUsed;
343 }
344
345 return STATUS_SUCCESS;
346 }
347
348 NTSTATUS
349 NTAPI
350 NpQueryPipeInfo(IN PNP_FCB Fcb,
351 IN PNP_CCB Ccb,
352 IN PVOID Buffer,
353 IN OUT PULONG Length,
354 IN ULONG NamedPipeEnd)
355 {
356 PFILE_PIPE_INFORMATION InfoBuffer = Buffer;
357
358 *Length -= sizeof(*InfoBuffer);
359
360 RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
361
362 InfoBuffer->ReadMode = Ccb->ReadMode[NamedPipeEnd];
363 InfoBuffer->CompletionMode = Ccb->CompletionMode[NamedPipeEnd];
364
365 return STATUS_SUCCESS;
366 }
367
368 NTSTATUS
369 NTAPI
370 NpCommonQueryInformation(IN PDEVICE_OBJECT DeviceObject,
371 IN PIRP Irp)
372 {
373 PIO_STACK_LOCATION IoStack;
374 NODE_TYPE_CODE NodeTypeCode;
375 ULONG NamedPipeEnd;
376 PNP_FCB Fcb;
377 PNP_CCB Ccb;
378 FILE_INFORMATION_CLASS InfoClass;
379 ULONG Length;
380 PVOID Buffer;
381 PFILE_ALL_INFORMATION AllInfo;
382 NTSTATUS Status;
383 PAGED_CODE();
384
385 IoStack = IoGetCurrentIrpStackLocation(Irp);
386 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
387 (PVOID*)&Fcb,
388 &Ccb,
389 &NamedPipeEnd);
390 if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED;
391
392 Buffer = Irp->AssociatedIrp.SystemBuffer;
393 Length = IoStack->Parameters.QueryFile.Length;
394 InfoClass = IoStack->Parameters.QueryFile.FileInformationClass;
395
396 if (NodeTypeCode != NPFS_NTC_CCB)
397 {
398 if (NodeTypeCode != NPFS_NTC_ROOT_DCB || InfoClass != FileNameInformation)
399 {
400 return STATUS_INVALID_PARAMETER;
401 }
402 }
403
404 switch (InfoClass)
405 {
406 case FileNameInformation:
407 Status = NpQueryNameInfo(Ccb, Buffer, &Length);
408 break;
409
410 case FilePositionInformation:
411 Status = NpQueryPositionInfo(Ccb, Buffer, &Length, NamedPipeEnd);
412 break;
413
414 case FilePipeInformation:
415 Status = NpQueryPipeInfo(Fcb, Ccb, Buffer, &Length, NamedPipeEnd);
416 break;
417
418 case FilePipeLocalInformation:
419 Status = NpQueryPipeLocalInfo(Fcb, Ccb, Buffer, &Length, NamedPipeEnd);
420 break;
421
422 case FileBasicInformation:
423 Status = NpQueryBasicInfo(Ccb, Buffer, &Length);
424 break;
425
426 case FileStandardInformation:
427 Status = NpQueryStandardInfo(Ccb, Buffer, &Length, NamedPipeEnd);
428 break;
429
430 case FileInternalInformation:
431 Status = NpQueryInternalInfo(Ccb, Buffer, &Length);
432 break;
433
434 case FileAllInformation:
435
436 Length -= 12;
437 AllInfo = (PFILE_ALL_INFORMATION)Buffer;
438 NpQueryBasicInfo(Ccb, &AllInfo->BasicInformation, &Length);
439 NpQueryStandardInfo(Ccb, &AllInfo->StandardInformation, &Length, NamedPipeEnd);
440 NpQueryInternalInfo(Ccb, &AllInfo->InternalInformation, &Length);
441 NpQueryEaInfo(Ccb, &AllInfo->EaInformation, &Length);
442 NpQueryPositionInfo(Ccb, &AllInfo->PositionInformation, &Length, NamedPipeEnd);
443 Status = NpQueryNameInfo(Ccb, &AllInfo->NameInformation, &Length);
444 Length += 96;
445 break;
446
447 case FileEaInformation:
448 Status = NpQueryEaInfo(Ccb, Buffer, &Length);
449 break;
450
451 default:
452 Status = STATUS_INVALID_PARAMETER;
453 break;
454 }
455
456 Irp->IoStatus.Information = IoStack->Parameters.Read.Length - Length;
457 return Status;
458 }
459
460 NTSTATUS
461 NTAPI
462 NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
463 IN PIRP Irp)
464 {
465 NTSTATUS Status;
466 PAGED_CODE();
467
468 FsRtlEnterFileSystem();
469 NpAcquireSharedVcb();
470
471 Status = NpCommonQueryInformation(DeviceObject, Irp);
472
473 NpReleaseVcb();
474 FsRtlExitFileSystem();
475
476 if (Status != STATUS_PENDING)
477 {
478 Irp->IoStatus.Status = Status;
479 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
480 }
481
482 return Status;
483 }
484
485 /* EOF */