xref: /reactos/drivers/filesystems/npfs/fileinfo.c (revision 84ccccab)
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 */
486