Windows NT 4.0 source code leak
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.

4442 lines
129 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. fileinfo.c
  5. Abstract:
  6. This module implements the NtQueryInformationFile and NtSetInformationFile
  7. NT API functionality.
  8. Author:
  9. Larry Osterman (LarryO) 22-Aug-1990
  10. Revision History:
  11. 22-Aug-1990 LarryO
  12. Created
  13. --*/
  14. #define INCLUDE_SMB_TRANSACTION
  15. #define INCLUDE_SMB_QUERY_SET
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. DBGSTATIC
  19. BOOLEAN
  20. QueryBasicInfo(
  21. IN PIRP Irp,
  22. PICB Icb,
  23. PFILE_BASIC_INFORMATION UsersBuffer,
  24. PULONG BufferSize,
  25. PNTSTATUS FinalStatus,
  26. BOOLEAN Wait
  27. );
  28. DBGSTATIC
  29. BOOLEAN
  30. QueryStandardInfo(
  31. IN PIRP Irp,
  32. PICB Icb,
  33. PFILE_STANDARD_INFORMATION UsersBuffer,
  34. PULONG BufferSize,
  35. PNTSTATUS FinalStatus,
  36. BOOLEAN Wait
  37. );
  38. DBGSTATIC
  39. BOOLEAN
  40. QueryInternalInfo(
  41. PICB Icb,
  42. PFILE_INTERNAL_INFORMATION UsersBuffer,
  43. PULONG BufferSize,
  44. PNTSTATUS FinalStatus,
  45. BOOLEAN Wait
  46. );
  47. DBGSTATIC
  48. BOOLEAN
  49. QueryEaInfo(
  50. PIRP Irp,
  51. PICB Icb,
  52. PFILE_EA_INFORMATION UsersBuffer,
  53. PULONG BufferSize,
  54. PNTSTATUS FinalStatus,
  55. BOOLEAN Wait
  56. );
  57. DBGSTATIC
  58. BOOLEAN
  59. QueryNameInfo(
  60. PIRP Irp,
  61. PICB Icb,
  62. PFILE_NAME_INFORMATION UsersBuffer,
  63. PULONG BufferSize,
  64. PNTSTATUS FinalStatus,
  65. BOOLEAN Wait
  66. );
  67. DBGSTATIC
  68. BOOLEAN
  69. QueryAlternateNameInfo(
  70. PIRP Irp,
  71. PICB Icb,
  72. PFILE_NAME_INFORMATION UsersBuffer,
  73. PULONG BufferSize,
  74. PNTSTATUS FinalStatus,
  75. BOOLEAN Wait
  76. );
  77. DBGSTATIC
  78. BOOLEAN
  79. QueryPositionInfo(
  80. PICB Icb,
  81. PIO_STACK_LOCATION IrpSp,
  82. PFILE_POSITION_INFORMATION UsersBuffer,
  83. PULONG BufferSize,
  84. PNTSTATUS FinalStatus,
  85. BOOLEAN Wait
  86. );
  87. DBGSTATIC
  88. BOOLEAN
  89. QueryStreamInfo(
  90. PIRP Irp,
  91. PICB Icb,
  92. PFILE_STREAM_INFORMATION UsersBuffer,
  93. PULONG BufferSize,
  94. PNTSTATUS FinalStatus,
  95. BOOLEAN Wait
  96. );
  97. DBGSTATIC
  98. BOOLEAN
  99. QueryCompressionInfo(
  100. PIRP Irp,
  101. PICB Icb,
  102. PFILE_COMPRESSION_INFORMATION UsersBuffer,
  103. PULONG BufferSize,
  104. PNTSTATUS FinalStatus,
  105. BOOLEAN Wait
  106. );
  107. DBGSTATIC
  108. BOOLEAN
  109. QueryOleAllMiscInfo(
  110. PIRP Irp,
  111. PICB Icb,
  112. PFILE_OLE_ALL_INFORMATION UsersBuffer,
  113. PULONG BufferSize,
  114. PNTSTATUS FinalStatus,
  115. BOOLEAN Wait
  116. );
  117. DBGSTATIC
  118. BOOLEAN
  119. QueryOleInfo(
  120. PIRP Irp,
  121. PICB Icb,
  122. PFILE_OLE_INFORMATION UsersBuffer,
  123. PULONG BufferSize,
  124. PNTSTATUS FinalStatus,
  125. BOOLEAN Wait
  126. );
  127. DBGSTATIC
  128. BOOLEAN
  129. SetBasicInfo(
  130. IN PIRP Irp,
  131. PICB Icb,
  132. PFILE_BASIC_INFORMATION UsersBuffer,
  133. ULONG BufferSize,
  134. PNTSTATUS FinalStatus,
  135. BOOLEAN Wait
  136. );
  137. DBGSTATIC
  138. BOOLEAN
  139. SetDispositionInfo(
  140. IN PICB Icb,
  141. OUT PFILE_DISPOSITION_INFORMATION UsersBuffer,
  142. IN ULONG BufferSize,
  143. IN PIRP Irp,
  144. OUT PNTSTATUS FinalStatus,
  145. IN BOOLEAN Wait
  146. );
  147. DBGSTATIC
  148. BOOLEAN
  149. SetRenameInfo(
  150. IN PIRP Irp OPTIONAL,
  151. PICB Icb,
  152. PFILE_RENAME_INFORMATION UsersBuffer,
  153. ULONG BufferSize,
  154. PNTSTATUS FinalStatus,
  155. BOOLEAN Wait,
  156. USHORT NtInformationLevel
  157. );
  158. DBGSTATIC
  159. BOOLEAN
  160. SetPositionInfo(
  161. PICB Icb,
  162. PIO_STACK_LOCATION IrpSp,
  163. PFILE_POSITION_INFORMATION UsersBuffer,
  164. ULONG BufferSize,
  165. PNTSTATUS FinalStatus,
  166. BOOLEAN Wait
  167. );
  168. DBGSTATIC
  169. BOOLEAN
  170. SetAllocationInfo(
  171. PIRP Irp,
  172. PICB Icb,
  173. PFILE_ALLOCATION_INFORMATION UsersBuffer,
  174. ULONG BufferSize,
  175. PNTSTATUS FinalStatus,
  176. BOOLEAN Wait
  177. );
  178. DBGSTATIC
  179. BOOLEAN
  180. SetEndOfFileInfo(
  181. IN PIRP Irp,
  182. PICB Icb,
  183. PFILE_END_OF_FILE_INFORMATION UsersBuffer,
  184. ULONG BufferSize,
  185. PNTSTATUS FinalStatus,
  186. BOOLEAN Wait
  187. );
  188. DBGSTATIC
  189. BOOLEAN
  190. SetGenericInfo(
  191. IN PIRP Irp,
  192. PICB Icb,
  193. VOID *pvUsersBuffer,
  194. ULONG cbBuffer,
  195. ULONG cbMin,
  196. USHORT NtInformationLevel,
  197. PNTSTATUS FinalStatus,
  198. BOOLEAN Wait
  199. );
  200. #ifdef ALLOC_PRAGMA
  201. #pragma alloc_text(PAGE, RdrFsdQueryInformationFile)
  202. #pragma alloc_text(PAGE, RdrFspQueryInformationFile)
  203. #pragma alloc_text(PAGE, RdrFscQueryInformationFile)
  204. #pragma alloc_text(PAGE, RdrFsdSetInformationFile)
  205. #pragma alloc_text(PAGE, RdrFspSetInformationFile)
  206. #pragma alloc_text(PAGE, RdrFscSetInformationFile)
  207. #pragma alloc_text(PAGE, RdrFastQueryBasicInfo)
  208. #pragma alloc_text(PAGE, RdrFastQueryStdInfo)
  209. #pragma alloc_text(PAGE, RdrQueryNtFileInformation)
  210. #pragma alloc_text(PAGE, RdrQueryNtPathInformation)
  211. #pragma alloc_text(PAGE, QueryBasicInfo)
  212. #pragma alloc_text(PAGE, QueryStandardInfo)
  213. #pragma alloc_text(PAGE, QueryInternalInfo)
  214. #pragma alloc_text(PAGE, QueryEaInfo)
  215. #pragma alloc_text(PAGE, QueryNameInfo)
  216. #pragma alloc_text(PAGE, QueryAlternateNameInfo)
  217. #pragma alloc_text(PAGE, QueryPositionInfo)
  218. #pragma alloc_text(PAGE, QueryStreamInfo)
  219. #pragma alloc_text(PAGE, QueryCompressionInfo)
  220. #pragma alloc_text(PAGE, QueryOleAllMiscInfo)
  221. #pragma alloc_text(PAGE, QueryOleInfo)
  222. #pragma alloc_text(PAGE, SetBasicInfo)
  223. #pragma alloc_text(PAGE, SetRenameInfo)
  224. #pragma alloc_text(PAGE, SetDispositionInfo)
  225. #pragma alloc_text(PAGE, SetPositionInfo)
  226. #pragma alloc_text(PAGE, SetAllocationInfo)
  227. #pragma alloc_text(PAGE, SetEndOfFileInfo)
  228. #pragma alloc_text(PAGE, SetGenericInfo)
  229. #endif
  230. NTSTATUS
  231. RdrFsdQueryInformationFile (
  232. IN PFS_DEVICE_OBJECT DeviceObject,
  233. IN PIRP Irp
  234. )
  235. /*++
  236. Routine Description:
  237. This routine implements the FSD version of the NtQueryInformationFile API.
  238. Arguments:
  239. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  240. request
  241. IN PIRP Irp - Supplies the IRP that describes the request
  242. Return Value:
  243. NTSTATUS - Status of operation
  244. --*/
  245. {
  246. NTSTATUS Status;
  247. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  248. PFCB Fcb = FCB_OF(IrpSp);
  249. PAGED_CODE();
  250. if (DeviceObject == (PFS_DEVICE_OBJECT)BowserDeviceObject) {
  251. return BowserFsdQueryInformationFile(BowserDeviceObject, Irp);
  252. }
  253. FsRtlEnterFileSystem();
  254. // dprintf(DPRT_DISPATCH, ("RdrFsdQueryInformationFile: Class: %ld Irp:%08lx\n", IrpSp->Parameters.QueryFile.FileInformationClass, Irp));
  255. Status = RdrFscQueryInformationFile(CanFsdWait(Irp), DeviceObject, Irp);
  256. FsRtlExitFileSystem();
  257. return Status;
  258. }
  259. NTSTATUS
  260. RdrFspQueryInformationFile (
  261. IN PFS_DEVICE_OBJECT DeviceObject,
  262. IN PIRP Irp
  263. )
  264. /*++
  265. Routine Description:
  266. This routine implements the FSP version of the NtFsControlFile API.
  267. Arguments:
  268. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  269. request
  270. IN PIRP Irp - Supplies the IRP that describes the request
  271. Return Value:
  272. NTSTATUS - Status of operation
  273. --*/
  274. {
  275. PAGED_CODE();
  276. // dprintf(DPRT_FILEINFO, ("RdrFsdFsControlFile: Device: %08lx Irp:%08lx\n", DeviceObject, Irp));
  277. return RdrFscQueryInformationFile(TRUE, DeviceObject, Irp);
  278. }
  279. NTSTATUS
  280. RdrFscQueryInformationFile (
  281. IN BOOLEAN Wait,
  282. IN PFS_DEVICE_OBJECT DeviceObject,
  283. IN PIRP Irp
  284. )
  285. /*++
  286. Routine Description:
  287. This routine implements the FSD version of the NtFsControlFile API
  288. .
  289. Arguments:
  290. IN BOOLEAN Wait - True if routine can block waiting for the request
  291. to complete.
  292. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  293. request
  294. IN PIRP Irp - Supplies the IRP that describes the request
  295. Return Value:
  296. NTSTATUS - Status of operation
  297. Note:
  298. This code assumes that this is a buffered I/O operation. If it is ever
  299. implemented as a non buffered operation, then we have to put code to map
  300. in the users buffer here.
  301. --*/
  302. {
  303. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  304. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  305. PVOID UsersBuffer = Irp->AssociatedIrp.SystemBuffer;
  306. ULONG BufferSize = IrpSp->Parameters.QueryFile.Length;
  307. PICB Icb = ICB_OF(IrpSp);
  308. BOOLEAN QueueToFsp = FALSE;
  309. PAGED_CODE();
  310. ASSERT (Icb->Signature == STRUCTURE_SIGNATURE_ICB);
  311. // dprintf(DPRT_FILEINFO, ("NtQueryInformationFile File Class %ld Buffer %lx, Length %lx\n", IrpSp->Parameters.QueryFile.FileInformationClass, UsersBuffer, BufferSize));
  312. RdrAcquireFcbLock(Icb->Fcb, SharedLock, TRUE);
  313. //
  314. // If the file has a delete operation pending on it, or does not have
  315. // a remote instantiation, blow the request away.
  316. //
  317. Status = RdrIsOperationValid(ICB_OF(IrpSp), IRP_MJ_QUERY_INFORMATION, IrpSp->FileObject);
  318. RdrReleaseFcbLock(Icb->Fcb);
  319. if (!NT_SUCCESS(Status)) {
  320. RdrCompleteRequest(Irp, Status);
  321. return Status;
  322. }
  323. switch (IrpSp->Parameters.QueryFile.FileInformationClass) {
  324. case FileBasicInformation:
  325. QueueToFsp = QueryBasicInfo(Irp, Icb,
  326. UsersBuffer,
  327. &BufferSize,
  328. &Status,
  329. Wait);
  330. break;
  331. case FileStandardInformation:
  332. QueueToFsp = QueryStandardInfo(Irp, Icb,
  333. UsersBuffer,
  334. &BufferSize,
  335. &Status,
  336. Wait);
  337. break;
  338. case FileInternalInformation:
  339. QueueToFsp = QueryInternalInfo(Icb,
  340. UsersBuffer,
  341. &BufferSize,
  342. &Status,
  343. Wait);
  344. break;
  345. case FileEaInformation:
  346. QueueToFsp = QueryEaInfo(Irp,
  347. Icb,
  348. UsersBuffer,
  349. &BufferSize,
  350. &Status,
  351. Wait);
  352. break;
  353. case FileNameInformation:
  354. QueueToFsp = QueryNameInfo(Irp, Icb,
  355. UsersBuffer,
  356. &BufferSize,
  357. &Status,
  358. Wait);
  359. break;
  360. case FileAlternateNameInformation:
  361. QueueToFsp = QueryAlternateNameInfo(Irp, Icb,
  362. UsersBuffer,
  363. &BufferSize,
  364. &Status,
  365. Wait);
  366. break;
  367. case FilePositionInformation:
  368. QueueToFsp = QueryPositionInfo(Icb,
  369. IrpSp,
  370. UsersBuffer,
  371. &BufferSize,
  372. &Status,
  373. Wait);
  374. break;
  375. case FileOleAllInformation:
  376. case FileAllInformation:
  377. {
  378. PFILE_ALL_INFORMATION AllInfo = UsersBuffer;
  379. //
  380. // We can assume that we will have to go to the net for this
  381. // guy, queue it to the FSP.
  382. //
  383. if (!Wait) {
  384. QueueToFsp = TRUE;
  385. break;
  386. }
  387. BufferSize -= (sizeof(FILE_ALIGNMENT_INFORMATION) +
  388. sizeof(FILE_ACCESS_INFORMATION) +
  389. sizeof(FILE_MODE_INFORMATION) ) ;
  390. QueryBasicInfo(Irp, Icb, &AllInfo->BasicInformation,
  391. &BufferSize,
  392. &Status,
  393. Wait);
  394. if (!NT_SUCCESS(Status)) {
  395. break;
  396. }
  397. QueryStandardInfo(Irp, Icb, &AllInfo->StandardInformation,
  398. &BufferSize,
  399. &Status,
  400. Wait);
  401. if (!NT_SUCCESS(Status)) {
  402. break;
  403. }
  404. QueryInternalInfo(Icb, &AllInfo->InternalInformation,
  405. &BufferSize,
  406. &Status,
  407. Wait);
  408. if (!NT_SUCCESS(Status)) {
  409. break;
  410. }
  411. QueryEaInfo(Irp, Icb, &AllInfo->EaInformation,
  412. &BufferSize,
  413. &Status,
  414. Wait);
  415. if (!NT_SUCCESS(Status)) {
  416. if (Status != STATUS_EAS_NOT_SUPPORTED) {
  417. break;
  418. }
  419. }
  420. QueryPositionInfo(Icb, IrpSp, &AllInfo->PositionInformation,
  421. &BufferSize,
  422. &Status,
  423. Wait);
  424. if (!NT_SUCCESS(Status)) {
  425. break;
  426. }
  427. if (IrpSp->Parameters.QueryFile.FileInformationClass ==
  428. FileOleAllInformation) {
  429. PFILE_OLE_ALL_INFORMATION OleAllInfo = UsersBuffer;
  430. QueryOleAllMiscInfo(
  431. Irp,
  432. Icb,
  433. OleAllInfo,
  434. &BufferSize,
  435. &Status,
  436. Wait);
  437. } else {
  438. QueryNameInfo(Irp, Icb, &AllInfo->NameInformation,
  439. &BufferSize,
  440. &Status,
  441. Wait);
  442. }
  443. }
  444. break;
  445. case FilePipeInformation:
  446. QueueToFsp = RdrQueryNpInfo( Icb,
  447. UsersBuffer,
  448. &BufferSize,
  449. &Status);
  450. break;
  451. case FilePipeLocalInformation:
  452. QueueToFsp = RdrQueryNpLocalInfo( Irp,
  453. Icb,
  454. UsersBuffer,
  455. &BufferSize,
  456. &Status,
  457. Wait);
  458. break;
  459. case FilePipeRemoteInformation:
  460. QueueToFsp = RdrQueryNpRemoteInfo( Icb,
  461. UsersBuffer,
  462. &BufferSize,
  463. &Status);
  464. break;
  465. case FileStreamInformation:
  466. QueueToFsp = QueryStreamInfo(Irp, Icb,
  467. UsersBuffer,
  468. &BufferSize,
  469. &Status,
  470. Wait);
  471. break;
  472. case FileCompressionInformation:
  473. QueueToFsp = QueryCompressionInfo(Irp, Icb,
  474. UsersBuffer,
  475. &BufferSize,
  476. &Status,
  477. Wait);
  478. break;
  479. case FileOleInformation:
  480. QueueToFsp = QueryOleInfo(Irp, Icb,
  481. UsersBuffer,
  482. &BufferSize,
  483. &Status,
  484. Wait);
  485. break;
  486. #if RDRDBG
  487. //
  488. // Special case information fields handled in the I/O subsystem
  489. //
  490. case FileAlignmentInformation:
  491. InternalError(("FileAlignmentInformation handled in I/O subsystem"));
  492. break;
  493. case FileAccessInformation:
  494. InternalError(("FileAccessInformation handled in I/O subsystem"));
  495. break;
  496. case FileModeInformation:
  497. InternalError(("FileModeInformation handled in I/O subsystem"));
  498. break;
  499. //
  500. // Special case information fields that can never be passed on Qinfo.
  501. //
  502. case FileFullDirectoryInformation:
  503. InternalError(("FileFullDirectory illegal for NtQueryInformationFile"));
  504. break;
  505. case FileBothDirectoryInformation:
  506. InternalError(("FileBothDirectory illegal for NtQueryInformationFile"));
  507. break;
  508. case FileRenameInformation:
  509. InternalError(("FileRename illegal for NtQueryInformationFile"));
  510. break;
  511. case FileMailslotQueryInformation:
  512. InternalError(("FileMailslotQuery illegal for NtQueryInformationFile"));
  513. break;
  514. case FileMailslotSetInformation:
  515. InternalError(("FileMailslotSet illegal for NtQueryInformationFile"));
  516. break;
  517. case FileCompletionInformation:
  518. InternalError(("FileCompletion illegal for NtQueryInformationFile"));
  519. break;
  520. case FileLinkInformation:
  521. InternalError(("FileLink illegal for NtQueryInformationFile"));
  522. break;
  523. case FileFullEaInformation:
  524. InternalError(("FileFullEa illegal for NtQueryInformationFile"));
  525. break;
  526. case FileDirectoryInformation:
  527. InternalError(("FileDirectory illegal for NtQueryInformationFile"));
  528. break;
  529. case FileNamesInformation:
  530. InternalError(("FileNames illegal for NtQueryInformationFile"));
  531. break;
  532. case FileDispositionInformation:
  533. InternalError(("FileDisposition illegal for NtQueryInformationFile"));
  534. break;
  535. case FileAllocationInformation:
  536. InternalError(("FileAllocation illegal for NtQueryInformationFile"));
  537. break;
  538. case FileEndOfFileInformation:
  539. InternalError(("FileEndOfFile illegal for NtQueryInformationFile"));
  540. break;
  541. case FileCopyOnWriteInformation:
  542. InternalError(("FileCopyOnWrite illegal for NtQueryInformationFile"));
  543. break;
  544. case FileMoveClusterInformation:
  545. InternalError(("FileMoveCluster illegal for NtQueryInformationFile"));
  546. break;
  547. case FileOleClassIdInformation:
  548. InternalError(("FileOleClassId illegal for NtQueryInformationFile"));
  549. break;
  550. case FileOleStateBitsInformation:
  551. InternalError(("FileOleStateBits illegal for NtQueryInformationFile"));
  552. break;
  553. case FileObjectIdInformation:
  554. InternalError(("FileObjectId illegal for NtQueryInformationFile"));
  555. break;
  556. case FileOleDirectoryInformation:
  557. InternalError(("FileOleDirectory illegal for NtQueryInformationFile"));
  558. break;
  559. #endif // RDRDBG
  560. default:
  561. Status = STATUS_NOT_IMPLEMENTED;
  562. };
  563. if (QueueToFsp) {
  564. RdrFsdPostToFsp(DeviceObject, Irp);
  565. return STATUS_PENDING;
  566. }
  567. if (!NT_ERROR(Status)) {
  568. Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length -
  569. BufferSize;
  570. }
  571. // dprintf(DPRT_FILEINFO, ("Returning status: %X\n", Status));
  572. //
  573. // Complete the I/O request with the specified status.
  574. //
  575. RdrCompleteRequest(Irp, Status);
  576. return Status;
  577. }
  578. NTSTATUS
  579. RdrFsdSetInformationFile (
  580. IN PFS_DEVICE_OBJECT DeviceObject,
  581. IN PIRP Irp
  582. )
  583. /*++
  584. Routine Description:
  585. This routine implements the FSD version of the NtSetInformationFile API.
  586. Arguments:
  587. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  588. request
  589. IN PIRP Irp - Supplies the IRP that describes the request
  590. Return Value:
  591. NTSTATUS - Status of operation
  592. --*/
  593. {
  594. NTSTATUS Status = STATUS_SUCCESS;
  595. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  596. PFCB Fcb = FCB_OF(IrpSp);
  597. PAGED_CODE();
  598. FsRtlEnterFileSystem();
  599. // dprintf(DPRT_FILEINFO, ("RdrFsdSetInformationFile: Device: %08lx Irp:%08lx\n", DeviceObject, Irp));
  600. //
  601. // Now make sure that the file that we are dealing with is of an
  602. // appropriate type for us to perform this operation.
  603. //
  604. // We can perform these operation on any file that has an instantiation
  605. // on the remote server, so ignore any that have either purely local
  606. // semantics, or on tree connections.
  607. //
  608. if (NT_SUCCESS(Status)) {
  609. Status = RdrFscSetInformationFile(CanFsdWait(Irp), DeviceObject, Irp);
  610. } else {
  611. RdrCompleteRequest(Irp, Status);
  612. }
  613. FsRtlExitFileSystem();
  614. return Status;
  615. }
  616. NTSTATUS
  617. RdrFspSetInformationFile (
  618. IN PFS_DEVICE_OBJECT DeviceObject,
  619. IN PIRP Irp
  620. )
  621. /*++
  622. Routine Description:
  623. This routine implements the FSP version of the NtFsControlFile API.
  624. Arguments:
  625. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  626. request
  627. IN PIRP Irp - Supplies the IRP that describes the request
  628. Return Value:
  629. NTSTATUS - Status of operation
  630. --*/
  631. {
  632. // dprintf(DPRT_FILEINFO, ("RdrFsdSetInformationFile: Device: %08lx Irp:%08lx\n", DeviceObject, Irp));
  633. return RdrFscSetInformationFile(TRUE, DeviceObject, Irp);
  634. }
  635. NTSTATUS
  636. RdrFscSetInformationFile (
  637. IN BOOLEAN Wait,
  638. IN PFS_DEVICE_OBJECT DeviceObject,
  639. IN PIRP Irp
  640. )
  641. /*++
  642. Routine Description:
  643. This routine implements the common version of the NtSetInformationFile API.
  644. Arguments:
  645. IN BOOLEAN Wait - True if routine can block waiting for the request
  646. to complete.
  647. IN PFS_DEVICE_OBJECT DeviceObject, - Supplies the device object for this
  648. request
  649. IN PIRP Irp - Supplies the IRP that describes the request
  650. Return Value:
  651. NTSTATUS - Status of operation
  652. Note:
  653. This code assumes that this is a buffered I/O operation. If it is ever
  654. implemented as a non buffered operation, then we have to put code to map
  655. in the users buffer here.
  656. --*/
  657. {
  658. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  659. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  660. PVOID UsersBuffer = Irp->AssociatedIrp.SystemBuffer;
  661. PICB Icb = ICB_OF(IrpSp);
  662. BOOLEAN QueueToFsp = FALSE;
  663. ULONG cbMin = 0;
  664. USHORT NtInformationLevel;
  665. PAGED_CODE();
  666. ASSERT (Icb->Signature == STRUCTURE_SIGNATURE_ICB);
  667. // dprintf(DPRT_FILEINFO, ("NtSetInformationFile File Class %ld Buffer %lx\n", IrpSp->Parameters.QueryFile.FileInformationClass, UsersBuffer));
  668. //
  669. // If the file has a delete operation pending on it, blow away
  670. // this request for the file.
  671. //
  672. Status = RdrIsOperationValid(ICB_OF(IrpSp), IRP_MJ_SET_INFORMATION, IrpSp->FileObject);
  673. if (!NT_SUCCESS(Status)) {
  674. RdrCompleteRequest(Irp, Status);
  675. return Status;
  676. }
  677. Icb->Fcb->UpdatedFile = TRUE;
  678. InterlockedIncrement( &RdrServerStateUpdated );
  679. switch (Icb->NonPagedFcb->FileType) {
  680. //
  681. // NAMED PIPES======================================================
  682. //
  683. case FileTypeByteModePipe:
  684. case FileTypeMessageModePipe:
  685. switch (IrpSp->Parameters.SetFile.FileInformationClass) {
  686. case FilePipeInformation:
  687. QueueToFsp = RdrSetNpInfo( Irp, Icb,
  688. Irp->AssociatedIrp.SystemBuffer,
  689. IrpSp->Parameters.SetFile.Length,
  690. &Status,
  691. Wait);
  692. break;
  693. case FilePipeRemoteInformation:
  694. QueueToFsp = RdrSetNpRemoteInfo( Icb,
  695. Irp->AssociatedIrp.SystemBuffer,
  696. IrpSp->Parameters.SetFile.Length,
  697. &Status);
  698. break;
  699. default:
  700. Status = STATUS_NOT_IMPLEMENTED;
  701. }
  702. break;
  703. //
  704. // ALL OTHER FILE TYPES=============================================
  705. //
  706. default:
  707. switch (IrpSp->Parameters.SetFile.FileInformationClass) {
  708. case FileBasicInformation:
  709. QueueToFsp = SetBasicInfo(Irp, Icb,
  710. Irp->AssociatedIrp.SystemBuffer,
  711. IrpSp->Parameters.SetFile.Length,
  712. &Status,
  713. Wait);
  714. break;
  715. case FileDispositionInformation:
  716. QueueToFsp = SetDispositionInfo(Icb,
  717. Irp->AssociatedIrp.SystemBuffer,
  718. IrpSp->Parameters.SetFile.Length,
  719. Irp,
  720. &Status,
  721. Wait);
  722. break;
  723. case FileCopyOnWriteInformation:
  724. case FileMoveClusterInformation:
  725. case FileLinkInformation:
  726. case FileRenameInformation:
  727. QueueToFsp = SetRenameInfo(Irp, Icb,
  728. Irp->AssociatedIrp.SystemBuffer,
  729. IrpSp->Parameters.SetFile.Length,
  730. &Status,
  731. Wait,
  732. (USHORT)IrpSp->Parameters.SetFile.FileInformationClass);
  733. break;
  734. case FilePositionInformation:
  735. QueueToFsp = SetPositionInfo(Icb, IrpSp,
  736. Irp->AssociatedIrp.SystemBuffer,
  737. IrpSp->Parameters.SetFile.Length,
  738. &Status,
  739. Wait);
  740. break;
  741. case FileAllocationInformation:
  742. QueueToFsp = SetAllocationInfo(Irp, Icb,
  743. Irp->AssociatedIrp.SystemBuffer,
  744. IrpSp->Parameters.SetFile.Length,
  745. &Status,
  746. Wait);
  747. break;
  748. case FileEndOfFileInformation:
  749. QueueToFsp = SetEndOfFileInfo(Irp, Icb,
  750. Irp->AssociatedIrp.SystemBuffer,
  751. IrpSp->Parameters.SetFile.Length,
  752. &Status,
  753. Wait);
  754. break;
  755. case FileOleClassIdInformation:
  756. cbMin = sizeof(FILE_OLE_CLASSID_INFORMATION);
  757. NtInformationLevel = SMB_SET_FILE_OLE_CLASSID_INFO;
  758. break;
  759. case FileOleStateBitsInformation:
  760. cbMin = sizeof(FILE_OLE_STATE_BITS_INFORMATION);
  761. NtInformationLevel = SMB_SET_FILE_OLE_STATE_BITS_INFO;
  762. break;
  763. case FileObjectIdInformation:
  764. cbMin = sizeof(FILE_OBJECTID_INFORMATION);
  765. NtInformationLevel = SMB_SET_FILE_OBJECTID_INFO;
  766. break;
  767. case FileContentIndexInformation:
  768. cbMin = sizeof(BOOLEAN);
  769. NtInformationLevel = SMB_SET_FILE_CONTENT_INDEX_INFO;
  770. break;
  771. case FileInheritContentIndexInformation:
  772. cbMin = sizeof(BOOLEAN);
  773. NtInformationLevel = SMB_SET_FILE_INHERIT_CONTENT_INDEX_INFO;
  774. break;
  775. case FileOleInformation:
  776. cbMin = sizeof(FILE_OLE_INFORMATION);
  777. NtInformationLevel = SMB_SET_FILE_OLE_INFO;
  778. break;
  779. #if RDRDBG
  780. //
  781. // Special case information fields handled in the I/O subsystem
  782. //
  783. case FileModeInformation:
  784. InternalError(("FileModeInformation handled in I/O subsystem"));
  785. break;
  786. //
  787. // Special case information fields that can never be passed on Qinfo.
  788. //
  789. case FileDirectoryInformation:
  790. InternalError(("FileDirectory illegal for NtSetInformationFile"));
  791. break;
  792. case FileFullDirectoryInformation:
  793. InternalError(("FileFullDirectory illegal for NtSetInformationFile"));
  794. break;
  795. case FileBothDirectoryInformation:
  796. InternalError(("FileBothDirectory illegal for NtSetInformationFile"));
  797. break;
  798. case FileStandardInformation:
  799. InternalError(("FileStandard illegal for NtSetInformationFile"));
  800. break;
  801. case FileInternalInformation:
  802. InternalError(("FileInternal illegal for NtSetInformationFile"));
  803. break;
  804. case FileEaInformation:
  805. InternalError(("FileEa illegal for NtSetInformationFile"));
  806. break;
  807. case FileAccessInformation:
  808. InternalError(("FileAccess illegal for NtSetInformationFile"));
  809. break;
  810. case FileNameInformation:
  811. InternalError(("FileName illegal for NtSetInformationFile"));
  812. break;
  813. case FileNamesInformation:
  814. InternalError(("FileNames illegal for NtSetInformationFile"));
  815. break;
  816. case FileFullEaInformation:
  817. InternalError(("FileFullEa illegal for NtSetInformationFile"));
  818. break;
  819. case FileAlignmentInformation:
  820. InternalError(("FileAlignment illegal for NtSetInformationFile"));
  821. break;
  822. case FileAllInformation:
  823. InternalError(("FileAll illegal for NtSetInformationFile"));
  824. break;
  825. case FileAlternateNameInformation:
  826. InternalError(("FileAlternateName illegal for NtSetInformationFile"));
  827. break;
  828. case FileStreamInformation:
  829. InternalError(("FileStream illegal for NtSetInformationFile"));
  830. break;
  831. case FilePipeInformation:
  832. InternalError(("FilePipe illegal for NtSetInformationFile"));
  833. break;
  834. case FilePipeLocalInformation:
  835. InternalError(("FilePipeLocal illegal for NtSetInformationFile"));
  836. break;
  837. case FilePipeRemoteInformation:
  838. InternalError(("FilePipeRemote illegal for NtSetInformationFile"));
  839. break;
  840. case FileMailslotQueryInformation:
  841. InternalError(("FileMailslotQuery illegal for NtSetInformationFile"));
  842. break;
  843. case FileMailslotSetInformation:
  844. InternalError(("FileMailslotSet illegal for NtSetInformationFile"));
  845. break;
  846. case FileCompressionInformation:
  847. InternalError(("FileCompression illegal for NtSetInformationFile"));
  848. break;
  849. case FileCompletionInformation:
  850. InternalError(("FileCompletion illegal for NtSetInformationFile"));
  851. break;
  852. case FileOleAllInformation:
  853. InternalError(("FileOleAll illegal for NtSetInformationFile"));
  854. break;
  855. case FileOleDirectoryInformation:
  856. InternalError(("FileOleDirectory illegal for NtSetInformationFile"));
  857. break;
  858. #endif // RDRDBG
  859. default:
  860. Status = STATUS_NOT_IMPLEMENTED;
  861. }
  862. if (cbMin != 0) {
  863. QueueToFsp = SetGenericInfo(
  864. Irp,
  865. Icb,
  866. Irp->AssociatedIrp.SystemBuffer,
  867. IrpSp->Parameters.SetFile.Length,
  868. cbMin,
  869. NtInformationLevel,
  870. &Status,
  871. Wait);
  872. }
  873. }
  874. if (QueueToFsp) {
  875. RdrFsdPostToFsp(DeviceObject, Irp);
  876. return STATUS_PENDING;
  877. }
  878. // dprintf(DPRT_FILEINFO, ("Returning status: %X\n", Status));
  879. //
  880. // Complete the I/O request with the specified status.
  881. //
  882. RdrCompleteRequest(Irp, Status);
  883. return Status;
  884. }
  885. BOOLEAN
  886. RdrFastQueryBasicInfo (
  887. IN PFILE_OBJECT FileObject,
  888. IN BOOLEAN Wait,
  889. IN OUT PFILE_BASIC_INFORMATION Buffer,
  890. OUT PIO_STATUS_BLOCK IoStatus,
  891. IN PDEVICE_OBJECT DeviceObject
  892. )
  893. /*++
  894. Routine Description:
  895. This routine is for the fast query call for basic file information.
  896. Arguments:
  897. FileObject - Supplies the file object used in this operation
  898. Wait - Indicates if we are allowed to wait for the information
  899. Buffer - Supplies the output buffer to receive the basic information
  900. IoStatus - Receives the final status of the operation
  901. Return Value:
  902. TRUE - Indicates the the operation succeeded with the specified
  903. IoStatus.
  904. FALSE - Indicates that the caller should take the long route
  905. to do the query call.
  906. --*/
  907. {
  908. BOOLEAN Results = FALSE;
  909. BOOLEAN FcbAcquired = FALSE;
  910. PFCB Fcb = FileObject->FsContext;
  911. PICB Icb = FileObject->FsContext2;
  912. PAGED_CODE();
  913. ASSERT (Icb->Signature == STRUCTURE_SIGNATURE_ICB);
  914. ASSERT (Fcb->Header.NodeTypeCode == STRUCTURE_SIGNATURE_FCB);
  915. FsRtlEnterFileSystem();
  916. if (!RdrAcquireFcbLock(Fcb, SharedLock, Wait)) {
  917. FsRtlExitFileSystem();
  918. return Results;
  919. }
  920. FcbAcquired = TRUE;
  921. try {
  922. QSFILEATTRIB FileAttribs;
  923. if (!Wait) {
  924. if (!RdrCanFileBeBuffered(Icb) || Icb->Type != DiskFile) {
  925. try_return( Results );
  926. }
  927. }
  928. if (RdrCanFileBeBuffered(Icb) && Icb->Type == DiskFile) {
  929. //
  930. // If the file can be buffered, we don't have to hit the net
  931. // to find this information out, we have it cached locally anyway!
  932. //
  933. ASSERT ((Fcb->Attribute & ~FILE_ATTRIBUTE_VALID_FLAGS) == 0);
  934. try {
  935. Buffer->CreationTime = Fcb->CreationTime;
  936. Buffer->LastAccessTime = Fcb->LastAccessTime;
  937. Buffer->LastWriteTime = Fcb->LastWriteTime;
  938. Buffer->ChangeTime = Fcb->ChangeTime;
  939. Buffer->FileAttributes = Fcb->Attribute;
  940. } except (EXCEPTION_EXECUTE_HANDLER) {
  941. IoStatus->Status = GetExceptionCode();
  942. IoStatus->Information = 0;
  943. try_return(Results = FALSE);
  944. }
  945. IoStatus->Status = STATUS_SUCCESS;
  946. IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
  947. try_return(Results = TRUE);
  948. }
  949. //
  950. // We can't determine the file information from the FCB, however we
  951. // CAN tie up the users thread, so we can query it right now.
  952. //
  953. ASSERT (Wait);
  954. //
  955. // Query the file attributes over the net.
  956. //
  957. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  958. FILE_BASIC_INFORMATION LocalBuffer;
  959. IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
  960. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  961. IoStatus->Status = RdrQueryNtFileInformation(
  962. NULL,
  963. Icb,
  964. SMB_QUERY_FILE_BASIC_INFO,
  965. &LocalBuffer,
  966. &IoStatus->Information
  967. );
  968. } else {
  969. IoStatus->Status = RdrQueryNtPathInformation(
  970. NULL,
  971. Icb,
  972. SMB_QUERY_FILE_BASIC_INFO,
  973. &LocalBuffer,
  974. &IoStatus->Information
  975. );
  976. }
  977. IoStatus->Information = sizeof(FILE_BASIC_INFORMATION) - IoStatus->Information;
  978. if (NT_SUCCESS(IoStatus->Status)) {
  979. try {
  980. RtlCopyMemory( Buffer, &LocalBuffer, sizeof(FILE_BASIC_INFORMATION) );
  981. } except (EXCEPTION_EXECUTE_HANDLER) {
  982. IoStatus->Status = GetExceptionCode();
  983. IoStatus->Information = 0;
  984. try_return (Results = FALSE);
  985. }
  986. }
  987. } else {
  988. IoStatus->Status = RdrQueryFileAttributes(NULL, Icb, &FileAttribs);
  989. if (NT_SUCCESS(IoStatus->Status)) {
  990. ASSERT ((FileAttribs.Attributes & ~FILE_ATTRIBUTE_VALID_FLAGS) == 0);
  991. try {
  992. Buffer->CreationTime = FileAttribs.CreationTime;
  993. Buffer->LastAccessTime = FileAttribs.LastAccessTime;
  994. Buffer->LastWriteTime = FileAttribs.LastWriteTime;
  995. Buffer->ChangeTime = FileAttribs.ChangeTime;
  996. Buffer->FileAttributes = FileAttribs.Attributes;
  997. } except (EXCEPTION_EXECUTE_HANDLER) {
  998. IoStatus->Status = GetExceptionCode();
  999. IoStatus->Information = 0;
  1000. try_return (Results = FALSE);
  1001. }
  1002. }
  1003. IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
  1004. }
  1005. try_return(Results = TRUE);
  1006. try_exit: NOTHING;
  1007. } finally {
  1008. if (FcbAcquired) {
  1009. RdrReleaseFcbLock( Fcb );
  1010. }
  1011. FsRtlExitFileSystem();
  1012. }
  1013. //
  1014. // And return to our caller
  1015. //
  1016. return Results;
  1017. }
  1018. BOOLEAN
  1019. RdrFastQueryStdInfo (
  1020. IN PFILE_OBJECT FileObject,
  1021. IN BOOLEAN Wait,
  1022. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  1023. OUT PIO_STATUS_BLOCK IoStatus,
  1024. IN PDEVICE_OBJECT DeviceObject
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This routine is for the fast query call for standard file information.
  1029. Arguments:
  1030. FileObject - Supplies the file object used in this operation
  1031. Wait - Indicates if we are allowed to wait for the information
  1032. Buffer - Supplies the output buffer to receive the basic information
  1033. IoStatus - Receives the final status of the operation
  1034. Return Value:
  1035. TRUE - Indicates the the operation succeeded with the specified
  1036. IoStatus.
  1037. FALSE - Indicates that the caller should take the long route
  1038. to do the query call.
  1039. --*/
  1040. {
  1041. BOOLEAN Results = FALSE;
  1042. BOOLEAN FcbAcquired = FALSE;
  1043. PFCB Fcb = FileObject->FsContext;
  1044. PICB Icb = FileObject->FsContext2;
  1045. PAGED_CODE();
  1046. ASSERT (Icb->Signature == STRUCTURE_SIGNATURE_ICB);
  1047. ASSERT (Fcb->Header.NodeTypeCode == STRUCTURE_SIGNATURE_FCB);
  1048. FsRtlEnterFileSystem();
  1049. if (!RdrAcquireFcbLock(Fcb, SharedLock, Wait)) {
  1050. FsRtlExitFileSystem();
  1051. return Results;
  1052. }
  1053. FcbAcquired = TRUE;
  1054. try {
  1055. IoStatus->Status = RdrIsOperationValid(Icb, IRP_MJ_QUERY_INFORMATION, FileObject);
  1056. if (!NT_SUCCESS(IoStatus->Status)) {
  1057. IoStatus->Information = 0;
  1058. try_return(Results = TRUE);
  1059. }
  1060. if (!RdrCanFileBeBuffered(Icb)) {
  1061. try_return(Results);
  1062. }
  1063. Buffer->NumberOfLinks = 1; // Assume 1 links on the file.
  1064. Buffer->DeletePending = FileObject->DeletePending;
  1065. if (Icb->Type != DiskFile) {
  1066. Buffer->EndOfFile.QuadPart =
  1067. Buffer->AllocationSize.QuadPart = 0;
  1068. Buffer->Directory = (BOOLEAN)((Icb->Type == Directory) || (Icb->Type == TreeConnect));
  1069. } else {
  1070. IoStatus->Status = RdrDetermineFileAllocation(NULL,
  1071. Icb,
  1072. &Buffer->AllocationSize,
  1073. NULL);
  1074. if (!NT_SUCCESS(IoStatus->Status)) {
  1075. IoStatus->Information = 0;
  1076. try_return(Results = TRUE);
  1077. }
  1078. Buffer->EndOfFile = Icb->Fcb->Header.FileSize;
  1079. Buffer->Directory = FALSE;
  1080. }
  1081. IoStatus->Status = STATUS_SUCCESS;
  1082. IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
  1083. Results = TRUE;
  1084. try_exit: NOTHING;
  1085. } finally {
  1086. if (FcbAcquired) {
  1087. RdrReleaseFcbLock( Fcb );
  1088. }
  1089. FsRtlExitFileSystem();
  1090. }
  1091. //
  1092. // And return to our caller
  1093. //
  1094. return Results;
  1095. }
  1096. DBGSTATIC
  1097. BOOLEAN
  1098. QueryBasicInfo (
  1099. IN PIRP Irp,
  1100. IN PICB Icb,
  1101. OUT PFILE_BASIC_INFORMATION UsersBuffer,
  1102. IN OUT PULONG BufferSize,
  1103. PNTSTATUS FinalStatus,
  1104. BOOLEAN Wait
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. This routine implements the FileQueryBasicInformation value of the
  1109. NtQueryInformationFile api. It returns the following information:
  1110. Arguments:
  1111. IN PICB Icb - Supplies the ICB associated with this request.
  1112. OUT PFILE_BASIC_INFORMATION UsersBuffer - Supplies the user's buffer
  1113. that is filled in with the
  1114. requested data.
  1115. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1116. with the amount used.
  1117. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1118. IN BOOLEAN Wait - True if FSP can wait for this request.
  1119. Return Value:
  1120. NTSTATUS - Status of operation performed.
  1121. --*/
  1122. {
  1123. QSFILEATTRIB FileAttribs;
  1124. PAGED_CODE();
  1125. if (!RdrAcquireFcbLock(Icb->Fcb, SharedLock, Wait)) {
  1126. return TRUE;
  1127. }
  1128. if (Icb->Type == DiskFile &&
  1129. RdrCanFileBeBuffered(Icb)) {
  1130. //
  1131. // If the file can be buffered, we don't have to hit the net
  1132. // to find this information out, we have it cached locally anyway!
  1133. //
  1134. UsersBuffer->CreationTime = Icb->Fcb->CreationTime;
  1135. UsersBuffer->LastAccessTime = Icb->Fcb->LastAccessTime;
  1136. UsersBuffer->LastWriteTime = Icb->Fcb->LastWriteTime;
  1137. UsersBuffer->ChangeTime = Icb->Fcb->ChangeTime;
  1138. UsersBuffer->FileAttributes = Icb->Fcb->Attribute;
  1139. ASSERT ((Icb->Fcb->Attribute & ~FILE_ATTRIBUTE_VALID_FLAGS) == 0);
  1140. *BufferSize -= sizeof(FILE_BASIC_INFORMATION);
  1141. *FinalStatus = STATUS_SUCCESS;
  1142. RdrReleaseFcbLock(Icb->Fcb);
  1143. return FALSE;
  1144. }
  1145. RdrReleaseFcbLock(Icb->Fcb);
  1146. if (!Wait) {
  1147. return TRUE;
  1148. }
  1149. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1150. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1151. *FinalStatus = RdrQueryNtFileInformation(
  1152. Irp,
  1153. Icb,
  1154. SMB_QUERY_FILE_BASIC_INFO,
  1155. UsersBuffer,
  1156. BufferSize
  1157. );
  1158. } else {
  1159. *FinalStatus = RdrQueryNtPathInformation(
  1160. Irp,
  1161. Icb,
  1162. SMB_QUERY_FILE_BASIC_INFO,
  1163. UsersBuffer,
  1164. BufferSize
  1165. );
  1166. }
  1167. } else {
  1168. *FinalStatus = RdrQueryFileAttributes(Irp, Icb, &FileAttribs);
  1169. if (NT_SUCCESS(*FinalStatus)) {
  1170. UsersBuffer->CreationTime = FileAttribs.CreationTime;
  1171. UsersBuffer->LastAccessTime = FileAttribs.LastAccessTime;
  1172. UsersBuffer->LastWriteTime = FileAttribs.LastWriteTime;
  1173. UsersBuffer->ChangeTime = FileAttribs.ChangeTime;
  1174. UsersBuffer->FileAttributes = FileAttribs.Attributes;
  1175. ASSERT ((FileAttribs.Attributes & ~FILE_ATTRIBUTE_VALID_FLAGS) == 0);
  1176. *BufferSize -= sizeof(FILE_BASIC_INFORMATION);
  1177. }
  1178. }
  1179. return FALSE;
  1180. }
  1181. DBGSTATIC
  1182. BOOLEAN
  1183. QueryStandardInfo (
  1184. IN PIRP Irp,
  1185. IN PICB Icb,
  1186. OUT PFILE_STANDARD_INFORMATION UsersBuffer,
  1187. IN OUT PULONG BufferSize,
  1188. PNTSTATUS FinalStatus,
  1189. BOOLEAN Wait
  1190. )
  1191. /*++
  1192. Routine Description:
  1193. This routine implements the FileQueryStandardInformation value of the
  1194. NtQueryInformationFile api. It returns the following information:
  1195. Arguments:
  1196. IN PICB Icb - Supplies the ICB associated with this request.
  1197. OUT PFILE_STANDARD_INFORMATION UsersBuffer - Supplies the user's buffer
  1198. that is filled in with the
  1199. requested data.
  1200. IN OUT PULONG BufferSize - Supplies the size of the buffer. On return,
  1201. the amount of the buffer consumed is
  1202. subtracted from the initial size.
  1203. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1204. IN BOOLEAN Wait - True if FSP can wait for this request.
  1205. Return Value:
  1206. BOOLEAN - True if request is to be processed in the FSP.
  1207. --*/
  1208. {
  1209. QSFILEATTRIB FileAttribs;
  1210. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  1211. UsersBuffer->NumberOfLinks = 1; // Assume 1 links on the file.
  1212. UsersBuffer->DeletePending = IrpSp->FileObject->DeletePending;
  1213. if (!RdrAcquireFcbLock(Icb->Fcb, SharedLock, Wait)) {
  1214. return TRUE;
  1215. }
  1216. if (Icb->Type != FileOrDirectory) {
  1217. UsersBuffer->Directory = (BOOLEAN )((Icb->Type == Directory) || (Icb->Type == TreeConnect));
  1218. //
  1219. // If this is not a disk file, then it has no size, and we should
  1220. // return 0 as the end of file and allocation size.
  1221. //
  1222. if (Icb->Type != DiskFile) {
  1223. UsersBuffer->EndOfFile.QuadPart =
  1224. UsersBuffer->AllocationSize.QuadPart = 0;
  1225. *FinalStatus = STATUS_SUCCESS;
  1226. *BufferSize -= sizeof(FILE_STANDARD_INFORMATION);
  1227. RdrReleaseFcbLock(Icb->Fcb);
  1228. return FALSE;
  1229. }
  1230. if (RdrCanFileBeBuffered(Icb)) {
  1231. *FinalStatus = RdrDetermineFileAllocation(Irp, Icb, &UsersBuffer->AllocationSize, NULL);
  1232. if (!NT_SUCCESS(*FinalStatus)) {
  1233. RdrReleaseFcbLock(Icb->Fcb);
  1234. return FALSE;
  1235. }
  1236. UsersBuffer->EndOfFile = Icb->Fcb->Header.FileSize;
  1237. *FinalStatus = STATUS_SUCCESS;
  1238. *BufferSize -= sizeof(FILE_STANDARD_INFORMATION);
  1239. RdrReleaseFcbLock(Icb->Fcb);
  1240. return FALSE;
  1241. }
  1242. }
  1243. RdrReleaseFcbLock(Icb->Fcb);
  1244. //
  1245. // We have to go to the net to find out the size of the file. If we
  1246. // cannot block the user's thread, pass the request to the FSP.
  1247. //
  1248. if (!Wait) {
  1249. return TRUE;
  1250. }
  1251. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1252. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1253. *FinalStatus = RdrQueryNtFileInformation(
  1254. Irp,
  1255. Icb,
  1256. SMB_QUERY_FILE_STANDARD_INFO,
  1257. UsersBuffer,
  1258. BufferSize
  1259. );
  1260. } else {
  1261. *FinalStatus = RdrQueryNtPathInformation(
  1262. Irp,
  1263. Icb,
  1264. SMB_QUERY_FILE_STANDARD_INFO,
  1265. UsersBuffer,
  1266. BufferSize
  1267. );
  1268. }
  1269. } else {
  1270. //
  1271. // Determine the file's size using a GetExpandedAttributes
  1272. // SMB.
  1273. //
  1274. *FinalStatus = RdrQueryFileAttributes(Irp, Icb, &FileAttribs);
  1275. if (NT_SUCCESS(*FinalStatus)) {
  1276. //
  1277. // If we don't know the type of this file, we want to
  1278. // find out whether or not it is a directory by looking at
  1279. // the attributes to see if the file is a directory.
  1280. //
  1281. if (Icb->Type == FileOrDirectory) {
  1282. UsersBuffer->Directory = (BOOLEAN)(FileAttribs.Attributes & FILE_ATTRIBUTE_DIRECTORY);
  1283. } else {
  1284. UsersBuffer->Directory = (BOOLEAN)((Icb->Type == Directory) || (Icb->Type == TreeConnect));
  1285. }
  1286. UsersBuffer->AllocationSize.QuadPart = FileAttribs.AllocationSize;
  1287. UsersBuffer->EndOfFile.QuadPart = FileAttribs.FileSize;
  1288. *BufferSize -= sizeof(FILE_STANDARD_INFORMATION);
  1289. } else {
  1290. dprintf(DPRT_FILEINFO, ("RdrQueryFileAttributes(%wZ) failed, Status=%X\n",
  1291. &Icb->Fcb->FileName, *FinalStatus));
  1292. }
  1293. }
  1294. return FALSE;
  1295. }
  1296. DBGSTATIC
  1297. BOOLEAN
  1298. QueryStreamInfo (
  1299. IN PIRP Irp,
  1300. IN PICB Icb,
  1301. OUT PFILE_STREAM_INFORMATION UsersBuffer,
  1302. IN OUT PULONG BufferSize,
  1303. PNTSTATUS FinalStatus,
  1304. BOOLEAN Wait
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine implements the FileQueryBasicInformation value of the
  1309. NtQueryInformationFile api. It returns the following information:
  1310. Arguments:
  1311. IN PICB Icb - Supplies the ICB associated with this request.
  1312. OUT PFILE_STREAM_INFORMATION UsersBuffer - Supplies the user's buffer
  1313. that is filled in with the
  1314. requested data.
  1315. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1316. with the amount used.
  1317. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1318. IN BOOLEAN Wait - True if FSP can wait for this request.
  1319. Return Value:
  1320. NTSTATUS - Status of operation performed.
  1321. --*/
  1322. {
  1323. PAGED_CODE();
  1324. if (!Wait) {
  1325. return TRUE;
  1326. }
  1327. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1328. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1329. *FinalStatus = RdrQueryNtFileInformation(
  1330. Irp,
  1331. Icb,
  1332. SMB_QUERY_FILE_STREAM_INFO,
  1333. UsersBuffer,
  1334. BufferSize
  1335. );
  1336. } else {
  1337. *FinalStatus = RdrQueryNtPathInformation(
  1338. Irp,
  1339. Icb,
  1340. SMB_QUERY_FILE_STREAM_INFO,
  1341. UsersBuffer,
  1342. BufferSize
  1343. );
  1344. }
  1345. } else {
  1346. *FinalStatus = STATUS_NOT_SUPPORTED;
  1347. }
  1348. return FALSE;
  1349. }
  1350. DBGSTATIC
  1351. BOOLEAN
  1352. QueryCompressionInfo (
  1353. IN PIRP Irp,
  1354. IN PICB Icb,
  1355. OUT PFILE_COMPRESSION_INFORMATION UsersBuffer,
  1356. IN OUT PULONG BufferSize,
  1357. PNTSTATUS FinalStatus,
  1358. BOOLEAN Wait
  1359. )
  1360. /*++
  1361. Routine Description:
  1362. This routine implements the FileCompressionInformation value of the
  1363. NtQueryInformationFile API.
  1364. Arguments:
  1365. IN PIRP Irp - Supplies the IRP associated with this request.
  1366. IN PICB Icb - Supplies the ICB associated with this request.
  1367. OUT PFILE_COMPRESSION_INFORMATION UsersBuffer - Supplies the user's buffer
  1368. that is filled in with the
  1369. requested data.
  1370. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1371. with the amount used.
  1372. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1373. IN BOOLEAN Wait - True if FSP can wait for this request.
  1374. Return Value:
  1375. BOOLEAN - Indicates whether the IRP should be posted.
  1376. --*/
  1377. {
  1378. PAGED_CODE();
  1379. if ( !Wait ) {
  1380. return TRUE;
  1381. }
  1382. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1383. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1384. *FinalStatus = RdrQueryNtFileInformation(
  1385. Irp,
  1386. Icb,
  1387. SMB_QUERY_FILE_COMPRESSION_INFO,
  1388. UsersBuffer,
  1389. BufferSize
  1390. );
  1391. } else {
  1392. *FinalStatus = RdrQueryNtPathInformation(
  1393. Irp,
  1394. Icb,
  1395. SMB_QUERY_FILE_COMPRESSION_INFO,
  1396. UsersBuffer,
  1397. BufferSize
  1398. );
  1399. }
  1400. } else {
  1401. *FinalStatus = STATUS_NOT_SUPPORTED;
  1402. }
  1403. return FALSE;
  1404. }
  1405. DBGSTATIC
  1406. BOOLEAN
  1407. QueryOleAllMiscInfo (
  1408. IN PIRP Irp,
  1409. IN PICB Icb,
  1410. OUT PFILE_OLE_ALL_INFORMATION UsersBuffer,
  1411. IN OUT PULONG BufferSize,
  1412. PNTSTATUS FinalStatus,
  1413. BOOLEAN Wait
  1414. )
  1415. /*++
  1416. Routine Description:
  1417. This routine implements selected portions of FileQueryOleAllInformation
  1418. of the NtQueryInformationFile api.
  1419. It returns the following information:
  1420. Arguments:
  1421. IN PICB Icb - Supplies the ICB associated with this request.
  1422. OUT PFILE_OLE_INFORMATION UsersBuffer - Supplies the user's buffer
  1423. that is filled in with the
  1424. requested data.
  1425. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1426. with the amount used.
  1427. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1428. IN BOOLEAN Wait - True if FSP can wait for this request.
  1429. Return Value:
  1430. NTSTATUS - Status of operation performed.
  1431. --*/
  1432. {
  1433. PAGED_CODE();
  1434. ASSERT (!ExIsResourceAcquiredExclusive(Icb->Fcb->Header.Resource));
  1435. if (!Wait) {
  1436. return TRUE;
  1437. }
  1438. if ((Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) &&
  1439. (Icb->Flags & ICB_HASHANDLE)) {
  1440. FILE_OLE_ALL_INFORMATION *pfoai;
  1441. //
  1442. // We are going to ask the remote server for OLE_ALL_INFORMATION.
  1443. // We do not want to perturb the contents of the user's buffer that
  1444. // have been filled in so far. So, we allocate a new
  1445. // OLE_ALL_INFORMATION struct, get the info in it, and then copy only
  1446. // a subpart to the user's buffer.
  1447. //
  1448. // We will copy everything from the LastChangeUsn field of the struct.
  1449. //
  1450. // Hence, we need to allocate *BufferSize + field offset of
  1451. // LastChangeUsn bytes.
  1452. //
  1453. ULONG cb = *BufferSize + FIELD_OFFSET(FILE_OLE_ALL_INFORMATION, LastChangeUsn);
  1454. pfoai = ALLOCATE_POOL(PagedPool, cb, POOL_OLE_ALL_BUFFER);
  1455. if (pfoai == NULL) {
  1456. *FinalStatus = STATUS_NO_MEMORY;
  1457. } else {
  1458. try {
  1459. *FinalStatus = RdrQueryNtFileInformation(
  1460. Irp,
  1461. Icb,
  1462. SMB_QUERY_FILE_OLE_ALL_INFO,
  1463. pfoai,
  1464. &cb);
  1465. if (NT_SUCCESS(*FinalStatus)
  1466. ||
  1467. *FinalStatus == STATUS_BUFFER_OVERFLOW) {
  1468. ULONG cbCopy;
  1469. UsersBuffer->InternalInformation.IndexNumber =
  1470. pfoai->InternalInformation.IndexNumber;
  1471. cbCopy = FIELD_OFFSET(
  1472. FILE_OLE_ALL_INFORMATION,
  1473. NameInformation.FileName[0]) +
  1474. pfoai->NameInformation.FileNameLength -
  1475. FIELD_OFFSET( FILE_OLE_ALL_INFORMATION, LastChangeUsn);
  1476. if (cbCopy > *BufferSize) {
  1477. cbCopy = *BufferSize;
  1478. *FinalStatus = STATUS_BUFFER_OVERFLOW;
  1479. }
  1480. RtlCopyMemory(&UsersBuffer->LastChangeUsn, &pfoai->LastChangeUsn, cbCopy);
  1481. *BufferSize -= cbCopy;
  1482. }
  1483. } finally {
  1484. FREE_POOL(pfoai);
  1485. }
  1486. }
  1487. } else {
  1488. *FinalStatus = STATUS_NOT_SUPPORTED;
  1489. }
  1490. ASSERT (!ExIsResourceAcquiredExclusive(Icb->Fcb->Header.Resource));
  1491. return FALSE;
  1492. }
  1493. DBGSTATIC
  1494. BOOLEAN
  1495. QueryOleInfo (
  1496. IN PIRP Irp,
  1497. IN PICB Icb,
  1498. OUT PFILE_OLE_INFORMATION UsersBuffer,
  1499. IN OUT PULONG BufferSize,
  1500. PNTSTATUS FinalStatus,
  1501. BOOLEAN Wait
  1502. )
  1503. /*++
  1504. Routine Description:
  1505. This routine implements the FileQueryOleInformation value of the
  1506. NtQueryInformationFile api. It returns the following information:
  1507. Arguments:
  1508. IN PICB Icb - Supplies the ICB associated with this request.
  1509. OUT PFILE_OLE_INFORMATION UsersBuffer - Supplies the user's buffer
  1510. that is filled in with the
  1511. requested data.
  1512. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1513. with the amount used.
  1514. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1515. IN BOOLEAN Wait - True if FSP can wait for this request.
  1516. Return Value:
  1517. NTSTATUS - Status of operation performed.
  1518. --*/
  1519. {
  1520. PAGED_CODE();
  1521. if (!Wait) {
  1522. return TRUE;
  1523. }
  1524. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1525. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1526. *FinalStatus = RdrQueryNtFileInformation(
  1527. Irp,
  1528. Icb,
  1529. SMB_QUERY_FILE_OLE_INFO,
  1530. UsersBuffer,
  1531. BufferSize
  1532. );
  1533. } else {
  1534. *FinalStatus = RdrQueryNtPathInformation(
  1535. Irp,
  1536. Icb,
  1537. SMB_QUERY_FILE_OLE_INFO,
  1538. UsersBuffer,
  1539. BufferSize
  1540. );
  1541. }
  1542. } else {
  1543. ULONG TransferSize = min(sizeof(*UsersBuffer), *BufferSize);
  1544. RtlZeroMemory(UsersBuffer, TransferSize);
  1545. *FinalStatus = (sizeof(*UsersBuffer) > *BufferSize)?
  1546. STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
  1547. *BufferSize -= TransferSize;
  1548. }
  1549. return FALSE;
  1550. }
  1551. NTSTATUS
  1552. RdrQueryNtFileInformation(
  1553. IN PIRP Irp,
  1554. IN PICB Icb,
  1555. IN USHORT FileInformationClass,
  1556. IN OUT PVOID Buffer,
  1557. IN OUT PULONG BufferSize
  1558. )
  1559. /*++
  1560. Routine Description:
  1561. This routine remotes a simple NtQueryInformationFile API to the server.
  1562. Arguments:
  1563. IN PIRP Irp - Supplies an IRP to use for the request.
  1564. IN PICB Icb - Supplies the ICB associated with this request.
  1565. IN USHORT FileInformationClass - Information class to query.
  1566. OUT PVOID UsersBuffer - Supplies the user's buffer
  1567. that is filled in with the requested data.
  1568. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1569. with the amount used.
  1570. Return Value:
  1571. NTSTATUS - True if request is to be processed in the FSP.
  1572. --*/
  1573. {
  1574. //
  1575. // Use TRANSACT2_QFILEINFO to query FileInformationClass.
  1576. //
  1577. USHORT Setup[] = {TRANS2_QUERY_FILE_INFORMATION};
  1578. REQ_QUERY_FILE_INFORMATION Parameters;
  1579. CLONG OutParameterCount;
  1580. CLONG OutDataCount;
  1581. CLONG OutSetupCount;
  1582. NTSTATUS Status;
  1583. PAGED_CODE();
  1584. ASSERT( sizeof(REQ_QUERY_FILE_INFORMATION) >= sizeof(RESP_QUERY_FILE_INFORMATION) );
  1585. OutParameterCount = sizeof(RESP_QUERY_FILE_INFORMATION);
  1586. OutDataCount = *BufferSize;
  1587. OutSetupCount = 0;
  1588. SmbPutAlignedUshort(&Parameters.InformationLevel, FileInformationClass);
  1589. SmbPutAlignedUshort(&Parameters.Fid, Icb->FileId);
  1590. Status = RdrTransact(Irp, // Irp,
  1591. Icb->Fcb->Connection,
  1592. Icb->Se,
  1593. Setup,
  1594. (CLONG) sizeof(Setup), // InSetupCount,
  1595. &OutSetupCount,
  1596. NULL, // Name,
  1597. &Parameters,
  1598. sizeof(Parameters), // InParameterCount,
  1599. &OutParameterCount,
  1600. NULL, // InData,
  1601. 0, // InDataCount,
  1602. Buffer, // OutData,
  1603. &OutDataCount,
  1604. &Icb->FileId, // Fid
  1605. 0, // Timeout
  1606. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  1607. 0, // NtTransactionFunction
  1608. NULL,
  1609. NULL
  1610. );
  1611. if (Status == STATUS_INVALID_HANDLE) {
  1612. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  1613. }
  1614. if (NT_SUCCESS(Status)) {
  1615. *BufferSize -= OutDataCount;
  1616. }
  1617. return Status;
  1618. }
  1619. NTSTATUS
  1620. RdrQueryNtPathInformation(
  1621. IN PIRP Irp,
  1622. IN PICB Icb,
  1623. IN USHORT FileInformationClass,
  1624. IN OUT PVOID Buffer,
  1625. IN OUT PULONG BufferSize
  1626. )
  1627. /*++
  1628. Routine Description:
  1629. This routine remotes a simple NtQueryInformationFile API to the server.
  1630. Arguments:
  1631. IN PIRP Irp - Supplies an IRP to use for the request.
  1632. IN PICB Icb - Supplies the ICB associated with this request.
  1633. IN USHORT FileInformationClass - Information class to query.
  1634. OUT PVOID UsersBuffer - Supplies the user's buffer
  1635. that is filled in with the requested data.
  1636. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1637. with the amount used.
  1638. Return Value:
  1639. NTSTATUS - True if request is to be processed in the FSP.
  1640. --*/
  1641. {
  1642. //
  1643. // Use TRANSACT2_QPATHINFO to query FileInformationClass.
  1644. //
  1645. USHORT Setup[] = {TRANS2_QUERY_PATH_INFORMATION};
  1646. PREQ_QUERY_PATH_INFORMATION Parameters;
  1647. PUCHAR Path;
  1648. PCONNECTLISTENTRY Connect = Icb->Fcb->Connection;
  1649. LARGE_INTEGER currentTime;
  1650. CLONG InParameterCount;
  1651. CLONG OutParameterCount;
  1652. CLONG OutDataCount;
  1653. CLONG OutSetupCount;
  1654. NTSTATUS Status;
  1655. PAGED_CODE();
  1656. KeQuerySystemTime( &currentTime );
  1657. if( currentTime.QuadPart <= Connect->CachedInvalidPathExpiration.QuadPart &&
  1658. RdrStatistics.SmbsTransmitted.LowPart == Connect->CachedInvalidSmbCount &&
  1659. RtlEqualUnicodeString( &Icb->Fcb->FileName, &Connect->CachedInvalidPath, TRUE ) ) {
  1660. //
  1661. // We know that this file does not exist on the server, so return error right now
  1662. //
  1663. return STATUS_OBJECT_NAME_NOT_FOUND;
  1664. }
  1665. InParameterCount = sizeof(REQ_QUERY_FILE_INFORMATION) + Icb->Fcb->FileName.Length;
  1666. Parameters = ALLOCATE_POOL( NonPagedPool, InParameterCount, POOL_PATH_BUFFER );
  1667. if ( Parameters == NULL ) {
  1668. return STATUS_INSUFFICIENT_RESOURCES;
  1669. }
  1670. Path = Parameters->Buffer;
  1671. Status = RdrCopyNetworkPath(
  1672. &Path,
  1673. &Icb->Fcb->FileName,
  1674. Connect->Server,
  1675. 0,
  1676. SKIP_SERVER_SHARE
  1677. );
  1678. if ( !NT_SUCCESS(Status) ) {
  1679. FREE_POOL( Parameters );
  1680. return Status;
  1681. }
  1682. InParameterCount = (ULONG)(Path - (PUCHAR)Parameters);
  1683. ASSERT( sizeof(REQ_QUERY_PATH_INFORMATION) >= sizeof(RESP_QUERY_PATH_INFORMATION) );
  1684. OutParameterCount = sizeof(RESP_QUERY_PATH_INFORMATION);
  1685. OutDataCount = *BufferSize;
  1686. OutSetupCount = 0;
  1687. SmbPutAlignedUshort(&Parameters->InformationLevel, FileInformationClass);
  1688. SmbPutAlignedUlong(&Parameters->Reserved, 0);
  1689. Status = RdrTransact(Irp, // Irp,
  1690. Connect,
  1691. Icb->Se,
  1692. Setup,
  1693. (CLONG) sizeof(Setup), // InSetupCount,
  1694. &OutSetupCount,
  1695. NULL, // Name,
  1696. Parameters,
  1697. InParameterCount,
  1698. &OutParameterCount,
  1699. NULL, // InData,
  1700. 0, // InDataCount,
  1701. Buffer, // OutData,
  1702. &OutDataCount,
  1703. NULL, // Fid
  1704. 0, // Timeout
  1705. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  1706. 0, // NtTransactionFunction
  1707. NULL,
  1708. NULL
  1709. );
  1710. FREE_POOL( Parameters );
  1711. if (NT_SUCCESS(Status)) {
  1712. *BufferSize -= OutDataCount;
  1713. } else if( Status == STATUS_OBJECT_NAME_NOT_FOUND &&
  1714. Icb->Fcb->FileName.Length <= Connect->CachedInvalidPath.MaximumLength ) {
  1715. //
  1716. // Cache the fact that this file does not exist on the server
  1717. //
  1718. RtlCopyMemory( Connect->CachedInvalidPath.Buffer,
  1719. Icb->Fcb->FileName.Buffer,
  1720. Icb->Fcb->FileName.Length );
  1721. Connect->CachedInvalidPath.Length = Icb->Fcb->FileName.Length;
  1722. Connect->CachedInvalidSmbCount = RdrStatistics.SmbsTransmitted.LowPart;
  1723. KeQuerySystemTime( &currentTime );
  1724. Connect->CachedInvalidPathExpiration.QuadPart = currentTime.QuadPart + 2 * 10 * 1000 * 1000;
  1725. }
  1726. return Status;
  1727. }
  1728. DBGSTATIC
  1729. BOOLEAN
  1730. QueryInternalInfo (
  1731. IN PICB Icb,
  1732. OUT PFILE_INTERNAL_INFORMATION UsersBuffer,
  1733. IN OUT PULONG BufferSize,
  1734. PNTSTATUS FinalStatus,
  1735. BOOLEAN Wait
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. This routine implements the FileQueryInternalInformation value of the
  1740. NtQueryInformationFile api. It returns the following information:
  1741. Arguments:
  1742. IN PICB Icb - Supplies the ICB associated with this request.
  1743. OUT PFILE_INTERNAL_INFORMATION UsersBuffer - Supplies the user's buffer
  1744. that is filled in with the
  1745. requested data.
  1746. IN OUT PULONG BufferSize - Supplies the size of the buffer, and is updated
  1747. with the amount used.
  1748. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1749. IN BOOLEAN Wait - True if FSP can wait for this request.
  1750. Return Value:
  1751. BOOLEAN - True if request is to be processed in the FSP.
  1752. --*/
  1753. {
  1754. PAGED_CODE();
  1755. // if ((Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) &&
  1756. // (Icb->Flags & ICB_HASHANDLE)) {
  1757. //
  1758. // *FinalStatus = RdrQueryNtFileInformation(Irp, Icb, SMB_QUERY_FILE_INTERNAL_INFO,
  1759. // UsersBuffer,
  1760. // BufferSize);
  1761. //
  1762. // } else {
  1763. //
  1764. // Note: We use the address of the FCB to determine the
  1765. // index number of the file. If we have to maintain persistance between
  1766. // file opens for this request, then we might have to do something
  1767. // like checksuming the reserved fields on a FUNIQUE SMB response.
  1768. //
  1769. UsersBuffer->IndexNumber.LowPart = (ULONG )Icb->Fcb;
  1770. UsersBuffer->IndexNumber.HighPart = 0;
  1771. *FinalStatus = STATUS_SUCCESS;
  1772. *BufferSize -= sizeof(FILE_INTERNAL_INFORMATION);
  1773. // }
  1774. return FALSE;
  1775. UNREFERENCED_PARAMETER(Wait);
  1776. }
  1777. DBGSTATIC
  1778. BOOLEAN
  1779. QueryEaInfo (
  1780. IN PIRP Irp,
  1781. IN PICB Icb,
  1782. OUT PFILE_EA_INFORMATION UsersBuffer,
  1783. IN OUT PULONG BufferSize,
  1784. PNTSTATUS FinalStatus,
  1785. BOOLEAN Wait
  1786. )
  1787. /*++
  1788. Routine Description:
  1789. This routine implements the FileQueryEaInformation value of the
  1790. NtQueryInformationFile api. It returns the following information:
  1791. Arguments:
  1792. IN PICB Icb - Supplies the ICB associated with this request.
  1793. OUT PFILE_EA_INFORMATION UsersBuffer - Supplies the user's buffer
  1794. that is filled in with the
  1795. requested data.
  1796. IN OUT PULONG BufferSize - Supplies the size of the buffer. On return,
  1797. the amount of the buffer consumed is
  1798. subtracted from the initial size.
  1799. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1800. IN BOOLEAN Wait - True if FSP can wait for this request.
  1801. Return Value:
  1802. BOOLEAN - True if request is to be processed in the FSP.
  1803. --*/
  1804. {
  1805. PAGED_CODE();
  1806. if (!(Icb->Fcb->Connection->Server->Capabilities & DF_SUPPORTEA)) {
  1807. //
  1808. // Make sure that there are 0 ea's on the file.
  1809. //
  1810. UsersBuffer->EaSize = 0;
  1811. *FinalStatus = STATUS_EAS_NOT_SUPPORTED;
  1812. return FALSE;
  1813. } else if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  1814. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  1815. *FinalStatus = RdrQueryNtFileInformation(
  1816. Irp,
  1817. Icb,
  1818. SMB_QUERY_FILE_EA_INFO,
  1819. UsersBuffer,
  1820. BufferSize
  1821. );
  1822. } else {
  1823. *FinalStatus = RdrQueryNtPathInformation(
  1824. Irp,
  1825. Icb,
  1826. SMB_QUERY_FILE_EA_INFO,
  1827. UsersBuffer,
  1828. BufferSize
  1829. );
  1830. }
  1831. } else {
  1832. USHORT Setup[] = {TRANS2_QUERY_PATH_INFORMATION};
  1833. PUCHAR TempBuffer;
  1834. FILESTATUS Buffer;
  1835. CLONG OutSetupCount = 0;
  1836. CLONG OutDataCount = sizeof(Buffer);
  1837. CLONG OutParameterCount = sizeof(RESP_QUERY_PATH_INFORMATION);
  1838. //
  1839. // The same buffer is used for request and response parameters
  1840. //
  1841. union {
  1842. struct _Q {
  1843. REQ_QUERY_PATH_INFORMATION Q;
  1844. UCHAR PathName[MAXIMUM_PATHLEN_LANMAN12];
  1845. } Q;
  1846. RESP_QUERY_PATH_INFORMATION R;
  1847. } Parameters;
  1848. SmbPutAlignedUshort( &Parameters.Q.Q.InformationLevel, SMB_INFO_QUERY_EA_SIZE);
  1849. TempBuffer = Parameters.Q.Q.Buffer;
  1850. //
  1851. // Strip \Server\Share and copy just PATH
  1852. //
  1853. *FinalStatus = RdrCopyNetworkPath((PVOID *)&TempBuffer,
  1854. &Icb->Fcb->FileName,
  1855. Icb->Fcb->Connection->Server,
  1856. FALSE,
  1857. SKIP_SERVER_SHARE);
  1858. if (!NT_SUCCESS(*FinalStatus)) {
  1859. return FALSE;
  1860. }
  1861. *FinalStatus = RdrTransact(Irp, // Irp,
  1862. Icb->Fcb->Connection,
  1863. Icb->Se,
  1864. Setup,
  1865. (CLONG) sizeof(Setup), // InSetupCount,
  1866. &OutSetupCount,
  1867. NULL, // Name,
  1868. &Parameters.Q,
  1869. TempBuffer-(PUCHAR)&Parameters, // InParameterCount,
  1870. &OutParameterCount,
  1871. NULL, // InData,
  1872. 0,
  1873. &Buffer, // OutData,
  1874. &OutDataCount,
  1875. NULL, // Fid
  1876. 0, // Timeout
  1877. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  1878. 0,
  1879. NULL,
  1880. NULL
  1881. );
  1882. if (!NT_SUCCESS(*FinalStatus)) {
  1883. return FALSE;
  1884. }
  1885. UsersBuffer->EaSize = Buffer.EaSize;
  1886. //
  1887. // Os/2 machines return 4 (sizeof(cblist)) when there are no ea's on
  1888. // a file.
  1889. //
  1890. if (UsersBuffer->EaSize == 4) {
  1891. UsersBuffer->EaSize = 0;
  1892. }
  1893. *BufferSize -= sizeof(FILE_EA_INFORMATION);
  1894. }
  1895. return FALSE;
  1896. UNREFERENCED_PARAMETER(Wait);
  1897. }
  1898. DBGSTATIC
  1899. BOOLEAN
  1900. QueryNameInfo (
  1901. IN PIRP Irp,
  1902. IN PICB Icb,
  1903. OUT PFILE_NAME_INFORMATION UsersBuffer,
  1904. IN OUT PULONG BufferSize,
  1905. PNTSTATUS FinalStatus,
  1906. BOOLEAN Wait
  1907. )
  1908. /*++
  1909. Routine Description:
  1910. This routine implements the FileQueryNameInformation value of the
  1911. NtQueryInformationFile api. It returns the following information:
  1912. Arguments:
  1913. IN PICB Icb - Supplies the ICB associated with this request.
  1914. OUT PFILE_NAME_INFORMATION UsersBuffer - Supplies the user's buffer
  1915. that is filled in with the
  1916. requested data.
  1917. IN OUT PULONG BufferSize - Supplies the size of the buffer. On return,
  1918. the amount of the buffer consumed is
  1919. subtracted from the initial size.
  1920. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  1921. IN BOOLEAN Wait - True if FSP can wait for this request.
  1922. Return Value:
  1923. BOOLEAN - True if request is to be processed in the FSP.
  1924. --*/
  1925. {
  1926. PFCB Fcb = Icb->Fcb;
  1927. PCONNECTLISTENTRY Connection = Fcb->Connection;
  1928. PSERVERLISTENTRY Server = Connection->Server;
  1929. PAGED_CODE();
  1930. RdrAcquireFcbLock(Fcb, SharedLock, TRUE);
  1931. //
  1932. // Reduce the available buffer space by the fixed part of the structure.
  1933. //
  1934. *BufferSize -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
  1935. if ((Server->Capabilities & DF_NT_SMBS) &&
  1936. (Icb->Flags & ICB_HASHANDLE)) {
  1937. WCHAR FilenameBuffer[MAXIMUM_FILENAME_LENGTH+sizeof(FILE_NAME_INFORMATION)];
  1938. PFILE_NAME_INFORMATION NameInfo = (PFILE_NAME_INFORMATION)FilenameBuffer;
  1939. //
  1940. // Use TRANSACT2_QFILEINFO to query FILE_STANDARD_INFORMATION.
  1941. //
  1942. USHORT Setup[] = {TRANS2_QUERY_FILE_INFORMATION};
  1943. REQ_QUERY_FILE_INFORMATION Parameters;
  1944. CLONG OutParameterCount = sizeof(REQ_QUERY_FILE_INFORMATION);
  1945. CLONG OutDataCount = sizeof(FilenameBuffer);
  1946. CLONG OutSetupCount = 0;
  1947. SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_QUERY_FILE_NAME_INFO);
  1948. SmbPutAlignedUshort(&Parameters.Fid, Icb->FileId);
  1949. *FinalStatus = RdrTransact(Irp, // Irp,
  1950. Connection,
  1951. Icb->Se,
  1952. Setup,
  1953. (CLONG) sizeof(Setup), // InSetupCount,
  1954. &OutSetupCount,
  1955. NULL, // Name,
  1956. &Parameters,
  1957. sizeof(Parameters), // InParameterCount,
  1958. &OutParameterCount,
  1959. NULL, // InData,
  1960. 0, // InDataCount,
  1961. FilenameBuffer, // OutData,
  1962. &OutDataCount,
  1963. &Icb->FileId, // Fid
  1964. 0, // Timeout
  1965. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  1966. 0, // NtTransact function
  1967. NULL,
  1968. NULL
  1969. );
  1970. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  1971. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  1972. }
  1973. if (!NT_ERROR(*FinalStatus)) {
  1974. UNICODE_STRING FileName;
  1975. UNICODE_STRING ServerFileName;
  1976. UsersBuffer->FileNameLength =
  1977. sizeof(WCHAR) + Server->Text.Length + sizeof(WCHAR) +
  1978. ((Icb->Type == NamedPipe) ? RdrPipeText.Length : Connection->Text.Length) +
  1979. NameInfo->FileNameLength;
  1980. ServerFileName.Buffer = NameInfo->FileName;
  1981. ServerFileName.MaximumLength = sizeof(FilenameBuffer);
  1982. ServerFileName.Length = (USHORT)NameInfo->FileNameLength;
  1983. FileName.Buffer = UsersBuffer->FileName;
  1984. FileName.Length = 0;
  1985. FileName.MaximumLength = (USHORT)*BufferSize;
  1986. RtlAppendUnicodeToString(&FileName, L"\\");
  1987. RtlAppendUnicodeStringToString(&FileName, &Server->Text);
  1988. RtlAppendUnicodeToString(&FileName, L"\\");
  1989. if (Icb->Type == NamedPipe) {
  1990. RtlAppendUnicodeStringToString(&FileName, &RdrPipeText);
  1991. } else {
  1992. RtlAppendUnicodeStringToString(&FileName, &Connection->Text);
  1993. }
  1994. RtlAppendUnicodeStringToString(&FileName, &ServerFileName);
  1995. ASSERT(*BufferSize >= (ULONG)FileName.Length);
  1996. *BufferSize -= FileName.Length;
  1997. if (FileName.Length < UsersBuffer->FileNameLength) {
  1998. *FinalStatus = STATUS_BUFFER_OVERFLOW;
  1999. } else {
  2000. *FinalStatus = STATUS_SUCCESS;
  2001. }
  2002. }
  2003. } else {
  2004. ULONG NameSizeToCopy;
  2005. if (*BufferSize < Fcb->FileName.Length ) {
  2006. *FinalStatus = STATUS_BUFFER_OVERFLOW;
  2007. NameSizeToCopy = *BufferSize;
  2008. } else {
  2009. *FinalStatus = STATUS_SUCCESS;
  2010. NameSizeToCopy = Fcb->FileName.Length;
  2011. }
  2012. UsersBuffer->FileNameLength = Fcb->FileName.Length;
  2013. RtlCopyMemory(UsersBuffer->FileName, Fcb->FileName.Buffer, NameSizeToCopy);
  2014. *BufferSize -= NameSizeToCopy;
  2015. }
  2016. RdrReleaseFcbLock(Fcb);
  2017. return FALSE;
  2018. UNREFERENCED_PARAMETER(Wait);
  2019. }
  2020. DBGSTATIC
  2021. BOOLEAN
  2022. QueryAlternateNameInfo (
  2023. IN PIRP Irp,
  2024. IN PICB Icb,
  2025. OUT PFILE_NAME_INFORMATION UsersBuffer,
  2026. IN OUT PULONG BufferSize,
  2027. PNTSTATUS FinalStatus,
  2028. BOOLEAN Wait
  2029. )
  2030. /*++
  2031. Routine Description:
  2032. This routine implements the FileAlternateNameInformation value of the
  2033. NtQueryInformationFile api. It returns the following information:
  2034. Arguments:
  2035. IN PICB Icb - Supplies the ICB associated with this request.
  2036. OUT PFILE_NAME_INFORMATION UsersBuffer - Supplies the user's buffer
  2037. that is filled in with the
  2038. requested data.
  2039. IN OUT PULONG BufferSize - Supplies the size of the buffer. On return,
  2040. the amount of the buffer consumed is
  2041. subtracted from the initial size.
  2042. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2043. IN BOOLEAN Wait - True if FSP can wait for this request.
  2044. Return Value:
  2045. BOOLEAN - True if request is to be processed in the FSP.
  2046. --*/
  2047. {
  2048. PAGED_CODE();
  2049. if ( FlagOn(Icb->Fcb->Connection->Server->Capabilities, DF_NT_SMBS) ) {
  2050. if ( FlagOn(Icb->Flags, ICB_HASHANDLE) ) {
  2051. *FinalStatus = RdrQueryNtFileInformation(
  2052. Irp,
  2053. Icb,
  2054. SMB_QUERY_FILE_ALT_NAME_INFO,
  2055. UsersBuffer,
  2056. BufferSize
  2057. );
  2058. } else {
  2059. *FinalStatus = RdrQueryNtPathInformation(
  2060. Irp,
  2061. Icb,
  2062. SMB_QUERY_FILE_ALT_NAME_INFO,
  2063. UsersBuffer,
  2064. BufferSize
  2065. );
  2066. }
  2067. } else {
  2068. *FinalStatus = STATUS_NOT_SUPPORTED;
  2069. }
  2070. return FALSE;
  2071. UNREFERENCED_PARAMETER(Wait);
  2072. }
  2073. DBGSTATIC
  2074. BOOLEAN
  2075. QueryPositionInfo (
  2076. IN PICB Icb,
  2077. IN PIO_STACK_LOCATION IrpSp,
  2078. OUT PFILE_POSITION_INFORMATION UsersBuffer,
  2079. IN OUT PULONG BufferSize,
  2080. PNTSTATUS FinalStatus,
  2081. BOOLEAN Wait
  2082. )
  2083. /*++
  2084. Routine Description:
  2085. This routine implements the FileQueryPositionInformation value of the
  2086. NtQueryInformationFile api. It returns the following information:
  2087. Arguments:
  2088. IN PICB Icb - Supplies the ICB associated with this request.
  2089. OUT PFILE_POSITION_INFORMATION UsersBuffer - Supplies the user's buffer
  2090. that is filled in with the
  2091. requested data.
  2092. IN OUT PULONG BufferSize - Supplies the size of the buffer. On return,
  2093. the amount of the buffer consumed is
  2094. subtracted from the initial size.
  2095. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2096. IN BOOLEAN Wait - True if FSP can wait for this request.
  2097. Return Value:
  2098. BOOLEAN - True if request is to be processed in the FSP.
  2099. --*/
  2100. {
  2101. PAGED_CODE();
  2102. //
  2103. // Snarf the position out of the file object. Please note that
  2104. // this information is totally bogus for a file that is not
  2105. // synchronous. (But you knew that anyway).
  2106. //
  2107. *BufferSize -= sizeof(FILE_POSITION_INFORMATION);
  2108. UsersBuffer->CurrentByteOffset = IrpSp->FileObject->CurrentByteOffset;
  2109. *FinalStatus = STATUS_SUCCESS;
  2110. return FALSE;
  2111. if (Wait||Icb);
  2112. }
  2113. DBGSTATIC
  2114. BOOLEAN
  2115. SetBasicInfo (
  2116. IN PIRP Irp,
  2117. IN PICB Icb,
  2118. IN PFILE_BASIC_INFORMATION UsersBuffer,
  2119. IN ULONG BufferSize,
  2120. PNTSTATUS FinalStatus,
  2121. BOOLEAN Wait
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. This routine implements the FileBasicInformation value of the
  2126. NtSetInformationFile api. It returns the following information:
  2127. Arguments:
  2128. IN PICB Icb - Supplies the ICB associated with this request.
  2129. OUT PFILE_BASIC_INFORMATION UsersBuffer - Supplies the user's buffer
  2130. that is filled in with the
  2131. requested data.
  2132. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  2133. the amount of the buffer consumed is
  2134. subtracted from the initial size.
  2135. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2136. IN BOOLEAN Wait - True if FSD can wait for this request.
  2137. Return Value:
  2138. BOOLEAN - True if request is to be processed in the FSP.
  2139. --*/
  2140. {
  2141. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2142. BOOLEAN FcbLocked = FALSE;
  2143. PAGED_CODE();
  2144. if (BufferSize < sizeof(FILE_BASIC_INFORMATION)) {
  2145. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  2146. return FALSE;
  2147. } else {
  2148. if (UsersBuffer->FileAttributes == 0 &&
  2149. UsersBuffer->CreationTime.HighPart == 0 &&
  2150. UsersBuffer->CreationTime.LowPart == 0 &&
  2151. UsersBuffer->LastAccessTime.HighPart == 0 &&
  2152. UsersBuffer->LastAccessTime.LowPart == 0 &&
  2153. UsersBuffer->LastWriteTime.HighPart == 0 &&
  2154. UsersBuffer->LastWriteTime.LowPart == 0 &&
  2155. UsersBuffer->ChangeTime.HighPart == 0 &&
  2156. UsersBuffer->ChangeTime.LowPart == 0) {
  2157. *FinalStatus = STATUS_SUCCESS;
  2158. return FALSE;
  2159. }
  2160. if (!Wait) {
  2161. return TRUE;
  2162. }
  2163. *FinalStatus = RdrSetFileAttributes(Irp, Icb, UsersBuffer);
  2164. if (NT_SUCCESS(*FinalStatus)) {
  2165. RdrAcquireFcbLock(Icb->Fcb, ExclusiveLock, TRUE);
  2166. if (UsersBuffer->FileAttributes != 0) {
  2167. Icb->Fcb->Attribute = UsersBuffer->FileAttributes;
  2168. //
  2169. // If this is a disk file, and
  2170. // the file has a handle (isn't pseudo-opened) &&
  2171. // the new file attributes indicate that the file isn't
  2172. // readonly and
  2173. // the file is currently cached, and
  2174. // we can't keep the file open for any other reason,
  2175. // then purge the cache for the file.
  2176. //
  2177. if ((Icb->Type == DiskFile) &&
  2178. (Icb->Flags & ICB_HASHANDLE)) {
  2179. if ((!(UsersBuffer->FileAttributes & FILE_ATTRIBUTE_READONLY))
  2180. &&
  2181. (CcIsFileCached(Icb->u.f.FileObject))) {
  2182. if (!(Icb->u.f.Flags & (ICBF_OPLOCKED | ICBF_OPENEDEXCLUSIVE))) {
  2183. ASSERT (RdrData.BufferReadOnlyFiles);
  2184. //RdrLog(( "rdflusha", &Icb->Fcb->FileName, 0 ));
  2185. *FinalStatus = RdrFlushCacheFile(Icb->Fcb);
  2186. if (Icb->Fcb->NonPagedFcb->OplockLevel != SMB_OPLOCK_LEVEL_II) {
  2187. *FinalStatus = RdrFlushFileLocks(Icb->Fcb);
  2188. }
  2189. //RdrLog(( "rdpurgea", &Icb->Fcb->FileName, 0 ));
  2190. *FinalStatus = RdrPurgeCacheFile(Icb->Fcb);
  2191. }
  2192. }
  2193. //
  2194. // If the user is setting the temporary bit, and the file
  2195. // object is not marked as temporary, mark it as temporary.
  2196. //
  2197. // If the temporary bit is NOT on, and the file is
  2198. // marked as temporary, turn off the temporary bit.
  2199. //
  2200. if ((FlagOn(UsersBuffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY))) {
  2201. if (!FlagOn(IrpSp->FileObject->Flags, FO_TEMPORARY_FILE)) {
  2202. IrpSp->FileObject->Flags |= FO_TEMPORARY_FILE;
  2203. }
  2204. } else if (FlagOn(IrpSp->FileObject->Flags, FO_TEMPORARY_FILE)) {
  2205. IrpSp->FileObject->Flags &= ~FO_TEMPORARY_FILE;
  2206. }
  2207. }
  2208. }
  2209. //
  2210. // Update the times in the FCB for the times that are being
  2211. // modified.
  2212. //
  2213. if (UsersBuffer->CreationTime.HighPart != 0 &&
  2214. UsersBuffer->CreationTime.LowPart != 0) {
  2215. Icb->Fcb->CreationTime = UsersBuffer->CreationTime;
  2216. Icb->Flags |= ICB_USER_SET_TIMES;
  2217. }
  2218. if (UsersBuffer->LastAccessTime.HighPart != 0 &&
  2219. UsersBuffer->LastAccessTime.LowPart != 0) {
  2220. Icb->Fcb->LastAccessTime = UsersBuffer->LastAccessTime;
  2221. Icb->Flags |= ICB_USER_SET_TIMES;
  2222. }
  2223. if (UsersBuffer->LastWriteTime.HighPart != 0 &&
  2224. UsersBuffer->LastWriteTime.LowPart != 0) {
  2225. Icb->Fcb->LastWriteTime = UsersBuffer->LastWriteTime;
  2226. Icb->Flags |= ICB_USER_SET_TIMES;
  2227. }
  2228. if (UsersBuffer->CreationTime.HighPart != 0 &&
  2229. UsersBuffer->CreationTime.LowPart != 0) {
  2230. Icb->Fcb->ChangeTime = UsersBuffer->ChangeTime;
  2231. Icb->Flags |= ICB_USER_SET_TIMES;
  2232. }
  2233. RdrReleaseFcbLock(Icb->Fcb);
  2234. }
  2235. }
  2236. return FALSE;
  2237. }
  2238. DBGSTATIC
  2239. BOOLEAN
  2240. SetRenameInfo (
  2241. IN PIRP Irp OPTIONAL,
  2242. IN PICB Icb,
  2243. OUT PFILE_RENAME_INFORMATION UsersBuffer,
  2244. IN ULONG BufferSize,
  2245. PNTSTATUS FinalStatus,
  2246. BOOLEAN Wait,
  2247. USHORT NtInformationLevel
  2248. )
  2249. /*++
  2250. Routine Description:
  2251. This routine implements the FileCopyOnWriteInformation,
  2252. FileMoveClusterInformation, FileLinkInformation and
  2253. FileRenameInformation info levels of the NtSetInformationFile api.
  2254. It returns the following information:
  2255. Arguments:
  2256. IN PICB Icb - Supplies the ICB associated with this request.
  2257. OUT PFILE_RENAME_INFORMATION UsersBuffer - Supplies the user's buffer
  2258. that is filled in with the
  2259. requested data.
  2260. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  2261. the amount of the buffer consumed is
  2262. subtracted from the initial size.
  2263. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2264. IN BOOLEAN Wait - True if FSP can wait for this request.
  2265. IN USHORT NtInformationLevel - Nt info level
  2266. Return Value:
  2267. BOOLEAN - True if request is to be processed in the FSP.
  2268. --*/
  2269. {
  2270. UNICODE_STRING NewFileName, RenameDestination;
  2271. PFCB Fcb = Icb->Fcb;
  2272. BOOLEAN FullyQualifiedPath = FALSE;
  2273. BOOLEAN PoolAllocatedForRenameDestination = FALSE;
  2274. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2275. PAGED_CODE();
  2276. NewFileName.Buffer = NULL;
  2277. //
  2278. // Force the request to be queued to the FSP right now to avoid our
  2279. // having to walk the connection database twice.
  2280. //
  2281. if (!Wait) {
  2282. return TRUE;
  2283. }
  2284. if (BufferSize < sizeof(FILE_RENAME_INFORMATION)) {
  2285. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  2286. return FALSE;
  2287. }
  2288. if (NtInformationLevel != FileRenameInformation &&
  2289. !(Fcb->Connection->Server->Capabilities & DF_NT_SMBS)) {
  2290. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  2291. return FALSE;
  2292. }
  2293. //
  2294. // Acquire the FCB lock to the source file for exclusive access to
  2295. // guarantee that no-one else is messing with the file.
  2296. //
  2297. RdrAcquireFcbLock(Fcb, ExclusiveLock, TRUE);
  2298. try {
  2299. // WARNING: Need NT support for rename functionality.
  2300. // if ( !(Fcb->Connection->Server->Capabilities & DF_NT_SMBS)
  2301. //
  2302. // ||
  2303. //
  2304. // !(Icb->Flags & ICB_HASHANDLE)
  2305. //
  2306. // ||
  2307. //
  2308. // ((IrpSp->Parameters.SetFile.FileObject != NULL) &&
  2309. // (!(((PICB)IrpSp->Parameters.SetFile.FileObject->FsContext2)->Flags & ICB_HASHANDLE) )
  2310. // )
  2311. //
  2312. // )
  2313. {
  2314. //
  2315. // Check to see whether this is a fully qualified RenameDestination or a simple
  2316. // rename within a directory.
  2317. //
  2318. if (IrpSp->Parameters.SetFile.FileObject != NULL) {
  2319. PFCB TargetFcb = NULL;
  2320. UNICODE_STRING TargetPath;
  2321. UNICODE_STRING LastComponent;
  2322. dprintf(DPRT_FILEINFO, ("SetRenameInformation: Fully qualified rename\n" ));
  2323. TargetFcb = IrpSp->Parameters.SetFile.FileObject->FsContext;
  2324. if (TargetFcb->Connection != Fcb->Connection) {
  2325. *FinalStatus = STATUS_NOT_SAME_DEVICE;
  2326. try_return(NOTHING);
  2327. }
  2328. //
  2329. // Disect the target path into two components, the file's path
  2330. // and the actual file name.
  2331. //
  2332. RdrExtractPathAndFileName(&IrpSp->Parameters.SetFile.FileObject->FileName, &TargetPath, &LastComponent);
  2333. RenameDestination.Buffer = ALLOCATE_POOL(PagedPool,
  2334. TargetFcb->FileName.MaximumLength + (USHORT )sizeof(WCHAR) + LastComponent.Length, POOL_RENAMEDEST);
  2335. if (RenameDestination.Buffer == NULL) {
  2336. try_return(*FinalStatus = STATUS_INSUFFICIENT_RESOURCES);
  2337. }
  2338. RenameDestination.MaximumLength = TargetFcb->FileName.MaximumLength + (USHORT )sizeof(WCHAR) + LastComponent.Length;
  2339. PoolAllocatedForRenameDestination = TRUE;
  2340. FullyQualifiedPath = TRUE;
  2341. //
  2342. // Build the rename destination name by concatinating the
  2343. // name of the FCB with the last component of the file name.
  2344. //
  2345. RtlCopyUnicodeString(&RenameDestination, &TargetFcb->FileName);
  2346. RtlAppendUnicodeToString(&RenameDestination, L"\\");
  2347. RtlAppendUnicodeStringToString(&RenameDestination, &LastComponent);
  2348. } else {
  2349. UNICODE_STRING LastComponent, FilePath;
  2350. //
  2351. // This is a relative rename operation, so treat it as such.
  2352. //
  2353. NewFileName.Length = (USHORT )UsersBuffer->FileNameLength;
  2354. NewFileName.Buffer = UsersBuffer->FileName;
  2355. if (NewFileName.Length == 0) {
  2356. *FinalStatus = STATUS_OBJECT_NAME_INVALID;
  2357. try_return(NOTHING);
  2358. }
  2359. //
  2360. // The user specified a path component. Check to make sure that
  2361. // the path component that the user specified is valid.
  2362. //
  2363. // If this is a LANMAN 2.0 server, use the NT canonicalization
  2364. // rules for determining name validity, otherwise use the
  2365. // DOS (8.3) file name rules.
  2366. //
  2367. if (!(Fcb->Connection->Server->Capabilities & DF_NT_SMBS)) {
  2368. OEM_STRING FileName;
  2369. *FinalStatus = RtlUnicodeStringToOemString(&FileName, &NewFileName, TRUE);
  2370. if (!NT_SUCCESS(*FinalStatus)) {
  2371. try_return(NOTHING);
  2372. }
  2373. if (Fcb->Connection->Server->Capabilities & DF_LANMAN20) {
  2374. if (!FsRtlIsHpfsDbcsLegal(FileName, FALSE, FALSE, FALSE)) {
  2375. *FinalStatus = STATUS_OBJECT_NAME_INVALID;
  2376. RtlFreeOemString(&FileName);
  2377. try_return(NOTHING);
  2378. }
  2379. } else {
  2380. if (!FsRtlIsFatDbcsLegal(FileName, FALSE, FALSE, FALSE)) {
  2381. *FinalStatus = STATUS_OBJECT_NAME_INVALID;
  2382. RtlFreeOemString(&FileName);
  2383. try_return(NOTHING);
  2384. }
  2385. }
  2386. RtlFreeOemString(&FileName);
  2387. }
  2388. //
  2389. // The target name is valid, figure out the fully qualified path
  2390. // to the destination.
  2391. //
  2392. //
  2393. // Initialize the path component to the entire source file name
  2394. // string.
  2395. //
  2396. FilePath = Fcb->FileName;
  2397. LastComponent.Length = LastComponent.MaximumLength = 0;
  2398. //
  2399. // Disect the source path into two components, the file's path
  2400. // and the actual file name.
  2401. //
  2402. RdrExtractPathAndFileName(&Fcb->FileName, &FilePath, &LastComponent);
  2403. //
  2404. // If the new file name matches the old file name, then we
  2405. // are done. Return success.
  2406. //
  2407. if (RtlEqualUnicodeString(&LastComponent, &NewFileName, TRUE)) {
  2408. *FinalStatus = STATUS_SUCCESS;
  2409. try_return(NOTHING);
  2410. }
  2411. RenameDestination.Buffer = ALLOCATE_POOL(PagedPool,
  2412. FilePath.Length + (USHORT )sizeof(WCHAR) + NewFileName.Length, POOL_RENAMEDEST);
  2413. RenameDestination.Length = RenameDestination.MaximumLength =
  2414. FilePath.Length + (USHORT )sizeof(WCHAR) + NewFileName.Length;
  2415. if (RenameDestination.Buffer == NULL) {
  2416. *FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  2417. try_return(NOTHING);
  2418. }
  2419. PoolAllocatedForRenameDestination = TRUE;
  2420. RtlCopyUnicodeString(&RenameDestination, &FilePath);
  2421. RtlAppendUnicodeToString(&RenameDestination, L"\\");
  2422. RtlAppendUnicodeStringToString(&RenameDestination, &NewFileName);
  2423. }
  2424. //
  2425. // RenameDestination contains the destination of the rename operation.
  2426. //
  2427. // Fcb->FileName contains the source of the rename operation.
  2428. //
  2429. dprintf(DPRT_FILEINFO, ("Rename %wZ to %wZ\n", &Fcb->FileName, &RenameDestination));
  2430. //
  2431. // We know we have enough quota to hold the new file name, attempt
  2432. // the rename operation.
  2433. //
  2434. //
  2435. // Purge this file from the cache, closing open instances.
  2436. //
  2437. if (Icb->Type == DiskFile) {
  2438. //
  2439. // Flush any write behind data from the cache for this file.
  2440. //
  2441. //RdrLog(( "rdflushb", &Icb->Fcb->FileName, 0 ));
  2442. *FinalStatus = RdrFlushCacheFile(Icb->Fcb);
  2443. //
  2444. // Purge the file from the cache.
  2445. //
  2446. //RdrLog(( "rdpurgeb", &Icb->Fcb->FileName, 0 ));
  2447. *FinalStatus = RdrPurgeCacheFile(Icb->Fcb);
  2448. }
  2449. //
  2450. // Force close the file.
  2451. //
  2452. // The SMB protocol sharing rules do not allow renaming open
  2453. // files, so we force close the file before renaming the
  2454. // old file to the new.
  2455. //
  2456. if (NtInformationLevel == FileRenameInformation &&
  2457. (Icb->Flags & ICB_HASHANDLE)) {
  2458. RdrCloseFile(Irp, Icb, IrpSp->FileObject, TRUE);
  2459. #if DBG
  2460. {
  2461. PLIST_ENTRY IcbEntry;
  2462. for (IcbEntry = Icb->Fcb->InstanceChain.Flink ;
  2463. IcbEntry != &Icb->Fcb->InstanceChain ;
  2464. IcbEntry = IcbEntry->Flink) {
  2465. PICB Icb2 = CONTAINING_RECORD(IcbEntry, ICB, InstanceNext);
  2466. if (Icb2->FileId == Icb->FileId) {
  2467. ASSERT (!(Icb2->Flags & ICB_HASHANDLE));
  2468. }
  2469. }
  2470. }
  2471. #endif
  2472. }
  2473. if (NtInformationLevel == FileRenameInformation &&
  2474. Fcb->NumberOfOpens != 1 &&
  2475. !(Fcb->Connection->Server->Capabilities & DF_NT_SMBS) ) {
  2476. *FinalStatus = STATUS_ACCESS_DENIED;
  2477. } else {
  2478. //
  2479. // If the user wanted us to delete this file, try the delete
  2480. // operation. If it fails, we ignore the error, since
  2481. // a better error will come from the RdrRenameFile request
  2482. // later on.
  2483. //
  2484. // To ease the load on the wire, if the user wanted us to
  2485. // replace the target, and the target doesn't exist, don't
  2486. // bother with the rename operation.
  2487. //
  2488. if (NtInformationLevel != FileMoveClusterInformation &&
  2489. IrpSp->Parameters.SetFile.ReplaceIfExists &&
  2490. !(Fcb->NonPagedFcb->Flags & FCB_DOESNTEXIST)) {
  2491. //
  2492. // Try to delete the destination of the rename operation.
  2493. //
  2494. //
  2495. *FinalStatus = RdrDeleteFile(Irp, &RenameDestination,
  2496. BooleanFlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE),
  2497. Icb->Fcb->Connection, Icb->Se);
  2498. #ifdef NOTIFY
  2499. if (NT_SUCCESS(*FinalStatus)) {
  2500. //
  2501. // Complete the report notify as appropriate.
  2502. //
  2503. FsRtlNotifyReportChange( Fcb->Connection->NotifySync,
  2504. &Fcb->Connection->DirNotifyList,
  2505. (PSTRING)&Icb->Fcb->FileName,
  2506. (PSTRING)&Icb->Fcb->LastFileName,
  2507. FILE_NOTIFY_CHANGE_ATTRIBUTES
  2508. | FILE_NOTIFY_CHANGE_SIZE
  2509. | FILE_NOTIFY_CHANGE_LAST_WRITE
  2510. | FILE_NOTIFY_CHANGE_LAST_ACCESS
  2511. | FILE_NOTIFY_CHANGE_CREATION
  2512. | FILE_NOTIFY_CHANGE_EA );
  2513. }
  2514. #endif
  2515. }
  2516. *FinalStatus = RdrRenameFile(
  2517. Irp,
  2518. Icb,
  2519. &Fcb->FileName,
  2520. &RenameDestination,
  2521. NtInformationLevel,
  2522. IrpSp->Parameters.SetFile.ClusterCount
  2523. );
  2524. #ifdef NOTIFY
  2525. if (NT_SUCCESS(*FinalStatus)) {
  2526. FsRtlNotifyReportChange( Fcb->Connection->NotifySync,
  2527. &Fcb->Connection->DirNotifyList,
  2528. (PSTRING)&Icb->Fcb->FileName,
  2529. (PSTRING)&Icb->Fcb->LastFileName,
  2530. NtInformationLevel == FileMoveClusterInformation?
  2531. FILE_NOTIFY_CHANGE_SIZE :
  2532. FILE_NOTIFY_CHANGE_NAME );
  2533. }
  2534. #endif
  2535. }
  2536. }
  2537. // else {
  2538. // //
  2539. // // Use TRANSACT2_SETFILEINFO to set FILE_RENAME_INFORMATION.
  2540. // //
  2541. //
  2542. // USHORT Setup[] = {TRANS2_SET_FILE_INFORMATION};
  2543. //
  2544. // REQ_SET_FILE_INFORMATION Parameters;
  2545. //
  2546. // CLONG OutParameterCount = sizeof(REQ_SET_FILE_INFORMATION);
  2547. //
  2548. // CLONG OutDataCount = 0;
  2549. //
  2550. // CLONG OutSetupCount = 0;
  2551. //
  2552. // UCHAR RenameBuffer[sizeof(FILE_RENAME_INFORMATION)+MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR)];
  2553. //
  2554. // PFILE_RENAME_INFORMATION RenameInfo = (PFILE_RENAME_INFORMATION)RenameBuffer;
  2555. //
  2556. // DbgBreakPoint();
  2557. //
  2558. // SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_SET_FILE_RENAME_INFO);
  2559. //
  2560. // SmbPutAlignedUshort(&Parameters.Fid, Icb->FileId);
  2561. //
  2562. // if (BufferSize > sizeof(RenameBuffer)) {
  2563. // try_return(*FinalStatus = STATUS_INSUFFICIENT_RESOURCES);
  2564. // }
  2565. //
  2566. // RtlCopyMemory(RenameBuffer, UsersBuffer, BufferSize);
  2567. //
  2568. // if (IrpSp->Parameters.SetFile.FileObject != NULL) {
  2569. // RenameInfo->RootDirectory = (HANDLE)((PICB)IrpSp->Parameters.SetFile.FileObject->FsContext2)->FileId;
  2570. // }
  2571. //
  2572. // RenameInfo->ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
  2573. //
  2574. // *FinalStatus = RdrTransact(Irp, // Irp,
  2575. // Icb->Fcb->Connection,
  2576. // Icb->Se,
  2577. // Setup,
  2578. // (CLONG) sizeof(Setup), // InSetupCount,
  2579. // &OutSetupCount,
  2580. // NULL, // Name,
  2581. // &Parameters,
  2582. // sizeof(Parameters), // InParameterCount,
  2583. // &OutParameterCount,
  2584. // RenameInfo, // InData,
  2585. // BufferSize, // InDataCount,
  2586. // NULL, // OutData,
  2587. // &OutDataCount, // OutDataCount
  2588. // &Icb->FileId, // Fid
  2589. // 0, // Timeout
  2590. // 0, // Flags
  2591. // 0, // NtTransact function
  2592. // NULL,
  2593. // NULL
  2594. // );
  2595. // }
  2596. //
  2597. if (NT_SUCCESS(*FinalStatus) &&
  2598. NtInformationLevel == FileRenameInformation) {
  2599. //
  2600. // The rename operation succeeded.
  2601. //
  2602. //
  2603. // We don't update the file name in the FCB because no further
  2604. // operations can be performed on the file.
  2605. //
  2606. Icb->Flags |= ICB_RENAMED;
  2607. }
  2608. try_exit: NOTHING;
  2609. } finally {
  2610. if (PoolAllocatedForRenameDestination) {
  2611. FREE_POOL(RenameDestination.Buffer);
  2612. }
  2613. RdrReleaseFcbLock(Fcb);
  2614. }
  2615. return FALSE;
  2616. }
  2617. DBGSTATIC
  2618. BOOLEAN
  2619. SetDispositionInfo (
  2620. IN PICB Icb,
  2621. OUT PFILE_DISPOSITION_INFORMATION UsersBuffer,
  2622. IN ULONG BufferSize,
  2623. IN PIRP Irp,
  2624. OUT PNTSTATUS FinalStatus,
  2625. IN BOOLEAN Wait
  2626. )
  2627. /*++
  2628. Routine Description:
  2629. This routine implements the FileSetDispositionInformation value of the
  2630. NtSetInformationFile api. It returns the following information:
  2631. Arguments:
  2632. IN PICB Icb - Supplies the ICB associated with this request.
  2633. OUT PFILE_DISPOSITION_INFORMATION UsersBuffer - Supplies the user's buffer
  2634. that is filled in with the
  2635. requested data.
  2636. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  2637. the amount of the buffer consumed is
  2638. subtracted from the initial size.
  2639. IN PIRP Irp - Irp that generated this request.
  2640. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2641. IN BOOLEAN Wait - True if FSP can wait for this request.
  2642. Return Value:
  2643. BOOLEAN - True if request is to be processed in the FSP.
  2644. --*/
  2645. {
  2646. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  2647. PFCB Fcb = Icb->Fcb;
  2648. PAGED_CODE();
  2649. dprintf(DPRT_FILEINFO, ("SetDispositionInformation, file %wZ\n", &Icb->Fcb->FileName));
  2650. if (BufferSize < sizeof(FILE_DISPOSITION_INFORMATION)) {
  2651. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  2652. return FALSE;
  2653. }
  2654. //
  2655. // We can only delete files or directories.
  2656. //
  2657. if (Icb->Type == PrinterFile || Icb->Type == NamedPipe ||
  2658. Icb->Type == Com) {
  2659. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  2660. return FALSE;
  2661. }
  2662. //
  2663. // Always process SetDisposition requests in the FSP if we can't block.
  2664. //
  2665. if (UsersBuffer->DeleteFile) {
  2666. BOOLEAN DeleteDirectory = (BOOLEAN)(Icb->Type == Directory);
  2667. if (!Wait) {
  2668. return TRUE;
  2669. }
  2670. //
  2671. // Gain exclusive access to the FCB.
  2672. //
  2673. RdrAcquireFcbLock(Fcb, ExclusiveLock, TRUE);
  2674. //
  2675. // If this file doesn't exist, then we're done now - this is simply
  2676. // a NOP.
  2677. //
  2678. if (Fcb->NonPagedFcb->Flags & FCB_DOESNTEXIST) {
  2679. #ifdef NOTIFY
  2680. FsRtlNotifyReportChange( Fcb->Connection->NotifySync,
  2681. &Fcb->Connection->DirNotifyList,
  2682. (PSTRING)&Fcb->FileName,
  2683. (PSTRING)&Fcb->LastFileName,
  2684. FILE_NOTIFY_CHANGE_NAME );
  2685. #endif
  2686. //
  2687. // Set the bitsy pieces to indicate that this file has been
  2688. // deleted.
  2689. //
  2690. IrpSp->FileObject->DeletePending = TRUE;
  2691. Icb->Flags |= ICB_DELETE_PENDING;
  2692. *FinalStatus = STATUS_SUCCESS;
  2693. RdrReleaseFcbLock(Fcb);
  2694. return FALSE;
  2695. }
  2696. //
  2697. // If this is a non NT server, or there is no valid file id for this file,
  2698. // use the Lanman SMB delete for this file.
  2699. //
  2700. if (!(Fcb->Connection->Server->Capabilities & DF_NT_SMBS)
  2701. ||
  2702. !(Icb->Flags & ICB_HASHANDLE)) {
  2703. if (Icb->Type == FileOrDirectory) {
  2704. ULONG FileAttributes;
  2705. BOOLEAN IsDirectory;
  2706. *FinalStatus = RdrDoesFileExist(Irp,
  2707. &Icb->Fcb->FileName,
  2708. Icb->Fcb->Connection,
  2709. Icb->Se,
  2710. BooleanFlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE),
  2711. &FileAttributes,
  2712. &IsDirectory,
  2713. NULL);
  2714. if (!NT_SUCCESS(*FinalStatus)) {
  2715. RdrReleaseFcbLock(Fcb);
  2716. return FALSE;
  2717. }
  2718. if (IsDirectory) {
  2719. DeleteDirectory = TRUE;
  2720. }
  2721. }
  2722. //
  2723. // Purge this file from the cache, closing open instances.
  2724. //
  2725. if (Icb->Type == DiskFile) {
  2726. //
  2727. // Flush any write behind data from the cache for this file.
  2728. //
  2729. //RdrLog(( "rdflushc", &Icb->Fcb->FileName, 0 ));
  2730. *FinalStatus = RdrFlushCacheFile(Icb->Fcb);
  2731. //
  2732. // Purge the file from the cache.
  2733. //
  2734. //RdrLog(( "rdpurgec", &Icb->Fcb->FileName, 0 ));
  2735. *FinalStatus = RdrPurgeCacheFile(Icb->Fcb);
  2736. }
  2737. if (Icb->Flags & ICB_HASHANDLE) {
  2738. RdrCloseFile(Irp, Icb, IrpSp->FileObject, TRUE);
  2739. #if DBG
  2740. {
  2741. PLIST_ENTRY IcbEntry;
  2742. for (IcbEntry = Icb->Fcb->InstanceChain.Flink ;
  2743. IcbEntry != &Icb->Fcb->InstanceChain ;
  2744. IcbEntry = IcbEntry->Flink) {
  2745. PICB Icb2 = CONTAINING_RECORD(IcbEntry, ICB, InstanceNext);
  2746. if (Icb2->FileId == Icb->FileId) {
  2747. ASSERT (!(Icb2->Flags & ICB_HASHANDLE));
  2748. }
  2749. }
  2750. }
  2751. #endif
  2752. }
  2753. //
  2754. // If there are other openers of this file left, and it is an old server,
  2755. // deny the user's request.
  2756. //
  2757. if (Fcb->NumberOfOpens != 1 &&
  2758. !(Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) ) {
  2759. *FinalStatus = STATUS_SHARING_VIOLATION;
  2760. //
  2761. // Release the FCB lock to allow potential oplock breaks
  2762. // from coming through.
  2763. //
  2764. RdrReleaseFcbLock(Fcb);
  2765. } else {
  2766. //
  2767. // If the delete succeeded, mark the file object as being
  2768. // deleted, otherwise it didn't actually get deleted.
  2769. //
  2770. IrpSp->FileObject->DeletePending = TRUE;
  2771. Icb->Flags |= ICB_DELETE_PENDING;
  2772. //
  2773. // Release the FCB lock to allow potential oplock breaks
  2774. // to come through.
  2775. //
  2776. RdrReleaseFcbLock(Fcb);
  2777. //
  2778. // Issue the delete/rmdir request to the remote server and
  2779. // check the status of the response. If it was successful
  2780. // we can mark the file as being deleted.
  2781. //
  2782. if ( !DeleteDirectory ) {
  2783. //
  2784. // Try to delete the file.
  2785. //
  2786. *FinalStatus = RdrDeleteFile(Irp, &Fcb->FileName,
  2787. BooleanFlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE),
  2788. Icb->Fcb->Connection, Icb->Se);
  2789. } else {
  2790. //
  2791. // Try to delete the directory.
  2792. //
  2793. *FinalStatus = RdrGenericPathSmb(Irp,
  2794. SMB_COM_DELETE_DIRECTORY,
  2795. BooleanFlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE),
  2796. &Fcb->FileName,
  2797. Fcb->Connection,
  2798. Icb->Se);
  2799. }
  2800. if (!NT_SUCCESS(*FinalStatus)) {
  2801. RdrAcquireFcbLock(Fcb, ExclusiveLock, TRUE);
  2802. IrpSp->FileObject->DeletePending = FALSE;
  2803. Icb->Flags &= ~ICB_DELETE_PENDING;
  2804. RdrReleaseFcbLock(Fcb);
  2805. #ifdef NOTIFY
  2806. } else {
  2807. FsRtlNotifyReportChange( Fcb->Connection->NotifySync,
  2808. &Fcb->Connection->DirNotifyList,
  2809. (PSTRING)&Fcb->FileName,
  2810. (PSTRING)&Fcb->LastFileName,
  2811. FILE_NOTIFY_CHANGE_NAME );
  2812. #endif
  2813. }
  2814. }
  2815. } else {
  2816. //
  2817. // Use TRANSACT2_SETFILEINFO to set FILE_DISPOSITION_INFORMATION.
  2818. //
  2819. USHORT Setup[] = {TRANS2_SET_FILE_INFORMATION};
  2820. REQ_SET_FILE_INFORMATION Parameters;
  2821. CLONG OutParameterCount = sizeof(REQ_SET_FILE_INFORMATION);
  2822. CLONG OutDataCount = 0;
  2823. CLONG OutSetupCount = 0;
  2824. //
  2825. // If the delete succeeded, mark the file object as being
  2826. // deleted, otherwise it didn't actually get deleted.
  2827. //
  2828. IrpSp->FileObject->DeletePending = TRUE;
  2829. Icb->Flags |= ICB_DELETE_PENDING;
  2830. //
  2831. // Blow the file out of the cache. Don't worry about the data,
  2832. // since we're going to be deleting the file.
  2833. //
  2834. if (Icb->Type == DiskFile) {
  2835. //RdrLog(( "rdpurged", &Icb->Fcb->FileName, 0 ));
  2836. *FinalStatus = RdrPurgeCacheFile(Icb->Fcb);
  2837. }
  2838. RdrReleaseFcbLock(Fcb);
  2839. SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_SET_FILE_DISPOSITION_INFO);
  2840. SmbPutAlignedUshort(&Parameters.Fid, Icb->FileId);
  2841. *FinalStatus = RdrTransact(Irp, // Irp,
  2842. Fcb->Connection,
  2843. Icb->Se,
  2844. Setup,
  2845. (CLONG) sizeof(Setup), // InSetupCount,
  2846. &OutSetupCount,
  2847. NULL, // Name,
  2848. &Parameters,
  2849. sizeof(Parameters), // InParameterCount,
  2850. &OutParameterCount,
  2851. UsersBuffer, // InData,
  2852. BufferSize, // InDataCount,
  2853. NULL, // OutData,
  2854. &OutDataCount, // OutDataCount
  2855. &Icb->FileId, // Fid
  2856. 0, // Timeout
  2857. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  2858. 0, // NtTransact function
  2859. NULL,
  2860. NULL
  2861. );
  2862. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  2863. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  2864. }
  2865. if (NT_SUCCESS(*FinalStatus)) {
  2866. #ifdef NOTIFY
  2867. FsRtlNotifyReportChange( Fcb->Connection->NotifySync,
  2868. &Fcb->Connection->DirNotifyList,
  2869. (PSTRING)&Fcb->FileName,
  2870. (PSTRING)&Fcb->LastFileName,
  2871. FILE_NOTIFY_CHANGE_NAME );
  2872. #endif
  2873. } else {
  2874. RdrAcquireFcbLock(Fcb, ExclusiveLock, TRUE);
  2875. IrpSp->FileObject->DeletePending = FALSE;
  2876. Icb->Flags &= ~ICB_DELETE_PENDING;
  2877. RdrReleaseFcbLock(Fcb);
  2878. }
  2879. }
  2880. } else {
  2881. *FinalStatus = STATUS_SUCCESS;
  2882. }
  2883. return FALSE;
  2884. }
  2885. DBGSTATIC
  2886. BOOLEAN
  2887. SetPositionInfo (
  2888. IN PICB Icb,
  2889. IN PIO_STACK_LOCATION IrpSp,
  2890. OUT PFILE_POSITION_INFORMATION UsersBuffer,
  2891. IN ULONG BufferSize,
  2892. PNTSTATUS FinalStatus,
  2893. BOOLEAN Wait
  2894. )
  2895. /*++
  2896. Routine Description:
  2897. This routine implements the FileSetPositionInformation value of the
  2898. NtSetInformationFile api. It returns the following information:
  2899. Arguments:
  2900. IN PICB Icb - Supplies the ICB associated with this request.
  2901. OUT PFILE_POSITION_INFORMATION UsersBuffer - Supplies the user's buffer
  2902. that is filled in with the
  2903. requested data.
  2904. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  2905. the amount of the buffer consumed is
  2906. subtracted from the initial size.
  2907. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2908. IN BOOLEAN Wait - True if FSP can wait for this request.
  2909. Return Value:
  2910. BOOLEAN - True if request is to be processed in the FSP.
  2911. --*/
  2912. {
  2913. PAGED_CODE();
  2914. if (BufferSize < sizeof(FILE_POSITION_INFORMATION)) {
  2915. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  2916. } else {
  2917. if (Icb->Flags & ICB_PSEUDOOPENED) {
  2918. *FinalStatus = STATUS_ACCESS_DENIED;
  2919. return FALSE;
  2920. }
  2921. // dprintf(DPRT_FILEINFO, ("Set current byte offset on file %lx to %lx%lx\n", IrpSp->FileObject, UsersBuffer->CurrentByteOffset.HighPart, UsersBuffer->CurrentByteOffset.LowPart));
  2922. IrpSp->FileObject->CurrentByteOffset = UsersBuffer->CurrentByteOffset;
  2923. *FinalStatus = STATUS_SUCCESS;
  2924. }
  2925. return FALSE;
  2926. UNREFERENCED_PARAMETER(Wait);
  2927. }
  2928. DBGSTATIC
  2929. BOOLEAN
  2930. SetAllocationInfo (
  2931. IN PIRP Irp,
  2932. IN PICB Icb,
  2933. OUT PFILE_ALLOCATION_INFORMATION UsersBuffer,
  2934. IN ULONG BufferSize,
  2935. PNTSTATUS FinalStatus,
  2936. BOOLEAN Wait
  2937. )
  2938. /*++
  2939. Routine Description:
  2940. This routine implements the FileSetAllocationInformation value of the
  2941. NtSetInformationFile api. It returns the following information:
  2942. Arguments:
  2943. IN PIRP Irp - Supplies an I/O request packet for the request.
  2944. IN PICB Icb - Supplies the ICB associated with this request.
  2945. OUT PFILE_ALLOCATION_INFORMATION UsersBuffer - Supplies the user's buffer
  2946. that is filled in with the
  2947. requested data.
  2948. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  2949. the amount of the buffer consumed is
  2950. subtracted from the initial size.
  2951. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  2952. IN BOOLEAN Wait - True if FSP can wait for this request.
  2953. Return Value:
  2954. BOOLEAN - True if request is to be processed in the FSP.
  2955. --*/
  2956. {
  2957. BOOLEAN RetValue = FALSE;
  2958. BOOLEAN Truncated = FALSE;
  2959. PAGED_CODE();
  2960. if (Icb->Type != DiskFile) {
  2961. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  2962. } else if (BufferSize < sizeof(FILE_ALLOCATION_INFORMATION)) {
  2963. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  2964. } else {
  2965. //
  2966. // Prevent other people from messing with the file.
  2967. //
  2968. RdrAcquireFcbLock(Icb->Fcb, ExclusiveLock, TRUE);
  2969. try {
  2970. if (!(Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) ||
  2971. !(Icb->Flags & ICB_HASHANDLE)) {
  2972. LARGE_INTEGER FileSize;
  2973. // dprintf(DPRT_FILEINFO, ("Set allocation info on file %lx (%wZ) to %lx%lx\n", IoGetCurrentIrpStackLocation(Irp)->FileObject, Icb->Fcb->FileName, UsersBuffer->AllocationSize.HighPart, UsersBuffer->AllocationSize.LowPart));
  2974. //
  2975. // If the file was pseudo-opened, this is an invalid operation.
  2976. //
  2977. if (Icb->Flags & ICB_PSEUDOOPENED) {
  2978. *FinalStatus = STATUS_ACCESS_DENIED;
  2979. try_return(RetValue = FALSE);
  2980. }
  2981. //
  2982. // Check to see what the user is trying to set as the new
  2983. // allocation for this size. We cannot set the file allocation
  2984. // information independently of the file size
  2985. //
  2986. // If the user is trying to extend the file, we ignore the
  2987. // request and return success, if he is trying to truncate
  2988. // the file, truncate it to the new value.
  2989. if (!Wait) {
  2990. try_return(RetValue = TRUE);
  2991. }
  2992. //
  2993. // Wait for writebehind operations to complete.
  2994. //
  2995. RdrWaitForWriteBehindOperation(Icb);
  2996. //
  2997. // First find out what the file's size is.
  2998. //
  2999. if (RdrCanFileBeBuffered(Icb)) {
  3000. //
  3001. // If the file is exclusive, we can rely on the
  3002. // file size cached in the FCB.
  3003. //
  3004. FileSize = Icb->Fcb->Header.FileSize;
  3005. } else {
  3006. *FinalStatus = RdrQueryEndOfFile(Irp, Icb, &FileSize);
  3007. if (!NT_SUCCESS(*FinalStatus)) {
  3008. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  3009. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  3010. }
  3011. try_return( RetValue = FALSE );
  3012. }
  3013. }
  3014. //
  3015. // Now see if the file is being extended or truncated.
  3016. //
  3017. // If the file is being extended, ignore this request,
  3018. // If the file is being truncated, truncate the file.
  3019. //
  3020. if (UsersBuffer->AllocationSize.QuadPart <
  3021. FileSize.QuadPart) {
  3022. *FinalStatus = RdrSetEndOfFile(Irp, Icb,
  3023. UsersBuffer->AllocationSize);
  3024. if (!NT_SUCCESS(*FinalStatus)) {
  3025. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  3026. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  3027. }
  3028. try_return ( RetValue = FALSE );
  3029. }
  3030. Icb->Fcb->Header.FileSize = UsersBuffer->AllocationSize;
  3031. if (Icb->Fcb->Header.FileSize.QuadPart >
  3032. Icb->Fcb->Header.AllocationSize.QuadPart) {
  3033. Icb->Fcb->Header.AllocationSize = Icb->Fcb->Header.FileSize;
  3034. }
  3035. Truncated = TRUE;
  3036. } else {
  3037. //
  3038. // The new allocation is larger than the file's size,
  3039. // return success always (ignore the api).
  3040. //
  3041. *FinalStatus = STATUS_SUCCESS;
  3042. }
  3043. } else {
  3044. //
  3045. // Use TRANSACT2_SETFILEINFO to set FILE_ALLOCATION_INFORMATION.
  3046. //
  3047. USHORT Setup[] = {TRANS2_SET_FILE_INFORMATION};
  3048. REQ_SET_FILE_INFORMATION Parameters;
  3049. CLONG OutParameterCount = sizeof(REQ_SET_FILE_INFORMATION);
  3050. CLONG OutDataCount = 0;
  3051. CLONG OutSetupCount = 0;
  3052. if (!Wait) {
  3053. try_return(RetValue = TRUE);
  3054. }
  3055. //
  3056. // Wait for writebehind operations to complete.
  3057. //
  3058. RdrWaitForWriteBehindOperation(Icb);
  3059. SmbPutAlignedUshort(&Parameters.InformationLevel, SMB_SET_FILE_ALLOCATION_INFO);
  3060. SmbPutAlignedUshort(&Parameters.Fid, Icb->FileId);
  3061. *FinalStatus = RdrTransact(Irp, // Irp,
  3062. Icb->Fcb->Connection,
  3063. Icb->Se,
  3064. Setup,
  3065. (CLONG) sizeof(Setup), // InSetupCount,
  3066. &OutSetupCount,
  3067. NULL, // Name,
  3068. &Parameters,
  3069. sizeof(Parameters), // InParameterCount,
  3070. &OutParameterCount,
  3071. UsersBuffer, // InData,
  3072. BufferSize, // InDataCount,
  3073. NULL, // OutData,
  3074. &OutDataCount, // OutDataCount
  3075. &Icb->FileId, // Fid
  3076. 0, // Timeout
  3077. (USHORT) (FlagOn(Icb->NonPagedFcb->Flags, FCB_DFSFILE) ? SMB_TRANSACTION_DFSFILE : 0),
  3078. 0, // NtTransact function
  3079. NULL,
  3080. NULL
  3081. );
  3082. if (NT_SUCCESS(*FinalStatus)) {
  3083. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  3084. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  3085. }
  3086. if (UsersBuffer->AllocationSize.QuadPart <
  3087. Icb->Fcb->Header.AllocationSize.QuadPart) {
  3088. Truncated = TRUE;
  3089. }
  3090. Icb->Fcb->Header.AllocationSize = UsersBuffer->AllocationSize;
  3091. }
  3092. }
  3093. try_exit: NOTHING;
  3094. } finally {
  3095. if ( Truncated ) {
  3096. CC_FILE_SIZES FileSizes =*((PCC_FILE_SIZES)&Icb->Fcb->Header.AllocationSize);
  3097. #ifdef NOTIFY
  3098. FsRtlNotifyReportChange( Icb->Fcb->Connection->NotifySync,
  3099. &Icb->Fcb->Connection->DirNotifyList,
  3100. (PSTRING)&Icb->Fcb->FileName,
  3101. (PSTRING)&Icb->Fcb->LastFileName,
  3102. FILE_NOTIFY_CHANGE_SIZE );
  3103. #endif
  3104. RdrTruncateLockHeadForFcb(Icb->Fcb);
  3105. RdrTruncateWriteBufferForFcb(Icb->Fcb);
  3106. CcSetFileSizes(IoGetCurrentIrpStackLocation(Irp)->FileObject,
  3107. &FileSizes);
  3108. }
  3109. RdrReleaseFcbLock(Icb->Fcb);
  3110. }
  3111. }
  3112. return RetValue;
  3113. }
  3114. DBGSTATIC
  3115. BOOLEAN
  3116. SetEndOfFileInfo (
  3117. IN PIRP Irp,
  3118. IN PICB Icb,
  3119. OUT PFILE_END_OF_FILE_INFORMATION UsersBuffer,
  3120. IN ULONG BufferSize,
  3121. PNTSTATUS FinalStatus,
  3122. BOOLEAN Wait
  3123. )
  3124. /*++
  3125. Routine Description:
  3126. This routine implements the FileSetEndOfFileInformation value of the
  3127. NtSetInformationFile api. It returns the following information:
  3128. Arguments:
  3129. IN PICB Icb - Supplies the ICB associated with this request.
  3130. OUT PFILE_END_OF_FILE_INFORMATION UsersBuffer - Supplies the user's buffer
  3131. that is filled in with the
  3132. requested data.
  3133. IN ULONG BufferSize - Supplies the size of the buffer. On return,
  3134. the amount of the buffer consumed is
  3135. subtracted from the initial size.
  3136. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  3137. IN BOOLEAN Wait - True if FSP can wait for this request.
  3138. Return Value:
  3139. BOOLEAN - True if request is to be processed in the FSP.
  3140. --*/
  3141. {
  3142. BOOLEAN RetValue = FALSE;
  3143. BOOLEAN Truncated = FALSE;
  3144. PAGED_CODE();
  3145. if (Icb->Type != DiskFile) {
  3146. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  3147. return FALSE;
  3148. }
  3149. if (BufferSize < sizeof(FILE_END_OF_FILE_INFORMATION)) {
  3150. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  3151. return FALSE;
  3152. }
  3153. //
  3154. // If IrpSp->Parameters.SetFile->AdvanceOnly is set, this is an
  3155. // indication that this is from the cache manager and should be
  3156. // used to update valid data length.
  3157. //
  3158. if (IoGetCurrentIrpStackLocation(Irp)->Parameters.SetFile.AdvanceOnly) {
  3159. *FinalStatus = STATUS_SUCCESS;
  3160. return FALSE;
  3161. }
  3162. //
  3163. // If the file was pseudo-opened, this is an invalid operation.
  3164. //
  3165. if (Icb->Flags & ICB_PSEUDOOPENED) {
  3166. *FinalStatus = STATUS_ACCESS_DENIED;
  3167. return FALSE;
  3168. }
  3169. RdrAcquireFcbLock(Icb->Fcb, ExclusiveLock, TRUE);
  3170. ExAcquireResourceExclusive(Icb->Fcb->Header.PagingIoResource, TRUE);
  3171. try {
  3172. //
  3173. // If this is not an NT server, or it doesn't have a handle...
  3174. //
  3175. // dprintf(DPRT_FILEINFO, ("Set end of file info on file %lx (%wZ) to %lx%lx\n", IoGetCurrentIrpStackLocation(Irp), Icb->Fcb->FileName, UsersBuffer->EndOfFile.HighPart, UsersBuffer->EndOfFile.LowPart));
  3176. if (!(Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) &&
  3177. (UsersBuffer->EndOfFile.HighPart != 0)) {
  3178. *FinalStatus = STATUS_INVALID_PARAMETER;
  3179. try_return(RetValue = FALSE);
  3180. }
  3181. if (!Wait) {
  3182. try_return(RetValue = TRUE);
  3183. }
  3184. //
  3185. // Wait for writebehind operations to complete.
  3186. //
  3187. RdrWaitForWriteBehindOperation(Icb);
  3188. //
  3189. // We know that the end of file is within the legal bounds
  3190. // for the SMB protocol. Set the end of file for the current
  3191. // file.
  3192. //
  3193. *FinalStatus = RdrSetEndOfFile(Irp, Icb, UsersBuffer->EndOfFile);
  3194. if (!NT_SUCCESS(*FinalStatus)) {
  3195. if (*FinalStatus == STATUS_INVALID_HANDLE) {
  3196. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  3197. }
  3198. try_return(RetValue = FALSE);
  3199. }
  3200. Truncated = TRUE;
  3201. Icb->Fcb->Header.FileSize = UsersBuffer->EndOfFile;
  3202. if (Icb->Fcb->Header.FileSize.QuadPart > Icb->Fcb->Header.AllocationSize.QuadPart) {
  3203. Icb->Fcb->Header.AllocationSize = Icb->Fcb->Header.FileSize;
  3204. }
  3205. //
  3206. // If this is a core server, then he might have extended the file
  3207. // but returned no error due to running out of disk space. We
  3208. // want to make sure that the right thing happened.
  3209. //
  3210. if (!(Icb->Fcb->Connection->Server->Capabilities & DF_LANMAN10)) {
  3211. LARGE_INTEGER TrueFileSize;
  3212. NTSTATUS Status;
  3213. //
  3214. // If the setting of the end of file succeeded, we need
  3215. // to determine what the true end of file is. We do
  3216. // this because it is possible that the attempt to set
  3217. // the end of file might have failed to set the end of
  3218. // file to the actual amount we requested. We issue an
  3219. // LSEEK SMB to find out how large the file is.
  3220. //
  3221. Status = RdrQueryEndOfFile(Irp, Icb, &TrueFileSize);
  3222. if (!NT_SUCCESS(Status)) {
  3223. if (Status == STATUS_INVALID_HANDLE) {
  3224. RdrInvalidateFileId(Icb->NonPagedFcb, Icb->FileId);
  3225. }
  3226. *FinalStatus = Status;
  3227. try_return(RetValue = FALSE);
  3228. }
  3229. if (TrueFileSize.QuadPart < UsersBuffer->EndOfFile.QuadPart) {
  3230. *FinalStatus = STATUS_DISK_FULL;
  3231. try_return(RetValue = FALSE);
  3232. }
  3233. }
  3234. try_exit: NOTHING;
  3235. } finally {
  3236. if ( Truncated ) {
  3237. CC_FILE_SIZES FileSizes =*((PCC_FILE_SIZES)&Icb->Fcb->Header.AllocationSize);
  3238. #ifdef NOTIFY
  3239. FsRtlNotifyReportChange( Icb->Fcb->Connection->NotifySync,
  3240. &Icb->Fcb->Connection->DirNotifyList,
  3241. (PSTRING)&Icb->Fcb->FileName,
  3242. (PSTRING)&Icb->Fcb->LastFileName,
  3243. FILE_NOTIFY_CHANGE_SIZE );
  3244. #endif
  3245. RdrTruncateLockHeadForFcb(Icb->Fcb);
  3246. RdrTruncateWriteBufferForFcb(Icb->Fcb);
  3247. CcSetFileSizes(IoGetCurrentIrpStackLocation(Irp)->FileObject,
  3248. &FileSizes);
  3249. }
  3250. ExReleaseResource(Icb->Fcb->Header.PagingIoResource);
  3251. RdrReleaseFcbLock(Icb->Fcb);
  3252. }
  3253. return RetValue;
  3254. }
  3255. DBGSTATIC
  3256. BOOLEAN
  3257. SetGenericInfo(
  3258. IN PIRP Irp,
  3259. PICB Icb,
  3260. VOID *pvUsersBuffer,
  3261. ULONG cbBuffer,
  3262. ULONG cbMin,
  3263. USHORT NtInformationLevel,
  3264. PNTSTATUS FinalStatus,
  3265. BOOLEAN Wait)
  3266. /*++
  3267. Routine Description:
  3268. This routine implements the extended portions of the NtSetInformationFile
  3269. api for Cairo. It returns the following information:
  3270. Arguments:
  3271. IN PICB Icb - Supplies the ICB associated with this request.
  3272. OUT VOID *pvUsersBuffer - Supplies the user's buffer
  3273. that is filled in with the
  3274. requested data.
  3275. IN ULONG cbBuffer - Supplies the size of the buffer. On return,
  3276. the amount of the buffer consumed is
  3277. subtracted from the initial size.
  3278. IN ULONG cbMin - Supplies the minimum required size of the buffer.
  3279. OUT PNTSTATUS FinalStatus - Status to be returned for this operation.
  3280. IN BOOLEAN Wait - True if FSP can wait for this request.
  3281. Return Value:
  3282. BOOLEAN - True if request is to be processed in the FSP.
  3283. --*/
  3284. {
  3285. PAGED_CODE();
  3286. if (Icb->Type != DiskFile && Icb->Type != Directory) {
  3287. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  3288. return(FALSE);
  3289. }
  3290. if (cbBuffer < cbMin) {
  3291. *FinalStatus = STATUS_BUFFER_TOO_SMALL;
  3292. return(FALSE);
  3293. }
  3294. if (!Wait) {
  3295. return(TRUE);
  3296. }
  3297. //
  3298. // Prevent other people from messing with the file.
  3299. //
  3300. RdrAcquireFcbLock(Icb->Fcb, ExclusiveLock, TRUE);
  3301. if ((Icb->Fcb->Connection->Server->Capabilities & DF_NT_SMBS) == 0) {
  3302. *FinalStatus = STATUS_INVALID_DEVICE_REQUEST;
  3303. } else if ((Icb->Flags & ICB_HASHANDLE) == 0) {
  3304. *FinalStatus = STATUS_INVALID_HANDLE;
  3305. } else {
  3306. *FinalStatus = RdrSetGeneric(
  3307. Irp,
  3308. Icb,
  3309. NtInformationLevel,
  3310. cbBuffer,
  3311. pvUsersBuffer);
  3312. }
  3313. RdrReleaseFcbLock(Icb->Fcb);
  3314. return(FALSE);
  3315. }