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