Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1304 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. FileInfo.c
  5. Abstract:
  6. This module implements the File Info routines for NPFS called by the
  7. dispatch driver. There are two entry points NpFsdQueryInformation
  8. and NpFsdSetInformation.
  9. Author:
  10. Gary Kimura [GaryKi] 21-Aug-1990
  11. Revision History:
  12. --*/
  13. #include "NpProcs.h"
  14. //
  15. // The Bug check file id for this module
  16. //
  17. #define BugCheckFileId (NPFS_BUG_CHECK_FILEINFO)
  18. //
  19. // The debug trace level
  20. //
  21. #define Dbg (DEBUG_TRACE_FILEINFO)
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE, NpCommonQueryInformation)
  24. #pragma alloc_text(PAGE, NpCommonSetInformation)
  25. #pragma alloc_text(PAGE, NpFsdQueryInformation)
  26. #pragma alloc_text(PAGE, NpFsdSetInformation)
  27. #pragma alloc_text(PAGE, NpQueryBasicInfo)
  28. #pragma alloc_text(PAGE, NpQueryEaInfo)
  29. #pragma alloc_text(PAGE, NpQueryInternalInfo)
  30. #pragma alloc_text(PAGE, NpQueryNameInfo)
  31. #pragma alloc_text(PAGE, NpQueryPipeInfo)
  32. #pragma alloc_text(PAGE, NpQueryPipeLocalInfo)
  33. #pragma alloc_text(PAGE, NpQueryPositionInfo)
  34. #pragma alloc_text(PAGE, NpQueryStandardInfo)
  35. #pragma alloc_text(PAGE, NpSetBasicInfo)
  36. #pragma alloc_text(PAGE, NpSetPipeInfo)
  37. #endif
  38. NTSTATUS
  39. NpFsdQueryInformation (
  40. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  41. IN PIRP Irp
  42. )
  43. /*++
  44. Routine Description:
  45. This routine implements the FSD part of the NtQueryInformationFile API
  46. calls.
  47. Arguments:
  48. NpfsDeviceObject - Supplies the device object to use.
  49. Irp - Supplies the Irp being processed
  50. Return Value:
  51. NTSTATUS - The Fsd status for the Irp
  52. --*/
  53. {
  54. NTSTATUS Status;
  55. PAGED_CODE();
  56. DebugTrace(+1, Dbg, "NpFsdQueryInformation\n", 0);
  57. //
  58. // Call the common Query Information routine.
  59. //
  60. FsRtlEnterFileSystem();
  61. NpAcquireSharedVcb();
  62. Status = NpCommonQueryInformation( NpfsDeviceObject, Irp );
  63. NpReleaseVcb();
  64. FsRtlExitFileSystem();
  65. if (Status != STATUS_PENDING) {
  66. NpCompleteRequest (Irp, Status);
  67. }
  68. //
  69. // And return to our caller
  70. //
  71. DebugTrace(-1, Dbg, "NpFsdQueryInformation -> %08lx\n", Status );
  72. return Status;
  73. }
  74. NTSTATUS
  75. NpFsdSetInformation (
  76. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  77. IN PIRP Irp
  78. )
  79. /*++
  80. Routine Description:
  81. This routine implements the FSD part of the NtSetInformationFile API
  82. calls.
  83. Arguments:
  84. NpfsDeviceObject - Supplies the device object to use.
  85. Irp - Supplies the Irp being processed
  86. Return Value:
  87. NTSTATUS - The Fsd status for the Irp
  88. --*/
  89. {
  90. NTSTATUS Status;
  91. LIST_ENTRY DeferredList;
  92. PAGED_CODE();
  93. DebugTrace(+1, Dbg, "NpFsdSetInformation\n", 0);
  94. //
  95. // Call the common Set Information routine.
  96. //
  97. InitializeListHead (&DeferredList);
  98. FsRtlEnterFileSystem ();
  99. NpAcquireExclusiveVcb ();
  100. Status = NpCommonSetInformation (NpfsDeviceObject, Irp, &DeferredList);
  101. NpReleaseVcb ();
  102. //
  103. // Complete the deferred IRPs now we have released the locks
  104. //
  105. NpCompleteDeferredIrps (&DeferredList);
  106. FsRtlExitFileSystem ();
  107. if (Status != STATUS_PENDING) {
  108. NpCompleteRequest (Irp, Status);
  109. }
  110. //
  111. // And return to our caller
  112. //
  113. DebugTrace(-1, Dbg, "NpFsdSetInformation -> %08lx\n", Status );
  114. return Status;
  115. }
  116. //
  117. // Internal support routine
  118. //
  119. NTSTATUS
  120. NpCommonQueryInformation (
  121. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  122. IN PIRP Irp
  123. )
  124. /*++
  125. Routine Description:
  126. This is the common routine for creating/opening a file.
  127. Arguments:
  128. Irp - Supplies the Irp to process
  129. Return Value:
  130. NTSTATUS - the return status for the operation
  131. --*/
  132. {
  133. PIO_STACK_LOCATION IrpSp;
  134. NTSTATUS Status;
  135. ULONG Length;
  136. FILE_INFORMATION_CLASS FileInformationClass;
  137. PVOID Buffer;
  138. NODE_TYPE_CODE NodeTypeCode;
  139. PFCB Fcb;
  140. PCCB Ccb;
  141. NAMED_PIPE_END NamedPipeEnd;
  142. PFILE_ALL_INFORMATION AllInfo;
  143. PAGED_CODE();
  144. //
  145. // Get the current stack location
  146. //
  147. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  148. DebugTrace(+1, Dbg, "NpCommonQueryInformation...\n", 0);
  149. DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp);
  150. DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryFile.Length);
  151. DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryFile.FileInformationClass);
  152. DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
  153. //
  154. // Get the ccb and figure out who we are, and make sure we're not
  155. // disconnected.
  156. //
  157. if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject,
  158. &Fcb,
  159. &Ccb,
  160. &NamedPipeEnd )) == NTC_UNDEFINED) {
  161. DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0);
  162. Status = STATUS_PIPE_DISCONNECTED;
  163. DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status );
  164. return Status;
  165. }
  166. //
  167. // Reference our input parameter to make things easier
  168. //
  169. Length = IrpSp->Parameters.QueryFile.Length;
  170. FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
  171. Buffer = Irp->AssociatedIrp.SystemBuffer;
  172. //
  173. // Case on the type of the context, We can only query information
  174. // on an Fcb, Dcb, or Root Dcb. If we are not passed on of these
  175. // we immediately tell the caller that there is an invalid parameter.
  176. //
  177. if (NodeTypeCode != NPFS_NTC_CCB &&
  178. (NodeTypeCode != NPFS_NTC_ROOT_DCB || FileInformationClass != FileNameInformation)) {
  179. DebugTrace(0, Dbg, "Node type code is not ccb\n", 0);
  180. DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0);
  181. return STATUS_INVALID_PARAMETER;
  182. }
  183. //
  184. // Based on the information class we'll do different actions. Each
  185. // of the procedure that we're calling fill up as much of the
  186. // buffer as possible and return the remaining length, and status
  187. // This is done so that we can use them to build up the
  188. // FileAllInformation request. These procedures do not complete the
  189. // Irp, instead this procedure must complete the Irp.
  190. //
  191. switch (FileInformationClass) {
  192. case FileAllInformation:
  193. //
  194. // For the all information class we'll typecast a local
  195. // pointer to the output buffer and then call the
  196. // individual routines to fill in the buffer.
  197. //
  198. AllInfo = Buffer;
  199. Length -= (sizeof(FILE_ACCESS_INFORMATION)
  200. + sizeof(FILE_MODE_INFORMATION)
  201. + sizeof(FILE_ALIGNMENT_INFORMATION));
  202. //
  203. // Only the QueryName call can return non-success
  204. //
  205. (VOID)NpQueryBasicInfo( Ccb, &AllInfo->BasicInformation, &Length );
  206. (VOID)NpQueryStandardInfo( Ccb, &AllInfo->StandardInformation, &Length, NamedPipeEnd );
  207. (VOID)NpQueryInternalInfo( Ccb, &AllInfo->InternalInformation, &Length );
  208. (VOID)NpQueryEaInfo( Ccb, &AllInfo->EaInformation, &Length );
  209. (VOID)NpQueryPositionInfo( Ccb, &AllInfo->PositionInformation, &Length, NamedPipeEnd );
  210. Status = NpQueryNameInfo( Ccb, &AllInfo->NameInformation, &Length );
  211. break;
  212. case FileBasicInformation:
  213. Status = NpQueryBasicInfo( Ccb, Buffer, &Length );
  214. break;
  215. case FileStandardInformation:
  216. Status = NpQueryStandardInfo( Ccb, Buffer, &Length, NamedPipeEnd );
  217. break;
  218. case FileInternalInformation:
  219. Status = NpQueryInternalInfo( Ccb, Buffer, &Length );
  220. break;
  221. case FileEaInformation:
  222. Status = NpQueryEaInfo( Ccb, Buffer, &Length );
  223. break;
  224. case FilePositionInformation:
  225. Status = NpQueryPositionInfo( Ccb, Buffer, &Length, NamedPipeEnd );
  226. break;
  227. case FileNameInformation:
  228. Status = NpQueryNameInfo( Ccb, Buffer, &Length );
  229. break;
  230. case FilePipeInformation:
  231. Status = NpQueryPipeInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd );
  232. break;
  233. case FilePipeLocalInformation:
  234. Status = NpQueryPipeLocalInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd );
  235. break;
  236. default:
  237. Status = STATUS_INVALID_PARAMETER;
  238. break;
  239. }
  240. //
  241. // Set the information field to the number of bytes actually filled in
  242. // and then complete the request
  243. //
  244. Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
  245. DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status );
  246. return Status;
  247. }
  248. //
  249. // Internal support routine
  250. //
  251. NTSTATUS
  252. NpCommonSetInformation (
  253. IN PNPFS_DEVICE_OBJECT NpfsDeviceObject,
  254. IN PIRP Irp,
  255. IN PLIST_ENTRY DeferredList
  256. )
  257. /*++
  258. Routine Description:
  259. This is the common routine for creating/opening a file.
  260. Arguments:
  261. NpfsDeviceObject - Device object for npfs
  262. Irp - Supplies the Irp to process
  263. DeferredList - List or IRPs to complete after we drop locks
  264. Return Value:
  265. NTSTATUS - the return status for the operation
  266. --*/
  267. {
  268. PIO_STACK_LOCATION IrpSp;
  269. NTSTATUS Status;
  270. ULONG Length;
  271. FILE_INFORMATION_CLASS FileInformationClass;
  272. PVOID Buffer;
  273. NODE_TYPE_CODE NodeTypeCode;
  274. PFCB Fcb;
  275. PCCB Ccb;
  276. NAMED_PIPE_END NamedPipeEnd;
  277. PAGED_CODE();
  278. //
  279. // Get the current Irp stack location
  280. //
  281. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  282. DebugTrace(+1, Dbg, "NpCommonSetInformation...\n", 0);
  283. DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp);
  284. DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.SetFile.Length);
  285. DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass);
  286. DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
  287. //
  288. // Get the ccb and figure out who we are, and make sure we're not
  289. // disconnected.
  290. //
  291. if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject,
  292. &Fcb,
  293. &Ccb,
  294. &NamedPipeEnd )) == NTC_UNDEFINED) {
  295. DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0);
  296. Status = STATUS_PIPE_DISCONNECTED;
  297. DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status );
  298. return Status;
  299. }
  300. //
  301. // Case on the type of the context, We can only query information
  302. // on an Fcb, Dcb, or Root Dcb. If we are not passed on of these
  303. // we immediately tell the caller that there is an invalid parameter.
  304. //
  305. if (NodeTypeCode != NPFS_NTC_CCB) {
  306. DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0);
  307. return STATUS_INVALID_PARAMETER;
  308. }
  309. //
  310. // Reference our input parameter to make things easier
  311. //
  312. Length = IrpSp->Parameters.SetFile.Length;
  313. FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
  314. Buffer = Irp->AssociatedIrp.SystemBuffer;
  315. //
  316. // Based on the information class we'll do differnt actions. Each
  317. // procedure that we're calling will complete the request.
  318. //
  319. switch (FileInformationClass) {
  320. case FileBasicInformation:
  321. Status = NpSetBasicInfo( Ccb, Buffer );
  322. break;
  323. case FilePipeInformation:
  324. Status = NpSetPipeInfo( Fcb, Ccb, Buffer, NamedPipeEnd, DeferredList );
  325. break;
  326. default:
  327. Status = STATUS_INVALID_PARAMETER;
  328. break;
  329. }
  330. DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status);
  331. return Status;
  332. }
  333. //
  334. // Internal support routine
  335. //
  336. NTSTATUS
  337. NpQueryBasicInfo (
  338. IN PCCB Ccb,
  339. IN PFILE_BASIC_INFORMATION Buffer,
  340. IN OUT PULONG Length
  341. )
  342. /*++
  343. Routine Description:
  344. This routine performs the query basic information operation.
  345. Arguments:
  346. Ccb - Supplies the Ccb of the named pipe being queried
  347. Buffer - Supplies a pointer to the buffer where the information is
  348. to be returned
  349. Length - Supplies the length of the buffer in bytes. This variable
  350. upon return will receive the remaining bytes free in the buffer.
  351. Return Value:
  352. NTSTATUS - The result of this query
  353. --*/
  354. {
  355. UNREFERENCED_PARAMETER( Ccb );
  356. PAGED_CODE();
  357. DebugTrace(0, Dbg, "NpQueryBasicInfo...\n", 0);
  358. //
  359. // Update the length field, and zero out the buffer
  360. //
  361. *Length -= sizeof( FILE_BASIC_INFORMATION );
  362. RtlZeroMemory( Buffer, sizeof(FILE_BASIC_INFORMATION) );
  363. //
  364. // Set the various fields in the record
  365. //
  366. //**** need to add the time fields to the fcb/ccb
  367. //
  368. Buffer->CreationTime.LowPart = 0; Buffer->CreationTime.HighPart = 0;
  369. Buffer->LastAccessTime.LowPart = 0; Buffer->LastAccessTime.HighPart = 0;
  370. Buffer->LastWriteTime.LowPart = 0; Buffer->LastWriteTime.HighPart = 0;
  371. Buffer->ChangeTime.LowPart = 0; Buffer->ChangeTime.HighPart = 0;
  372. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  373. //
  374. // and return to our caller
  375. //
  376. return STATUS_SUCCESS;
  377. }
  378. //
  379. // Internal support routine
  380. //
  381. NTSTATUS
  382. NpQueryStandardInfo (
  383. IN PCCB Ccb,
  384. IN PFILE_STANDARD_INFORMATION Buffer,
  385. IN OUT PULONG Length,
  386. IN NAMED_PIPE_END NamedPipeEnd
  387. )
  388. /*++
  389. Routine Description:
  390. This routine performs the query standard information operation.
  391. Arguments:
  392. Ccb - Supplies the Ccb of the named pipe being queried
  393. Buffer - Supplies a pointer to the buffer where the information is
  394. to be returned
  395. Length - Supplies the length of the buffer in bytes. This variable
  396. upon return will receive the remaining bytes free in the buffer.
  397. Return Value:
  398. NTSTATUS - The result of this query
  399. --*/
  400. {
  401. PDATA_QUEUE Inbound;
  402. PDATA_QUEUE Outbound;
  403. PDATA_QUEUE Queue;
  404. PAGED_CODE();
  405. DebugTrace(0, Dbg, "NpQueryStandardInfo...\n", 0);
  406. //
  407. // Update the length field, and zero out the buffer
  408. //
  409. *Length -= sizeof( FILE_STANDARD_INFORMATION );
  410. RtlZeroMemory( Buffer, sizeof(FILE_STANDARD_INFORMATION) );
  411. //
  412. // Set the various fields in the record
  413. //
  414. Inbound = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
  415. Outbound = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
  416. if (NamedPipeEnd == FILE_PIPE_CLIENT_END) {
  417. Queue = Outbound;
  418. } else {
  419. Queue = Inbound;
  420. }
  421. //
  422. // The allocation size is the amount of quota we've charged this pipe
  423. // instance
  424. //
  425. Buffer->AllocationSize.QuadPart = Inbound->Quota + Outbound->Quota;
  426. //
  427. // The Eof is the number of writen bytes ready to be read from the queue
  428. //
  429. if (NpIsDataQueueWriters( Queue )) {
  430. Buffer->EndOfFile.QuadPart = Queue->BytesInQueue - Queue->NextByteOffset;
  431. }
  432. Buffer->NumberOfLinks = 1;
  433. Buffer->DeletePending = TRUE;
  434. Buffer->Directory = FALSE;
  435. //
  436. // And return to our caller
  437. //
  438. return STATUS_SUCCESS;
  439. }
  440. //
  441. // Internal support routine
  442. //
  443. NTSTATUS
  444. NpQueryInternalInfo (
  445. IN PCCB Ccb,
  446. IN PFILE_INTERNAL_INFORMATION Buffer,
  447. IN OUT PULONG Length
  448. )
  449. /*++
  450. Routine Description:
  451. This routine performs the query internal information operation.
  452. Arguments:
  453. Ccb - Supplies the Ccb of the named pipe being queried
  454. Buffer - Supplies a pointer to the buffer where the information is
  455. to be returned
  456. Length - Supplies the length of the buffer in bytes. This variable
  457. upon return will receive the remaining bytes free in the buffer.
  458. Return Value:
  459. NTSTATUS - The result of this query
  460. --*/
  461. {
  462. PAGED_CODE();
  463. DebugTrace(0, Dbg, "NpQueryInternalInfo...\n", 0);
  464. //
  465. // Update the length field, and zero out the buffer
  466. //
  467. *Length -= sizeof(FILE_INTERNAL_INFORMATION);
  468. RtlZeroMemory(Buffer, sizeof(FILE_INTERNAL_INFORMATION));
  469. //
  470. // Set the internal index number to be the fnode lbn;
  471. //
  472. Buffer->IndexNumber.QuadPart = (ULONG_PTR)Ccb;
  473. //
  474. // And return to our caller
  475. //
  476. return STATUS_SUCCESS;
  477. }
  478. //
  479. // Internal support routine
  480. //
  481. NTSTATUS
  482. NpQueryEaInfo (
  483. IN PCCB Ccb,
  484. IN PFILE_EA_INFORMATION Buffer,
  485. IN OUT PULONG Length
  486. )
  487. /*++
  488. Routine Description:
  489. This routine performs the query Ea information operation.
  490. Arguments:
  491. Ccb - Supplies the Ccb of the named pipe being queried
  492. Buffer - Supplies a pointer to the buffer where the information is
  493. to be returned
  494. Length - Supplies the length of the buffer in bytes. This variable
  495. upon return will receive the remaining bytes free in the buffer.
  496. Return Value:
  497. NTSTATUS - The result of this query
  498. --*/
  499. {
  500. UNREFERENCED_PARAMETER( Ccb );
  501. PAGED_CODE();
  502. DebugTrace(0, Dbg, "NpQueryEaInfo...\n", 0);
  503. //
  504. // Update the length field, and zero out the buffer
  505. //
  506. *Length -= sizeof(FILE_EA_INFORMATION);
  507. RtlZeroMemory(Buffer, sizeof(FILE_EA_INFORMATION));
  508. //
  509. // And return to our caller
  510. //
  511. return STATUS_SUCCESS;
  512. }
  513. //
  514. // Internal support routine
  515. //
  516. NTSTATUS
  517. NpQueryNameInfo (
  518. IN PCCB Ccb,
  519. IN PFILE_NAME_INFORMATION Buffer,
  520. IN OUT PULONG Length
  521. )
  522. /*++
  523. Routine Description:
  524. This routine performs the query name information operation.
  525. Arguments:
  526. Ccb - Supplies the Ccb of the named pipe being queried
  527. Buffer - Supplies a pointer to the buffer where the information is
  528. to be returned
  529. Length - Supplies the length of the buffer in bytes. This variable
  530. upon return will receive the remaining bytes free in the buffer.
  531. Return Value:
  532. NTSTATUS - The result of this query
  533. --*/
  534. {
  535. ULONG bytesToCopy;
  536. ULONG fileNameSize;
  537. PFCB Fcb;
  538. NTSTATUS status;
  539. PAGED_CODE();
  540. DebugTrace(0, Dbg, "NpQueryNameInfo...\n", 0);
  541. //
  542. // See if the buffer is large enough, and decide how many bytes to copy.
  543. //
  544. *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName[0] );
  545. if (Ccb->NodeTypeCode == NPFS_NTC_ROOT_DCB_CCB) {
  546. Fcb = NpVcb->RootDcb;
  547. } else {
  548. Fcb = Ccb->Fcb;
  549. }
  550. fileNameSize = Fcb->FullFileName.Length;
  551. if ( *Length >= fileNameSize ) {
  552. status = STATUS_SUCCESS;
  553. bytesToCopy = fileNameSize;
  554. } else {
  555. status = STATUS_BUFFER_OVERFLOW;
  556. bytesToCopy = *Length;
  557. }
  558. //
  559. // Copy over the file name and its length.
  560. //
  561. RtlCopyMemory(
  562. Buffer->FileName,
  563. Fcb->FullFileName.Buffer,
  564. bytesToCopy);
  565. Buffer->FileNameLength = bytesToCopy;
  566. *Length -= bytesToCopy;
  567. return status;
  568. }
  569. //
  570. // Internal support routine
  571. //
  572. NTSTATUS
  573. NpQueryPositionInfo (
  574. IN PCCB Ccb,
  575. IN PFILE_POSITION_INFORMATION Buffer,
  576. IN OUT PULONG Length,
  577. IN NAMED_PIPE_END NamedPipeEnd
  578. )
  579. /*++
  580. Routine Description:
  581. This routine performs the query position information operation.
  582. Arguments:
  583. Ccb - Supplies the Ccb of the named pipe being queried
  584. Buffer - Supplies a pointer to the buffer where the information is
  585. to be returned
  586. Length - Supplies the length of the buffer in bytes. This variable
  587. upon return will receive the remaining bytes free in the buffer.
  588. NamedPipeEnd - Indicates if the server or client is calling
  589. Return Value:
  590. NTSTATUS - The result of this query
  591. --*/
  592. {
  593. PDATA_QUEUE Queue;
  594. PAGED_CODE();
  595. DebugTrace(0, Dbg, "PbQueryPositionInfo...\n", 0);
  596. //
  597. // Update the length field, and zero out the buffer
  598. //
  599. *Length -= sizeof(FILE_POSITION_INFORMATION);
  600. RtlZeroMemory(Buffer, sizeof(FILE_POSITION_INFORMATION));
  601. //
  602. // The current byte offset is the number of bytes available in the
  603. // read end of the caller's buffer. The client read from the outbound
  604. // end and the server reads from the inbound end.
  605. //
  606. if (NamedPipeEnd == FILE_PIPE_CLIENT_END) {
  607. Queue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
  608. } else {
  609. Queue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
  610. }
  611. if (NpIsDataQueueWriters( Queue )) {
  612. Buffer->CurrentByteOffset.QuadPart = Queue->BytesInQueue - Queue->NextByteOffset;
  613. }
  614. //
  615. // And return to our caller
  616. //
  617. return STATUS_SUCCESS;
  618. }
  619. //
  620. // Internal support routine
  621. //
  622. NTSTATUS
  623. NpQueryPipeInfo (
  624. IN PFCB Fcb,
  625. IN PCCB Ccb,
  626. IN PFILE_PIPE_INFORMATION Buffer,
  627. IN OUT PULONG Length,
  628. IN NAMED_PIPE_END NamedPipeEnd
  629. )
  630. /*++
  631. Routine Description:
  632. This routine performs the query pipe information operation.
  633. Arguments:
  634. Fcb - Supplies the Fcb of the named pipe being queried
  635. Ccb - Supplies the Ccb of the named pipe being queried
  636. Buffer - Supplies a pointer to the buffer where the information is
  637. to be returned
  638. Length - Supplies the length of the buffer in bytes. This variable
  639. upon return will receive the remaining bytes free in the buffer.
  640. NamedPipeEnd - Indicates if the server or client is calling
  641. Return Value:
  642. NTSTATUS - The result of this query
  643. --*/
  644. {
  645. UNREFERENCED_PARAMETER( Fcb );
  646. UNREFERENCED_PARAMETER( Ccb );
  647. PAGED_CODE();
  648. DebugTrace(0, Dbg, "PbQueryPipeInfo...\n", 0);
  649. //
  650. // Update the length field, and zero out the buffer
  651. //
  652. *Length -= sizeof(FILE_PIPE_INFORMATION);
  653. RtlZeroMemory(Buffer, sizeof(FILE_PIPE_INFORMATION));
  654. //
  655. // Set the fields in the record
  656. //
  657. Buffer->ReadMode = Ccb->ReadCompletionMode[ NamedPipeEnd ].ReadMode;
  658. Buffer->CompletionMode = Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode;
  659. //
  660. // And return to our caller
  661. //
  662. return STATUS_SUCCESS;
  663. }
  664. //
  665. // Internal support routine
  666. //
  667. NTSTATUS
  668. NpQueryPipeLocalInfo (
  669. IN PFCB Fcb,
  670. IN PCCB Ccb,
  671. IN PFILE_PIPE_LOCAL_INFORMATION Buffer,
  672. IN OUT PULONG Length,
  673. IN NAMED_PIPE_END NamedPipeEnd
  674. )
  675. /*++
  676. Routine Description:
  677. This routine performs the query pipe information operation.
  678. Arguments:
  679. Fcb - Supplies the Fcb of the named pipe being queried
  680. Ccb - Supplies the Ccb of the named pipe being queried
  681. Buffer - Supplies a pointer to the buffer where the information is
  682. to be returned
  683. Length - Supplies the length of the buffer in bytes. This variable
  684. upon return will receive the remaining bytes free in the buffer.
  685. NamedPipeEnd - Indicates if the server or client is calling
  686. Return Value:
  687. NTSTATUS - The result of this query
  688. --*/
  689. {
  690. PDATA_QUEUE Inbound;
  691. PDATA_QUEUE Outbound;
  692. UNREFERENCED_PARAMETER( Ccb );
  693. PAGED_CODE();
  694. DebugTrace(0, Dbg, "PbQueryPipeLocalInfo...\n", 0);
  695. //
  696. // Update the length field, and zero out the buffer
  697. //
  698. *Length -= sizeof(FILE_PIPE_LOCAL_INFORMATION);
  699. RtlZeroMemory(Buffer, sizeof(FILE_PIPE_LOCAL_INFORMATION));
  700. Inbound = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
  701. Outbound = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
  702. //
  703. // Set the fields in the record
  704. //
  705. Buffer->NamedPipeType = Fcb->Specific.Fcb.NamedPipeType;
  706. Buffer->NamedPipeConfiguration = Fcb->Specific.Fcb.NamedPipeConfiguration;
  707. Buffer->MaximumInstances = Fcb->Specific.Fcb.MaximumInstances;
  708. Buffer->CurrentInstances = Fcb->OpenCount;
  709. Buffer->InboundQuota = Inbound->Quota;
  710. Buffer->OutboundQuota = Outbound->Quota;
  711. Buffer->NamedPipeState = Ccb->NamedPipeState;
  712. Buffer->NamedPipeEnd = NamedPipeEnd;
  713. //
  714. // The read data available and write quota available depend on which
  715. // end of the pipe is doing the query. The client reads from the outbound
  716. // queue, and writes to the inbound queue.
  717. //
  718. if (NamedPipeEnd == FILE_PIPE_CLIENT_END) {
  719. if (NpIsDataQueueWriters( Outbound )) {
  720. Buffer->ReadDataAvailable = Outbound->BytesInQueue - Outbound->NextByteOffset;
  721. }
  722. Buffer->WriteQuotaAvailable = Inbound->Quota - Inbound->QuotaUsed;
  723. } else {
  724. if (NpIsDataQueueWriters( Inbound )) {
  725. Buffer->ReadDataAvailable = Inbound->BytesInQueue - Inbound->NextByteOffset;
  726. }
  727. Buffer->WriteQuotaAvailable = Outbound->Quota - Outbound->QuotaUsed;
  728. }
  729. //
  730. // And return to our caller
  731. //
  732. return STATUS_SUCCESS;
  733. }
  734. //
  735. // Internal support routine
  736. //
  737. NTSTATUS
  738. NpSetBasicInfo (
  739. IN PCCB Ccb,
  740. IN PFILE_BASIC_INFORMATION Buffer
  741. )
  742. /*++
  743. Routine Description:
  744. This routine sets the basic information for a named pipe.
  745. Arguments:
  746. Ccb - Supplies the ccb for the named pipe being modified
  747. Buffer - Supplies the buffer containing the data being set
  748. Return Value:
  749. NTSTATUS - Returns our completion status
  750. --*/
  751. {
  752. UNREFERENCED_PARAMETER( Ccb );
  753. PAGED_CODE();
  754. DebugTrace(0, Dbg, "NpSetBasicInfo...\n", 0);
  755. if (((PLARGE_INTEGER)&Buffer->CreationTime)->QuadPart != 0) {
  756. //
  757. // Modify the creation time
  758. //
  759. //**** need to add time fields
  760. }
  761. if (((PLARGE_INTEGER)&Buffer->LastAccessTime)->QuadPart != 0) {
  762. //
  763. // Modify the last access time
  764. //
  765. //**** need to add time fields
  766. }
  767. if (((PLARGE_INTEGER)&Buffer->LastWriteTime)->QuadPart != 0) {
  768. //
  769. // Modify the last write time
  770. //
  771. //**** need to add time fields
  772. }
  773. if (((PLARGE_INTEGER)&Buffer->ChangeTime)->QuadPart != 0) {
  774. //
  775. // Modify the change time
  776. //
  777. //**** need to add time fields
  778. }
  779. //
  780. // And return to our caller
  781. //
  782. return STATUS_SUCCESS;
  783. }
  784. //
  785. // Internal support routine
  786. //
  787. NTSTATUS
  788. NpSetPipeInfo (
  789. IN PFCB Fcb,
  790. IN PCCB Ccb,
  791. IN PFILE_PIPE_INFORMATION Buffer,
  792. IN NAMED_PIPE_END NamedPipeEnd,
  793. IN PLIST_ENTRY DeferredList
  794. )
  795. /*++
  796. Routine Description:
  797. This routine sets the pipe information for a named pipe.
  798. Arguments:
  799. Fcb - Supplies the Fcb for the named pipe being modified
  800. Ccb - Supplies the ccb for the named pipe being modified
  801. Buffer - Supplies the buffer containing the data being set
  802. NamedPipeEnd - Supplies the server/client end doing the operation
  803. DeferredList - List of IRPs to complete once we release locks
  804. Return Value:
  805. NTSTATUS - Returns our completion status
  806. --*/
  807. {
  808. PDATA_QUEUE ReadQueue;
  809. PDATA_QUEUE WriteQueue;
  810. UNREFERENCED_PARAMETER( Ccb );
  811. PAGED_CODE();
  812. DebugTrace(0, Dbg, "NpSetPipeInfo...\n", 0);
  813. //
  814. // If the caller requests message mode reads but the pipe is
  815. // byte stream then its an invalid parameter
  816. //
  817. if ((Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE) &&
  818. (Fcb->Specific.Fcb.NamedPipeType == FILE_PIPE_BYTE_STREAM_MODE)) {
  819. return STATUS_INVALID_PARAMETER;
  820. }
  821. //
  822. // Get a reference to our read queue
  823. //
  824. switch (NamedPipeEnd) {
  825. case FILE_PIPE_SERVER_END:
  826. ReadQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
  827. WriteQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
  828. break;
  829. case FILE_PIPE_CLIENT_END:
  830. ReadQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ];
  831. WriteQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ];
  832. break;
  833. default:
  834. NpBugCheck( NamedPipeEnd, 0, 0 );
  835. }
  836. //
  837. // If the completion mode is complete operations and the current mode
  838. // is queue operations and there and the data queues are not empty
  839. // then its pipe busy
  840. //
  841. if ((Buffer->CompletionMode == FILE_PIPE_COMPLETE_OPERATION)
  842. &&
  843. (Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode == FILE_PIPE_QUEUE_OPERATION)
  844. &&
  845. ((NpIsDataQueueReaders(ReadQueue)) ||
  846. (NpIsDataQueueWriters(WriteQueue)))) {
  847. return STATUS_PIPE_BUSY;
  848. }
  849. //
  850. // Everything is fine so update the pipe
  851. //
  852. Ccb->ReadCompletionMode[ NamedPipeEnd ].ReadMode = (UCHAR) Buffer->ReadMode;
  853. Ccb->ReadCompletionMode[ NamedPipeEnd ].CompletionMode = (UCHAR) Buffer->CompletionMode;
  854. //
  855. // Check for notify
  856. //
  857. NpCheckForNotify( Fcb->ParentDcb, FALSE, DeferredList );
  858. //
  859. // And return to our caller
  860. //
  861. return STATUS_SUCCESS;
  862. }