Leaked source code of windows server 2003
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.

3072 lines
81 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. fileinfo.c
  5. Abstract:
  6. This module implements the get / set file information routines for
  7. Netware Redirector.
  8. Author:
  9. Manny Weiser (mannyw) 4-Mar-1993
  10. Revision History:
  11. --*/
  12. #include "procs.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_FILEINFO)
  17. //
  18. // local procedure prototypes
  19. //
  20. NTSTATUS
  21. NwCommonQueryInformation (
  22. IN PIRP_CONTEXT pIrpContext
  23. );
  24. NTSTATUS
  25. NwCommonSetInformation (
  26. IN PIRP_CONTEXT pIrpContet
  27. );
  28. NTSTATUS
  29. NwQueryBasicInfo (
  30. IN PIRP_CONTEXT IrpContext,
  31. IN PICB Icb,
  32. IN PFILE_BASIC_INFORMATION Buffer
  33. );
  34. NTSTATUS
  35. NwQueryStandardInfo (
  36. IN PIRP_CONTEXT IrpContext,
  37. IN PICB Icb,
  38. IN PFILE_STANDARD_INFORMATION Buffer
  39. );
  40. NTSTATUS
  41. NwQueryInternalInfo (
  42. IN PIRP_CONTEXT IrpContext,
  43. IN PICB Icb,
  44. IN PFILE_INTERNAL_INFORMATION Buffer
  45. );
  46. NTSTATUS
  47. NwQueryEaInfo (
  48. IN PIRP_CONTEXT IrpContext,
  49. IN PFILE_EA_INFORMATION Buffer
  50. );
  51. NTSTATUS
  52. NwQueryNameInfo (
  53. IN PIRP_CONTEXT IrpContext,
  54. IN PICB Icb,
  55. IN PFILE_NAME_INFORMATION Buffer,
  56. IN OUT PULONG Length
  57. );
  58. NTSTATUS
  59. NwQueryAltNameInfo (
  60. IN PIRP_CONTEXT IrpContext,
  61. IN PICB Icb,
  62. IN PFILE_NAME_INFORMATION Buffer,
  63. IN OUT PULONG Length
  64. );
  65. NTSTATUS
  66. NwQueryPositionInfo (
  67. IN PIRP_CONTEXT IrpContext,
  68. IN PICB Icb,
  69. IN PFILE_POSITION_INFORMATION Buffer
  70. );
  71. NTSTATUS
  72. NwSetBasicInfo (
  73. IN PIRP_CONTEXT IrpContext,
  74. IN PICB Icb,
  75. IN PFILE_BASIC_INFORMATION Buffer
  76. );
  77. NTSTATUS
  78. NwSetDispositionInfo (
  79. IN PIRP_CONTEXT IrpContext,
  80. IN PICB Icb,
  81. IN PFILE_DISPOSITION_INFORMATION Buffer
  82. );
  83. NTSTATUS
  84. NwSetRenameInfo (
  85. IN PIRP_CONTEXT IrpContext,
  86. IN PICB Icb,
  87. IN PFILE_RENAME_INFORMATION Buffer
  88. );
  89. NTSTATUS
  90. NwSetPositionInfo (
  91. IN PIRP_CONTEXT IrpContext,
  92. IN PICB Icb,
  93. IN PFILE_POSITION_INFORMATION Buffer
  94. );
  95. NTSTATUS
  96. NwSetAllocationInfo (
  97. IN PIRP_CONTEXT IrpContext,
  98. IN PICB Icb,
  99. IN PFILE_ALLOCATION_INFORMATION Buffer
  100. );
  101. NTSTATUS
  102. NwSetEndOfFileInfo (
  103. IN PIRP_CONTEXT IrpContext,
  104. IN PICB Icb,
  105. IN PFILE_END_OF_FILE_INFORMATION Buffer
  106. );
  107. #ifdef ALLOC_PRAGMA
  108. #pragma alloc_text( PAGE, NwFsdQueryInformation )
  109. #pragma alloc_text( PAGE, NwFsdSetInformation )
  110. #pragma alloc_text( PAGE, NwCommonQueryInformation )
  111. #pragma alloc_text( PAGE, NwCommonSetInformation )
  112. #pragma alloc_text( PAGE, NwQueryStandardInfo )
  113. #pragma alloc_text( PAGE, NwQueryInternalInfo )
  114. #pragma alloc_text( PAGE, NwQueryEaInfo )
  115. #pragma alloc_text( PAGE, NwQueryNameInfo )
  116. #pragma alloc_text( PAGE, NwQueryPositionInfo )
  117. #pragma alloc_text( PAGE, NwSetBasicInfo )
  118. #pragma alloc_text( PAGE, NwSetDispositionInfo )
  119. #pragma alloc_text( PAGE, NwDeleteFile )
  120. #pragma alloc_text( PAGE, NwSetRenameInfo )
  121. #pragma alloc_text( PAGE, NwSetPositionInfo )
  122. #pragma alloc_text( PAGE, NwSetAllocationInfo )
  123. #pragma alloc_text( PAGE, NwSetEndOfFileInfo )
  124. #pragma alloc_text( PAGE, OccurenceCount )
  125. #ifndef QFE_BUILD
  126. #pragma alloc_text( PAGE1, NwQueryBasicInfo )
  127. #endif
  128. #endif
  129. #if 0 // Not pageable
  130. // see ifndef QFE_BUILD above
  131. #endif
  132. NTSTATUS
  133. NwFsdQueryInformation (
  134. IN PDEVICE_OBJECT DeviceObject,
  135. IN PIRP Irp
  136. )
  137. /*++
  138. Routine Description:
  139. This routine implements the FSD part of the NtQueryInformationFile API
  140. calls.
  141. Arguments:
  142. DeviceObject - Supplies a pointer to the device object to use.
  143. Irp - Supplies a pointer to the Irp to process.
  144. Return Value:
  145. NTSTATUS - The Fsd status for the Irp
  146. --*/
  147. {
  148. NTSTATUS status;
  149. PIRP_CONTEXT pIrpContext = NULL;
  150. BOOLEAN TopLevel;
  151. PAGED_CODE();
  152. DebugTrace(+1, Dbg, "NwFsdQueryInformation\n", 0);
  153. //
  154. // Call the common query information routine.
  155. //
  156. FsRtlEnterFileSystem();
  157. TopLevel = NwIsIrpTopLevel( Irp );
  158. try {
  159. pIrpContext = AllocateIrpContext( Irp );
  160. status = NwCommonQueryInformation( pIrpContext );
  161. } except(NwExceptionFilter( Irp, GetExceptionInformation() )) {
  162. if ( pIrpContext == NULL ) {
  163. //
  164. // If we couldn't allocate an irp context, just complete
  165. // irp without any fanfare.
  166. //
  167. status = STATUS_INSUFFICIENT_RESOURCES;
  168. Irp->IoStatus.Status = status;
  169. Irp->IoStatus.Information = 0;
  170. IoCompleteRequest ( Irp, IO_NETWORK_INCREMENT );
  171. } else {
  172. //
  173. // We had some trouble trying to perform the requested
  174. // operation, so we'll abort the I/O request with
  175. // the error Status that we get back from the
  176. // execption code
  177. //
  178. status = NwProcessException( pIrpContext, GetExceptionCode() );
  179. }
  180. }
  181. if ( pIrpContext ) {
  182. if ( status != STATUS_PENDING ) {
  183. NwDequeueIrpContext( pIrpContext, FALSE );
  184. }
  185. NwCompleteRequest( pIrpContext, status );
  186. }
  187. if ( TopLevel ) {
  188. NwSetTopLevelIrp( NULL );
  189. }
  190. FsRtlExitFileSystem();
  191. //
  192. // Return to the caller.
  193. //
  194. DebugTrace(-1, Dbg, "NwFsdQueryInformation -> %08lx\n", status );
  195. return status;
  196. }
  197. NTSTATUS
  198. NwFsdSetInformation (
  199. IN PDEVICE_OBJECT DeviceObject,
  200. IN PIRP Irp
  201. )
  202. /*++
  203. Routine Description:
  204. This routine implements the FSD part of the NtSetInformationFile API
  205. calls.
  206. Arguments:
  207. DeviceObject - Supplies the device object to use.
  208. Irp - Supplies the Irp being processed
  209. Return Value:
  210. NTSTATUS - The Fsd status for the Irp
  211. --*/
  212. {
  213. NTSTATUS status;
  214. PIRP_CONTEXT pIrpContext = NULL;
  215. BOOLEAN TopLevel;
  216. PAGED_CODE();
  217. DebugTrace(+1, Dbg, "NwFsdSetInformation\n", 0);
  218. //
  219. // Call the common Set Information routine.
  220. //
  221. FsRtlEnterFileSystem();
  222. TopLevel = NwIsIrpTopLevel( Irp );
  223. try {
  224. pIrpContext = AllocateIrpContext( Irp );
  225. status = NwCommonSetInformation( pIrpContext );
  226. } except(NwExceptionFilter( Irp, GetExceptionInformation() )) {
  227. if ( pIrpContext == NULL ) {
  228. //
  229. // If we couldn't allocate an irp context, just complete
  230. // irp without any fanfare.
  231. //
  232. status = STATUS_INSUFFICIENT_RESOURCES;
  233. Irp->IoStatus.Status = status;
  234. Irp->IoStatus.Information = 0;
  235. IoCompleteRequest ( Irp, IO_NETWORK_INCREMENT );
  236. } else {
  237. //
  238. // We had some trouble trying to perform the requested
  239. // operation, so we'll abort the I/O request with
  240. // the error Status that we get back from the
  241. // execption code
  242. //
  243. status = NwProcessException( pIrpContext, GetExceptionCode() );
  244. }
  245. }
  246. if ( pIrpContext ) {
  247. if ( status != STATUS_PENDING ) {
  248. NwDequeueIrpContext( pIrpContext, FALSE );
  249. }
  250. NwCompleteRequest( pIrpContext, status );
  251. }
  252. if ( TopLevel ) {
  253. NwSetTopLevelIrp( NULL );
  254. }
  255. FsRtlExitFileSystem();
  256. //
  257. // Return to the caller.
  258. //
  259. DebugTrace(-1, Dbg, "NwFsdSetInformation -> %08lx\n", status );
  260. return status;
  261. }
  262. NTSTATUS
  263. NwCommonQueryInformation (
  264. IN PIRP_CONTEXT pIrpContext
  265. )
  266. /*++
  267. Routine Description:
  268. This is the common routine for querying information on a file.
  269. Arguments:
  270. pIrpContext - Supplies Irp context information.
  271. Return Value:
  272. NTSTATUS - the return status for the operation.
  273. --*/
  274. {
  275. PIRP Irp;
  276. PIO_STACK_LOCATION irpSp;
  277. NTSTATUS status;
  278. ULONG length;
  279. FILE_INFORMATION_CLASS fileInformationClass;
  280. PVOID buffer;
  281. NODE_TYPE_CODE nodeTypeCode;
  282. PICB icb;
  283. PFCB fcb;
  284. PVOID fsContext, fsContext2;
  285. PFILE_ALL_INFORMATION AllInfo;
  286. PAGED_CODE();
  287. //
  288. // Get the current stack location.
  289. //
  290. Irp = pIrpContext->pOriginalIrp;
  291. irpSp = IoGetCurrentIrpStackLocation( Irp );
  292. DebugTrace(+1, Dbg, "NwCommonQueryInformation...\n", 0);
  293. DebugTrace( 0, Dbg, " Irp = %08lx\n", (ULONG_PTR)Irp);
  294. DebugTrace( 0, Dbg, " ->Length = %08lx\n", irpSp->Parameters.QueryFile.Length);
  295. DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", irpSp->Parameters.QueryFile.FileInformationClass);
  296. DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", (ULONG_PTR)Irp->AssociatedIrp.SystemBuffer);
  297. //
  298. // Find out who are.
  299. //
  300. if ((nodeTypeCode = NwDecodeFileObject( irpSp->FileObject,
  301. &fsContext,
  302. &fsContext2 )) == NTC_UNDEFINED) {
  303. status = STATUS_INVALID_HANDLE;
  304. DebugTrace(-1, Dbg, "NwCommonQueryInformation -> %08lx\n", status );
  305. return status;
  306. }
  307. //
  308. // Make sure that this the user is querying an ICB.
  309. //
  310. switch (nodeTypeCode) {
  311. case NW_NTC_ICB:
  312. icb = (PICB)fsContext2;
  313. break;
  314. default: // This is an illegal file object to query
  315. DebugTrace(0, Dbg, "Node type code is not incorrect\n", 0);
  316. DebugTrace(-1, Dbg, "NwCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0);
  317. return STATUS_INVALID_PARAMETER;
  318. }
  319. pIrpContext->Icb = icb;
  320. //
  321. // Make local copies of the input parameters.
  322. //
  323. length = irpSp->Parameters.QueryFile.Length;
  324. fileInformationClass = irpSp->Parameters.QueryFile.FileInformationClass;
  325. buffer = Irp->AssociatedIrp.SystemBuffer;
  326. //
  327. // Now acquire shared access to the FCB
  328. //
  329. fcb = icb->SuperType.Fcb;
  330. try {
  331. NwVerifyIcbSpecial( icb );
  332. //
  333. // Based on the information class we'll do different actions. Each
  334. // of the procedure that we're calling fill up as much of the
  335. // buffer as possible and return the remaining length, and status
  336. // This is done so that we can use them to build up the
  337. // FileAllInformation request. These procedures do not complete the
  338. // IRP, instead this procedure must complete the IRP.
  339. //
  340. status = STATUS_SUCCESS;
  341. switch (fileInformationClass) {
  342. case FileAllInformation:
  343. AllInfo = buffer;
  344. //
  345. // First call all the Query Info handlers we can call
  346. // synchronously.
  347. //
  348. NwQueryInternalInfo( pIrpContext, icb, &AllInfo->InternalInformation );
  349. NwQueryEaInfo( pIrpContext, &AllInfo->EaInformation );
  350. NwQueryPositionInfo( pIrpContext, icb, &AllInfo->PositionInformation );
  351. length -= FIELD_OFFSET( FILE_ALL_INFORMATION, NameInformation );
  352. status = NwQueryNameInfo( pIrpContext, icb, &AllInfo->NameInformation, &length );
  353. if ( !NT_ERROR( status ) ) {
  354. status = NwQueryStandardInfo( pIrpContext, icb, &AllInfo->StandardInformation );
  355. }
  356. if ( !NT_ERROR( status ) ) {
  357. status = NwQueryBasicInfo( pIrpContext, icb, &AllInfo->BasicInformation );
  358. }
  359. break;
  360. case FileBasicInformation:
  361. length -= sizeof( FILE_BASIC_INFORMATION );
  362. status = NwQueryBasicInfo( pIrpContext, icb, buffer );
  363. break;
  364. case FileStandardInformation:
  365. //
  366. // We will handle this call for information asynchronously.
  367. // The callback routine will fill in the missing data, and
  368. // complete the IRP.
  369. //
  370. // Remember the buffer length, and status to return.
  371. //
  372. length -= sizeof( FILE_STANDARD_INFORMATION );
  373. status = NwQueryStandardInfo( pIrpContext, icb, buffer );
  374. break;
  375. case FileInternalInformation:
  376. status = NwQueryInternalInfo( pIrpContext, icb, buffer );
  377. length -= sizeof( FILE_INTERNAL_INFORMATION );
  378. break;
  379. case FileEaInformation:
  380. status = NwQueryEaInfo( pIrpContext, buffer );
  381. length -= sizeof( FILE_EA_INFORMATION );
  382. break;
  383. case FilePositionInformation:
  384. status = NwQueryPositionInfo( pIrpContext, icb, buffer );
  385. length -= sizeof( FILE_POSITION_INFORMATION );
  386. break;
  387. case FileNameInformation:
  388. status = NwQueryNameInfo( pIrpContext, icb, buffer, &length );
  389. break;
  390. case FileAlternateNameInformation:
  391. if (!DisableAltFileName) {
  392. status = NwQueryAltNameInfo( pIrpContext, icb, buffer, &length);
  393. break;
  394. }
  395. default:
  396. status = STATUS_INVALID_PARAMETER;
  397. break;
  398. }
  399. //
  400. // Set the information field to the number of bytes actually
  401. // filled in and then complete the request. (This is
  402. // irrelavent if the Query worker function returned
  403. // STATUS_PENDING).
  404. //
  405. if ( status != STATUS_PENDING ) {
  406. Irp->IoStatus.Information =
  407. irpSp->Parameters.QueryFile.Length - length;
  408. }
  409. } finally {
  410. DebugTrace(-1, Dbg, "NwCommonQueryInformation -> %08lx\n", status );
  411. }
  412. return status;
  413. }
  414. NTSTATUS
  415. NwCommonSetInformation (
  416. IN PIRP_CONTEXT IrpContext
  417. )
  418. /*++
  419. Routine Description:
  420. This is the common routine for setting information on a file.
  421. Arguments:
  422. IrpContext - Supplies the Irp to process
  423. Return Value:
  424. NTSTATUS - the return status for the operation
  425. --*/
  426. {
  427. PIRP irp;
  428. PIO_STACK_LOCATION irpSp;
  429. NTSTATUS status;
  430. ULONG length;
  431. FILE_INFORMATION_CLASS fileInformationClass;
  432. PVOID buffer;
  433. NODE_TYPE_CODE nodeTypeCode;
  434. PICB icb;
  435. PFCB fcb;
  436. PVOID fsContext;
  437. //
  438. // Get the current Irp stack location.
  439. //
  440. irp = IrpContext->pOriginalIrp;
  441. irpSp = IoGetCurrentIrpStackLocation( irp );
  442. DebugTrace(+1, Dbg, "NwCommonSetInformation...\n", 0);
  443. DebugTrace( 0, Dbg, " Irp = %08lx\n", (ULONG_PTR)irp);
  444. DebugTrace( 0, Dbg, " ->Length = %08lx\n", irpSp->Parameters.SetFile.Length);
  445. DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", irpSp->Parameters.SetFile.FileInformationClass);
  446. DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", (ULONG_PTR)irp->AssociatedIrp.SystemBuffer);
  447. //
  448. // Get a pointer to the FCB and ensure that this is a server side
  449. // handler to a file.
  450. //
  451. if ((nodeTypeCode = NwDecodeFileObject( irpSp->FileObject,
  452. &fsContext,
  453. (PVOID *)&icb )) == NTC_UNDEFINED ) {
  454. status = STATUS_INVALID_HANDLE;
  455. DebugTrace(-1, Dbg, "NwCommonSetInformation -> %08lx\n", status );
  456. return status;
  457. }
  458. //
  459. // Make sure that this the user is querying an ICB.
  460. //
  461. switch (nodeTypeCode) {
  462. case NW_NTC_ICB:
  463. fcb = icb->SuperType.Fcb;
  464. break;
  465. default: // This is an illegal file object to query
  466. DebugTrace(0, Dbg, "Node type code is not incorrect\n", 0);
  467. DebugTrace(-1, Dbg, "NwCommonSetInformation -> STATUS_INVALID_PARAMETER\n", 0);
  468. return STATUS_INVALID_PARAMETER;
  469. }
  470. IrpContext->Icb = icb;
  471. //
  472. // Make local copies of the input parameters.
  473. //
  474. length = irpSp->Parameters.SetFile.Length;
  475. fileInformationClass = irpSp->Parameters.SetFile.FileInformationClass;
  476. buffer = irp->AssociatedIrp.SystemBuffer;
  477. try {
  478. NwVerifyIcb( icb );
  479. //
  480. // Based on the information class we'll do different actions. Each
  481. // procedure that we're calling will complete the request.
  482. //
  483. switch (fileInformationClass) {
  484. case FileBasicInformation:
  485. status = NwSetBasicInfo( IrpContext, icb, buffer );
  486. break;
  487. case FileDispositionInformation:
  488. status = NwSetDispositionInfo( IrpContext, icb, buffer );
  489. break;
  490. case FileRenameInformation:
  491. status = NwSetRenameInfo( IrpContext, icb, buffer );
  492. break;
  493. case FilePositionInformation:
  494. status = NwSetPositionInfo( IrpContext, icb, buffer );
  495. break;
  496. case FileLinkInformation:
  497. status = STATUS_INVALID_DEVICE_REQUEST;
  498. break;
  499. case FileAllocationInformation:
  500. status = NwSetAllocationInfo( IrpContext, icb, buffer );
  501. break;
  502. case FileEndOfFileInformation:
  503. status = NwSetEndOfFileInfo( IrpContext, icb, buffer );
  504. break;
  505. default:
  506. status = STATUS_INVALID_PARAMETER;
  507. break;
  508. }
  509. } finally {
  510. DebugTrace(-1, Dbg, "NwCommonSetInformation -> %08lx\n", status);
  511. }
  512. return status;
  513. }
  514. NTSTATUS
  515. NwQueryBasicInfo (
  516. IN PIRP_CONTEXT IrpContext,
  517. IN PICB Icb,
  518. OUT PFILE_BASIC_INFORMATION Buffer
  519. )
  520. /*++
  521. Routine Description:
  522. This routine performs the query basic information operation.
  523. This routine cannot be paged, it is called from QueryStandardInfoCallback.
  524. Arguments:
  525. Icb - Supplies a pointer the ICB for the file being querying.
  526. Buffer - Supplies a pointer to the buffer where the information is
  527. to be returned.
  528. Return Value:
  529. VOID
  530. --*/
  531. {
  532. PFCB Fcb;
  533. NTSTATUS Status;
  534. ULONG Attributes;
  535. USHORT CreationDate;
  536. USHORT CreationTime = DEFAULT_TIME;
  537. USHORT LastAccessDate;
  538. USHORT LastModifiedDate;
  539. USHORT LastModifiedTime;
  540. BOOLEAN FirstTime = TRUE;
  541. DebugTrace(0, Dbg, "QueryBasicInfo...\n", 0);
  542. //
  543. // Zero out the buffer.
  544. //
  545. RtlZeroMemory( Buffer, sizeof(FILE_BASIC_INFORMATION) );
  546. Fcb = Icb->SuperType.Fcb;
  547. //
  548. // It is ok to attempt a reconnect if this request fails with a
  549. // connection error.
  550. //
  551. SetFlag( IrpContext->Flags, IRP_FLAG_RECONNECTABLE );
  552. NwAcquireSharedFcb( Fcb->NonPagedFcb, TRUE );
  553. //
  554. // If we already know the file attributes, simply return them.
  555. //
  556. if ( FlagOn( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID ) ) {
  557. //
  558. // Set the various fields in the record
  559. //
  560. Buffer->CreationTime = NwDateTimeToNtTime(
  561. Fcb->CreationDate,
  562. Fcb->CreationTime
  563. );
  564. Buffer->LastAccessTime = NwDateTimeToNtTime(
  565. Fcb->LastAccessDate,
  566. DEFAULT_TIME
  567. );
  568. Buffer->LastWriteTime = NwDateTimeToNtTime(
  569. Fcb->LastModifiedDate,
  570. Fcb->LastModifiedTime
  571. );
  572. Buffer->ChangeTime.QuadPart = 0;
  573. DebugTrace(0, Dbg, "QueryBasic known %wZ\n", &Fcb->RelativeFileName);
  574. DebugTrace(0, Dbg, "LastModifiedDate %x\n", Fcb->LastModifiedDate);
  575. DebugTrace(0, Dbg, "LastModifiedTime %x\n", Fcb->LastModifiedTime);
  576. DebugTrace(0, Dbg, "CreationDate %x\n", Fcb->CreationDate );
  577. DebugTrace(0, Dbg, "CreationTime %x\n", Fcb->CreationTime );
  578. DebugTrace(0, Dbg, "LastAccessDate %x\n", Fcb->LastAccessDate );
  579. Buffer->FileAttributes = Fcb->NonPagedFcb->Attributes;
  580. if ( Buffer->FileAttributes == 0 ) {
  581. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  582. }
  583. NwReleaseFcb( Fcb->NonPagedFcb );
  584. return STATUS_SUCCESS;
  585. } else if ( Fcb->RelativeFileName.Length == 0 ) {
  586. //
  587. // Allow 'cd \' to work.
  588. //
  589. Buffer->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
  590. Buffer->CreationTime = NwDateTimeToNtTime(
  591. DEFAULT_DATE,
  592. DEFAULT_TIME
  593. );
  594. Buffer->LastAccessTime = Buffer->CreationTime;
  595. Buffer->LastWriteTime = Buffer->CreationTime;
  596. Buffer->ChangeTime.QuadPart = 0;
  597. NwReleaseFcb( Fcb->NonPagedFcb );
  598. return STATUS_SUCCESS;
  599. } else {
  600. NwReleaseFcb( Fcb->NonPagedFcb );
  601. IrpContext->pNpScb = Fcb->Scb->pNpScb;
  602. Retry:
  603. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  604. DebugTrace(0, Dbg, "QueryBasic short %wZ\n", &Fcb->RelativeFileName);
  605. Status = ExchangeWithWait (
  606. IrpContext,
  607. SynchronousResponseCallback,
  608. "FwbbJ",
  609. NCP_SEARCH_FILE,
  610. -1,
  611. Fcb->Vcb->Specific.Disk.Handle,
  612. Fcb->NodeTypeCode == NW_NTC_FCB ?
  613. SEARCH_ALL_FILES : SEARCH_ALL_DIRECTORIES,
  614. &Icb->SuperType.Fcb->RelativeFileName );
  615. if ( NT_SUCCESS( Status ) ) {
  616. Status = ParseResponse(
  617. IrpContext,
  618. IrpContext->rsp,
  619. IrpContext->ResponseLength,
  620. "N==_b-==wwww",
  621. 14,
  622. &Attributes,
  623. &CreationDate,
  624. &LastAccessDate,
  625. &LastModifiedDate,
  626. &LastModifiedTime);
  627. //
  628. // If this was a directory, there's no usable
  629. // time/date info from the server.
  630. //
  631. if ( ( NT_SUCCESS( Status ) ) &&
  632. ( Attributes & NW_ATTRIBUTE_DIRECTORY ) ) {
  633. CreationDate = DEFAULT_DATE;
  634. LastAccessDate = DEFAULT_DATE;
  635. LastModifiedDate = DEFAULT_DATE;
  636. LastModifiedTime = DEFAULT_TIME;
  637. }
  638. }
  639. } else {
  640. DebugTrace(0, Dbg, "QueryBasic long %wZ\n", &Fcb->RelativeFileName);
  641. Status = ExchangeWithWait (
  642. IrpContext,
  643. SynchronousResponseCallback,
  644. "LbbWDbDbC",
  645. NCP_LFN_GET_INFO,
  646. Fcb->Vcb->Specific.Disk.LongNameSpace,
  647. Fcb->Vcb->Specific.Disk.LongNameSpace,
  648. Fcb->NodeTypeCode == NW_NTC_FCB ?
  649. SEARCH_ALL_FILES : SEARCH_ALL_DIRECTORIES,
  650. LFN_FLAG_INFO_ATTRIBUTES |
  651. LFN_FLAG_INFO_MODIFY_TIME |
  652. LFN_FLAG_INFO_CREATION_TIME,
  653. Fcb->Vcb->Specific.Disk.VolumeNumber,
  654. Fcb->Vcb->Specific.Disk.Handle,
  655. 0,
  656. &Icb->SuperType.Fcb->RelativeFileName );
  657. if ( NT_SUCCESS( Status ) ) {
  658. Status = ParseResponse(
  659. IrpContext,
  660. IrpContext->rsp,
  661. IrpContext->ResponseLength,
  662. "N_e_xx_xx_x",
  663. 4,
  664. &Attributes,
  665. 12,
  666. &CreationTime,
  667. &CreationDate,
  668. 4,
  669. &LastModifiedTime,
  670. &LastModifiedDate,
  671. 4,
  672. &LastAccessDate );
  673. }
  674. }
  675. if ( NT_SUCCESS( Status ) ) {
  676. //
  677. // Set the various fields in the record
  678. //
  679. Buffer->CreationTime = NwDateTimeToNtTime(
  680. CreationDate,
  681. CreationTime
  682. );
  683. Buffer->LastAccessTime = NwDateTimeToNtTime(
  684. LastAccessDate,
  685. DEFAULT_TIME
  686. );
  687. Buffer->LastWriteTime = NwDateTimeToNtTime(
  688. LastModifiedDate,
  689. LastModifiedTime
  690. );
  691. Buffer->ChangeTime.QuadPart = 0;
  692. DebugTrace(0, Dbg, "CreationDate %x\n", CreationDate );
  693. DebugTrace(0, Dbg, "CreationTime %x\n", CreationTime );
  694. DebugTrace(0, Dbg, "LastAccessDate %x\n", LastAccessDate );
  695. DebugTrace(0, Dbg, "LastModifiedDate %x\n", LastModifiedDate);
  696. DebugTrace(0, Dbg, "LastModifiedTime %x\n", LastModifiedTime);
  697. Buffer->FileAttributes = (UCHAR)Attributes;
  698. if ( Buffer->FileAttributes == 0 ) {
  699. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  700. }
  701. } else if ((Status == STATUS_INVALID_HANDLE) &&
  702. (FirstTime)) {
  703. //
  704. // Check to see if Volume handle is invalid. Caused when volume
  705. // is unmounted and then remounted.
  706. //
  707. FirstTime = FALSE;
  708. NwReopenVcbHandle( IrpContext, Fcb->Vcb );
  709. goto Retry;
  710. }
  711. return( Status );
  712. }
  713. }
  714. #if NWFASTIO
  715. BOOLEAN
  716. NwFastQueryBasicInfo (
  717. IN PFILE_OBJECT FileObject,
  718. IN BOOLEAN Wait,
  719. IN OUT PFILE_BASIC_INFORMATION Buffer,
  720. OUT PIO_STATUS_BLOCK IoStatus,
  721. IN PDEVICE_OBJECT DeviceObject
  722. )
  723. /*++
  724. Routine Description:
  725. This routine is for the fast query call for standard file information.
  726. Arguments:
  727. FileObject - Supplies the file object used in this operation
  728. Wait - Indicates if we are allowed to wait for the information
  729. Buffer - Supplies the output buffer to receive the basic information
  730. IoStatus - Receives the final status of the operation
  731. Return Value:
  732. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  733. needs to take the long route.
  734. --*/
  735. {
  736. NODE_TYPE_CODE NodeTypeCode;
  737. PICB Icb;
  738. PFCB Fcb;
  739. PVOID FsContext;
  740. FsRtlEnterFileSystem();
  741. try {
  742. //
  743. // Find out who are.
  744. //
  745. if ((NodeTypeCode = NwDecodeFileObject( FileObject,
  746. &FsContext,
  747. &Icb )) != NW_NTC_ICB ) {
  748. DebugTrace(-1, Dbg, "NwFastQueryStandardInfo -> FALSE\n", 0 );
  749. return FALSE;
  750. }
  751. Fcb = Icb->SuperType.Fcb;
  752. NwAcquireExclusiveFcb( Fcb->NonPagedFcb, TRUE );
  753. //
  754. // If we don't have the info handy, we can't use the fast path.
  755. //
  756. if ( !FlagOn( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID ) ) {
  757. NwReleaseFcb( Fcb->NonPagedFcb );
  758. return( FALSE );
  759. }
  760. //
  761. // Set the various fields in the record
  762. //
  763. Buffer->CreationTime = NwDateTimeToNtTime(
  764. Fcb->CreationDate,
  765. Fcb->CreationTime
  766. );
  767. Buffer->LastAccessTime = NwDateTimeToNtTime(
  768. Fcb->LastAccessDate,
  769. DEFAULT_TIME
  770. );
  771. Buffer->LastWriteTime = NwDateTimeToNtTime(
  772. Fcb->LastModifiedDate,
  773. Fcb->LastModifiedTime
  774. );
  775. Buffer->ChangeTime.QuadPart = 0;
  776. DebugTrace(0, Dbg, "QueryBasic known %wZ\n", &Fcb->RelativeFileName);
  777. DebugTrace(0, Dbg, "LastModifiedDate %x\n", Fcb->LastModifiedDate);
  778. DebugTrace(0, Dbg, "LastModifiedTime %x\n", Fcb->LastModifiedTime);
  779. DebugTrace(0, Dbg, "CreationDate %x\n", Fcb->CreationDate );
  780. DebugTrace(0, Dbg, "CreationTime %x\n", Fcb->CreationTime );
  781. DebugTrace(0, Dbg, "LastAccessDate %x\n", Fcb->LastAccessDate );
  782. Buffer->FileAttributes = Fcb->NonPagedFcb->Attributes;
  783. if ( Buffer->FileAttributes == 0 ) {
  784. Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
  785. }
  786. IoStatus->Status = STATUS_SUCCESS;
  787. IoStatus->Information = sizeof( *Buffer );
  788. NwReleaseFcb( Fcb->NonPagedFcb );
  789. return TRUE;
  790. } finally {
  791. FsRtlExitFileSystem();
  792. }
  793. }
  794. #endif
  795. NTSTATUS
  796. NwQueryStandardInfo (
  797. IN PIRP_CONTEXT IrpContext,
  798. IN PICB Icb,
  799. IN PFILE_STANDARD_INFORMATION Buffer
  800. )
  801. /*++
  802. Routine Description:
  803. This routine perforNw the query standard information operation.
  804. Arguments:
  805. Fcb - Supplies the FCB of the being queried
  806. Buffer - Supplies a pointer to the buffer where the information is
  807. to be returned
  808. Return Value:
  809. VOID
  810. --*/
  811. {
  812. NTSTATUS Status;
  813. PFCB Fcb;
  814. ULONG FileSize;
  815. BOOLEAN FirstTime = TRUE;
  816. PAGED_CODE();
  817. Fcb = Icb->SuperType.Fcb;
  818. //
  819. // Zero out the buffer.
  820. //
  821. RtlZeroMemory( Buffer, sizeof(FILE_STANDARD_INFORMATION) );
  822. //
  823. // Fill in the answers we already know.
  824. //
  825. Buffer->NumberOfLinks = 1;
  826. Buffer->DeletePending = (BOOLEAN)FlagOn( Fcb->Flags, FCB_FLAGS_DELETE_ON_CLOSE );
  827. if ( Fcb->NodeTypeCode == NW_NTC_FCB ) {
  828. Buffer->Directory = FALSE;
  829. } else {
  830. Buffer->Directory = TRUE;
  831. }
  832. if ( !Icb->HasRemoteHandle ) {
  833. //
  834. // It is ok to attempt a reconnect if this request fails with a
  835. // connection error.
  836. //
  837. SetFlag( IrpContext->Flags, IRP_FLAG_RECONNECTABLE );
  838. if ( Fcb->NodeTypeCode == NW_NTC_DCB ||
  839. FlagOn( Fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  840. //
  841. // Allow 'cd \' to work.
  842. //
  843. Buffer->AllocationSize.QuadPart = 0;
  844. Buffer->EndOfFile.QuadPart = 0;
  845. return STATUS_SUCCESS;
  846. } else {
  847. //
  848. // No open handle for this file. Use a path based NCP
  849. // to get the file size.
  850. //
  851. Retry:
  852. IrpContext->pNpScb = Fcb->Scb->pNpScb;
  853. if ( !BooleanFlagOn( Icb->SuperType.Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  854. Status = ExchangeWithWait (
  855. IrpContext,
  856. SynchronousResponseCallback,
  857. "FwbbJ",
  858. NCP_SEARCH_FILE,
  859. -1,
  860. Fcb->Vcb->Specific.Disk.Handle,
  861. SEARCH_ALL_FILES,
  862. &Fcb->RelativeFileName );
  863. if ( NT_SUCCESS( Status ) ) {
  864. Status = ParseResponse(
  865. IrpContext,
  866. IrpContext->rsp,
  867. IrpContext->ResponseLength,
  868. "N_d",
  869. 20,
  870. &FileSize );
  871. }
  872. } else {
  873. Status = ExchangeWithWait (
  874. IrpContext,
  875. SynchronousResponseCallback,
  876. "LbbWDbDbC",
  877. NCP_LFN_GET_INFO,
  878. Fcb->Vcb->Specific.Disk.LongNameSpace,
  879. Fcb->Vcb->Specific.Disk.LongNameSpace,
  880. SEARCH_ALL_FILES,
  881. LFN_FLAG_INFO_FILE_SIZE,
  882. Fcb->Vcb->Specific.Disk.VolumeNumber,
  883. Fcb->Vcb->Specific.Disk.Handle,
  884. 0,
  885. &Fcb->RelativeFileName );
  886. if ( NT_SUCCESS( Status ) ) {
  887. Status = ParseResponse(
  888. IrpContext,
  889. IrpContext->rsp,
  890. IrpContext->ResponseLength,
  891. "N_e",
  892. 10,
  893. &FileSize );
  894. }
  895. }
  896. if ((Status == STATUS_INVALID_HANDLE) &&
  897. (FirstTime)) {
  898. //
  899. // Check to see if Volume handle is invalid. Caused when volume
  900. // is unmounted and then remounted.
  901. //
  902. FirstTime = FALSE;
  903. NwReopenVcbHandle( IrpContext, Fcb->Vcb );
  904. goto Retry;
  905. }
  906. Buffer->AllocationSize.QuadPart = FileSize;
  907. Buffer->EndOfFile.QuadPart = FileSize;
  908. }
  909. } else {
  910. //
  911. // Start a Get file size NCP
  912. //
  913. IrpContext->pNpScb = Fcb->Scb->pNpScb;
  914. if ( Fcb->NodeTypeCode == NW_NTC_FCB ) {
  915. AcquireFcbAndFlushCache( IrpContext, Fcb->NonPagedFcb );
  916. }
  917. Status = ExchangeWithWait(
  918. IrpContext,
  919. SynchronousResponseCallback,
  920. "F-r",
  921. NCP_GET_FILE_SIZE,
  922. &Icb->Handle, sizeof(Icb->Handle ) );
  923. if ( NT_SUCCESS( Status ) ) {
  924. //
  925. // Get the data from the response.
  926. //
  927. Status = ParseResponse(
  928. IrpContext,
  929. IrpContext->rsp,
  930. IrpContext->ResponseLength,
  931. "Nd",
  932. &FileSize );
  933. }
  934. if ( NT_SUCCESS( Status ) ) {
  935. //
  936. // Fill in Allocation size and EOF, based on the response.
  937. //
  938. Buffer->AllocationSize.QuadPart = FileSize;
  939. Buffer->EndOfFile.QuadPart = Buffer->AllocationSize.QuadPart;
  940. }
  941. }
  942. return( Status );
  943. }
  944. #if NWFASTIO
  945. BOOLEAN
  946. NwFastQueryStandardInfo (
  947. IN PFILE_OBJECT FileObject,
  948. IN BOOLEAN Wait,
  949. IN OUT PFILE_STANDARD_INFORMATION Buffer,
  950. OUT PIO_STATUS_BLOCK IoStatus,
  951. IN PDEVICE_OBJECT DeviceObject
  952. )
  953. /*++
  954. Routine Description:
  955. This routine is for the fast query call for standard file information.
  956. Arguments:
  957. FileObject - Supplies the file object used in this operation
  958. Wait - Indicates if we are allowed to wait for the information
  959. Buffer - Supplies the output buffer to receive the basic information
  960. IoStatus - Receives the final status of the operation
  961. Return Value:
  962. BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
  963. needs to take the long route.
  964. --*/
  965. {
  966. NODE_TYPE_CODE NodeTypeCode;
  967. PICB Icb;
  968. PFCB Fcb;
  969. PVOID FsContext;
  970. //
  971. // Find out who are.
  972. //
  973. try {
  974. FsRtlEnterFileSystem();
  975. if ((NodeTypeCode = NwDecodeFileObject( FileObject,
  976. &FsContext,
  977. &Icb )) != NW_NTC_ICB ) {
  978. DebugTrace(-1, Dbg, "NwFastQueryStandardInfo -> FALSE\n", 0 );
  979. return FALSE;
  980. }
  981. Fcb = Icb->SuperType.Fcb;
  982. //
  983. // If we have the info handy, we can use the fast path.
  984. //
  985. if ( Fcb->NodeTypeCode == NW_NTC_DCB ||
  986. FlagOn( Fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  987. Buffer->AllocationSize.QuadPart = 0;
  988. Buffer->EndOfFile.QuadPart = 0;
  989. Buffer->NumberOfLinks = 1;
  990. Buffer->DeletePending = (BOOLEAN)FlagOn( Fcb->Flags, FCB_FLAGS_DELETE_ON_CLOSE );
  991. Buffer->Directory = TRUE;
  992. IoStatus->Status = STATUS_SUCCESS;
  993. IoStatus->Information = sizeof( *Buffer );
  994. return TRUE;
  995. } else {
  996. return FALSE;
  997. }
  998. } finally {
  999. FsRtlExitFileSystem();
  1000. }
  1001. }
  1002. #endif
  1003. NTSTATUS
  1004. NwQueryInternalInfo (
  1005. IN PIRP_CONTEXT IrpContext,
  1006. IN PICB Icb,
  1007. IN PFILE_INTERNAL_INFORMATION Buffer
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. This routine perforNw the query internal information operation.
  1012. Arguments:
  1013. Fcb - Supplies the FCB of the being queried.
  1014. Buffer - Supplies a pointer to the buffer where the information is
  1015. to be returned.
  1016. Return Value:
  1017. VOID
  1018. --*/
  1019. {
  1020. PAGED_CODE();
  1021. DebugTrace(0, Dbg, "QueryInternalInfo...\n", 0);
  1022. //
  1023. // Zero out the buffer.
  1024. //
  1025. RtlZeroMemory( Buffer, sizeof(FILE_INTERNAL_INFORMATION) );
  1026. //
  1027. // Set the internal index number to be the address of the ICB.
  1028. //
  1029. Buffer->IndexNumber.HighPart = 0;
  1030. Buffer->IndexNumber.QuadPart = (ULONG_PTR)Icb->NpFcb;
  1031. return( STATUS_SUCCESS );
  1032. }
  1033. NTSTATUS
  1034. NwQueryEaInfo (
  1035. IN PIRP_CONTEXT IrpContext,
  1036. IN PFILE_EA_INFORMATION Buffer
  1037. )
  1038. /*++
  1039. Routine Description:
  1040. This routine performs the query Ea information operation.
  1041. Arguments:
  1042. Buffer - Supplies a pointer to the buffer where the information is
  1043. to be returned
  1044. Return Value:
  1045. VOID - The result of this query
  1046. --*/
  1047. {
  1048. PAGED_CODE();
  1049. DebugTrace(0, Dbg, "QueryEaInfo...\n", 0);
  1050. //
  1051. // Zero out the buffer.
  1052. //
  1053. RtlZeroMemory(Buffer, sizeof(FILE_EA_INFORMATION));
  1054. return STATUS_SUCCESS;
  1055. }
  1056. NTSTATUS
  1057. NwQueryNameInfo (
  1058. IN PIRP_CONTEXT IrpContext,
  1059. IN PICB Icb,
  1060. IN PFILE_NAME_INFORMATION Buffer,
  1061. IN PULONG Length
  1062. )
  1063. /*++
  1064. Routine Description:
  1065. This routine performs the query name information operation.
  1066. Arguments:
  1067. Fcb - Supplies the FCB of the file to query.
  1068. Buffer - Supplies a pointer to the buffer where the information is
  1069. to be returned
  1070. Length - Supplies and receives the length of the buffer in bytes.
  1071. Return Value:
  1072. NTSTATUS - The result of this query.
  1073. --*/
  1074. {
  1075. ULONG bytesToCopy;
  1076. ULONG fileNameSize;
  1077. PFCB Fcb = Icb->SuperType.Fcb;
  1078. NTSTATUS status;
  1079. PAGED_CODE();
  1080. DebugTrace(0, Dbg, "QueryNameInfo...\n", 0);
  1081. //
  1082. // Win32 expects the root directory name to be '\' terminated,
  1083. // the netware server does not. So if this is a root directory,
  1084. // (i.e RelativeFileName length is 0) append a '\' to the path name.
  1085. //
  1086. //
  1087. // See if the buffer is large enough, and decide how many bytes to copy.
  1088. //
  1089. *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName[0] );
  1090. fileNameSize = Fcb->FullFileName.Length;
  1091. if ( Fcb->RelativeFileName.Length == 0 ) {
  1092. fileNameSize += sizeof(L'\\');
  1093. }
  1094. Buffer->FileNameLength = fileNameSize;
  1095. if ( *Length >= fileNameSize ) {
  1096. status = STATUS_SUCCESS;
  1097. bytesToCopy = fileNameSize;
  1098. } else {
  1099. status = STATUS_BUFFER_OVERFLOW;
  1100. bytesToCopy = *Length;
  1101. }
  1102. //
  1103. // Copy over the file name and its length.
  1104. //
  1105. RtlMoveMemory(
  1106. Buffer->FileName,
  1107. Fcb->FullFileName.Buffer,
  1108. bytesToCopy);
  1109. //
  1110. // If this is a root directory, and there is space in the buffer
  1111. // append a '\' to make win32 happy.
  1112. //
  1113. if ( Fcb->RelativeFileName.Length == 0 && status == STATUS_SUCCESS ) {
  1114. Buffer->FileName[ fileNameSize/sizeof(WCHAR) - 1 ] = L'\\';
  1115. }
  1116. *Length -= bytesToCopy;
  1117. return status;
  1118. }
  1119. NTSTATUS
  1120. NwQueryAltNameInfo (
  1121. IN PIRP_CONTEXT pIrpContext,
  1122. IN PICB Icb,
  1123. IN PFILE_NAME_INFORMATION Buffer,
  1124. IN PULONG Length
  1125. )
  1126. /*++
  1127. Routine Description:
  1128. This routine performs the AltName query name information operation.
  1129. Arguments:
  1130. Fcb - Supplies the FCB of the file to query.
  1131. Buffer - Supplies a pointer to the buffer where the information is
  1132. to be returned
  1133. Length - Supplies and receives the length of the buffer in bytes.
  1134. Return Value:
  1135. NTSTATUS - The result of this query.
  1136. --*/
  1137. {
  1138. ULONG bytesToCopy;
  1139. ULONG fileNameSize;
  1140. PFCB Fcb = Icb->SuperType.Fcb;
  1141. UNICODE_STRING ShortName;
  1142. NTSTATUS status;
  1143. PAGED_CODE();
  1144. DebugTrace(0, Dbg, "QueryAltNameInfo...\n", 0);
  1145. pIrpContext->pNpScb = Fcb->Scb->pNpScb;
  1146. //
  1147. // See if the buffer is large enough, and decide how many bytes to copy.
  1148. //
  1149. *Length -= FIELD_OFFSET( FILE_NAME_INFORMATION, FileName[0] );
  1150. ShortName.MaximumLength = MAX_PATH;
  1151. ShortName.Buffer=NULL;
  1152. ShortName.Length = 0;
  1153. status = ExchangeWithWait (
  1154. pIrpContext,
  1155. SynchronousResponseCallback,
  1156. "LbbWDbDbC",
  1157. NCP_LFN_GET_INFO,
  1158. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1159. 0x0, //0x0 DOS Nam
  1160. SEARCH_ALL_DIRECTORIES,
  1161. LFN_FLAG_INFO_NAME,
  1162. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1163. Fcb->Vcb->Specific.Disk.Handle,
  1164. 0,
  1165. &Fcb->RelativeFileName );
  1166. if (!NT_SUCCESS( status ) ){
  1167. return status;
  1168. }
  1169. ShortName.Buffer= ALLOCATE_POOL(NonPagedPool,
  1170. ShortName.MaximumLength+sizeof(WCHAR));
  1171. if (ShortName.Buffer == NULL){
  1172. return STATUS_INSUFFICIENT_RESOURCES;
  1173. }
  1174. status = ParseResponse(
  1175. pIrpContext,
  1176. pIrpContext->rsp,
  1177. pIrpContext->ResponseLength,
  1178. "N_P",
  1179. 76,
  1180. &ShortName);
  1181. if ( NT_SUCCESS( status ) ) {
  1182. fileNameSize = ShortName.Length;
  1183. if ( *Length >= fileNameSize ) {
  1184. status = STATUS_SUCCESS;
  1185. bytesToCopy = fileNameSize;
  1186. } else {
  1187. status = STATUS_BUFFER_OVERFLOW;
  1188. bytesToCopy = *Length;
  1189. }
  1190. Buffer->FileNameLength = fileNameSize;
  1191. RtlMoveMemory(
  1192. Buffer->FileName,
  1193. ShortName.Buffer,
  1194. bytesToCopy);
  1195. *Length -= bytesToCopy;
  1196. }
  1197. FREE_POOL(ShortName.Buffer);
  1198. return status;
  1199. }
  1200. NTSTATUS
  1201. NwQueryPositionInfo (
  1202. IN PIRP_CONTEXT IrpContext,
  1203. IN PICB Icb,
  1204. IN PFILE_POSITION_INFORMATION Buffer
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. This routine performs the query position information operation.
  1209. Arguments:
  1210. Fcb - Supplies the FCB of the file being queried.
  1211. Buffer - Supplies a pointer to the buffer where the information is
  1212. to be returned.
  1213. Return Value:
  1214. VOID
  1215. --*/
  1216. {
  1217. PAGED_CODE();
  1218. DebugTrace(0, Dbg, "QueryPositionInfo...\n", 0);
  1219. //
  1220. // Return the current byte offset. This info is totally
  1221. // bogus for asynchronous files. Also note that we don't
  1222. // use the FilePosition member of the ICB for anything.
  1223. //
  1224. if ( Icb->FileObject ) {
  1225. Buffer->CurrentByteOffset.QuadPart = Icb->FileObject->CurrentByteOffset.QuadPart;
  1226. }
  1227. return STATUS_SUCCESS;
  1228. }
  1229. NTSTATUS
  1230. NwSetBasicInfo (
  1231. IN PIRP_CONTEXT pIrpContext,
  1232. IN PICB Icb,
  1233. IN PFILE_BASIC_INFORMATION Buffer
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. This routine sets the basic information for a file.
  1238. Arguments:
  1239. pIrpContext - Supplies Irp context information.
  1240. Icb - Supplies the ICB for the file being modified.
  1241. Buffer - Supplies the buffer containing the data being set.
  1242. Return Value:
  1243. NTSTATUS - Returns our completion status.
  1244. --*/
  1245. {
  1246. PFCB Fcb;
  1247. NTSTATUS Status;
  1248. BOOLEAN SetTime = FALSE;
  1249. BOOLEAN SetAttributes = FALSE;
  1250. ULONG LfnFlag = 0;
  1251. PAGED_CODE();
  1252. DebugTrace(0, Dbg, "SetBasicInfo...\n", 0);
  1253. Fcb = Icb->SuperType.Fcb;
  1254. pIrpContext->pNpScb = Fcb->Scb->pNpScb;
  1255. //
  1256. // Append this IRP context and wait to get to the front.
  1257. // then grab from FCB
  1258. //
  1259. NwAppendToQueueAndWait( pIrpContext );
  1260. NwAcquireExclusiveFcb( Fcb->NonPagedFcb, TRUE );
  1261. //
  1262. // It is ok to attempt a reconnect if this request fails with a
  1263. // connection error.
  1264. //
  1265. SetFlag( pIrpContext->Flags, IRP_FLAG_RECONNECTABLE );
  1266. if (Buffer->CreationTime.QuadPart != 0) {
  1267. //
  1268. // Modify the creation time.
  1269. //
  1270. Status = NwNtTimeToNwDateTime(
  1271. Buffer->CreationTime,
  1272. &Fcb->CreationDate,
  1273. &Fcb->CreationTime );
  1274. if ( !NT_SUCCESS( Status ) ) {
  1275. NwReleaseFcb( Fcb->NonPagedFcb );
  1276. return( Status );
  1277. }
  1278. SetTime = TRUE;
  1279. LfnFlag |= LFN_FLAG_SET_INFO_CREATE_DATE | LFN_FLAG_SET_INFO_CREATE_TIME;
  1280. }
  1281. if (Buffer->LastAccessTime.QuadPart != 0) {
  1282. USHORT Dummy;
  1283. //
  1284. // Modify the last access time.
  1285. //
  1286. Status = NwNtTimeToNwDateTime(
  1287. Buffer->LastAccessTime,
  1288. &Fcb->LastAccessDate,
  1289. &Dummy );
  1290. if ( !NT_SUCCESS( Status ) ) {
  1291. NwReleaseFcb( Fcb->NonPagedFcb );
  1292. return( Status );
  1293. }
  1294. SetTime = TRUE;
  1295. LfnFlag |= LFN_FLAG_SET_INFO_LASTACCESS_DATE;
  1296. // Set the last access flag in the ICB so that we update
  1297. // last access time for real when we close this handle!
  1298. Icb->UserSetLastAccessTime = TRUE;
  1299. }
  1300. if (Buffer->LastWriteTime.QuadPart != 0) {
  1301. //
  1302. // Modify the last write time
  1303. //
  1304. Status = NwNtTimeToNwDateTime(
  1305. Buffer->LastWriteTime,
  1306. &Fcb->LastModifiedDate,
  1307. &Fcb->LastModifiedTime );
  1308. if ( !NT_SUCCESS( Status ) ) {
  1309. NwReleaseFcb( Fcb->NonPagedFcb );
  1310. return( Status );
  1311. }
  1312. LfnFlag |= LFN_FLAG_SET_INFO_MODIFY_DATE | LFN_FLAG_SET_INFO_MODIFY_TIME;
  1313. }
  1314. if (Buffer->FileAttributes != 0) {
  1315. LfnFlag |= LFN_FLAG_SET_INFO_ATTRIBUTES;
  1316. }
  1317. if ( LfnFlag == 0 ) {
  1318. //
  1319. // Nothing to set, simply return success.
  1320. //
  1321. Status = STATUS_SUCCESS;
  1322. }
  1323. if ( Fcb->NodeTypeCode == NW_NTC_FCB ) {
  1324. //
  1325. // Call plain FlushCache - we don't want to acquire and
  1326. // release the NpFcb. We are already at the front and have the Fcb
  1327. // exclusive.
  1328. //
  1329. FlushCache( pIrpContext, Fcb->NonPagedFcb );
  1330. }
  1331. if ( BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1332. Status = ExchangeWithWait(
  1333. pIrpContext,
  1334. SynchronousResponseCallback,
  1335. "LbbWDW--WW==WW==_W_bDbC",
  1336. NCP_LFN_SET_INFO,
  1337. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1338. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1339. Fcb->NodeTypeCode == NW_NTC_FCB ?
  1340. SEARCH_ALL_FILES : SEARCH_ALL_DIRECTORIES,
  1341. LfnFlag,
  1342. NtAttributesToNwAttributes( Buffer->FileAttributes ),
  1343. Fcb->CreationDate,
  1344. Fcb->CreationTime,
  1345. Fcb->LastModifiedDate,
  1346. Fcb->LastModifiedTime,
  1347. 8,
  1348. Fcb->LastAccessDate,
  1349. 8,
  1350. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1351. Fcb->Vcb->Specific.Disk.Handle,
  1352. 0,
  1353. &Fcb->RelativeFileName );
  1354. } else {
  1355. if ( LfnFlag & LFN_FLAG_SET_INFO_ATTRIBUTES ) {
  1356. Status = ExchangeWithWait(
  1357. pIrpContext,
  1358. SynchronousResponseCallback,
  1359. "FbbbU",
  1360. NCP_SET_FILE_ATTRIBUTES,
  1361. NtAttributesToNwAttributes( Buffer->FileAttributes ),
  1362. Fcb->Vcb->Specific.Disk.Handle,
  1363. Fcb->NodeTypeCode == NW_NTC_FCB ?
  1364. SEARCH_ALL_FILES : SEARCH_ALL_DIRECTORIES,
  1365. &Fcb->RelativeFileName );
  1366. if ( !NT_SUCCESS( Status ) ) {
  1367. NwReleaseFcb( Fcb->NonPagedFcb );
  1368. return( Status );
  1369. }
  1370. }
  1371. #if 0
  1372. //
  1373. // We could conceivably use ScanDir/SetDir to update last access
  1374. // and create time. Not supported yet.
  1375. //
  1376. if ( LfnFlag & ( LFN_FLAG_SET_INFO_LASTACCESS_DATE | LFN_FLAG_SET_INFO_CREATE_DATE ) ) {
  1377. ULONG SearchIndex;
  1378. ULONG Directory;
  1379. Status = ExchangeWithWait(
  1380. pIrpContext,
  1381. SynchronousResponseCallback,
  1382. "SbbdU",
  1383. 0x16, 0x1E, // Scan dir entry
  1384. Fcb->Vcb->Specific.Disk.Handle,
  1385. 0x06, // Search attributes
  1386. -1, // Search index
  1387. &Fcb->RelativeFileName );
  1388. if ( NT_SUCCESS( Status ) ) {
  1389. Status = ParseResponse(
  1390. pIrpContext,
  1391. pIrpContext->rsp,
  1392. pIrpContext->ResponseLength,
  1393. "Ndd",
  1394. &SearchIndex,
  1395. &Directory );
  1396. }
  1397. if ( NT_SUCCESS( Status ) ) {
  1398. Status = ExchangeWithWait(
  1399. pIrpContext,
  1400. SynchronousResponseCallback,
  1401. "Sbbdddw=----_ww==ww==ww",
  1402. 0x16, 0x25, // Set dir entry
  1403. Fcb->Vcb->Specific.Disk.Handle,
  1404. 0x06, // Search attributes
  1405. SearchIndex,
  1406. 0, // Change Bits?
  1407. Directory,
  1408. 12,
  1409. Fcb->CreationDate,
  1410. 0,
  1411. Fcb->LastAccessDate,
  1412. 0,
  1413. Fcb->LastModifiedDate,
  1414. Fcb->LastModifiedTime );
  1415. }
  1416. }
  1417. #endif
  1418. if ( LfnFlag & LFN_FLAG_SET_INFO_MODIFY_DATE ) {
  1419. Status = ExchangeWithWait(
  1420. pIrpContext,
  1421. SynchronousResponseCallback,
  1422. "F-rww-",
  1423. NCP_SET_FILE_TIME,
  1424. &Icb->Handle, sizeof( Icb->Handle ),
  1425. Fcb->LastModifiedTime,
  1426. Fcb->LastModifiedDate );
  1427. }
  1428. }
  1429. NwReleaseFcb( Fcb->NonPagedFcb );
  1430. //
  1431. // And return to our caller
  1432. //
  1433. return Status;
  1434. }
  1435. NTSTATUS
  1436. NwSetDispositionInfo (
  1437. IN PIRP_CONTEXT pIrpContext,
  1438. IN PICB Icb,
  1439. IN PFILE_DISPOSITION_INFORMATION Buffer
  1440. )
  1441. /*++
  1442. Routine Description:
  1443. This routine sets the disposition information for a file.
  1444. Arguments:
  1445. pIrpContext - Supplies Irp context information.
  1446. Icb - Supplies the ICB for the file being modified.
  1447. Buffer - Supplies the buffer containing the data being set.
  1448. Return Value:
  1449. NTSTATUS - Returns our completion status.
  1450. --*/
  1451. {
  1452. PFCB Fcb;
  1453. NTSTATUS Status;
  1454. PAGED_CODE();
  1455. DebugTrace(0, Dbg, "SetDispositionInfo...\n", 0);
  1456. Fcb = Icb->SuperType.Fcb;
  1457. if ( FlagOn( Fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  1458. //
  1459. // This is a print queue, just pretend this IRP succeeded.
  1460. //
  1461. Status = STATUS_SUCCESS;
  1462. } else {
  1463. //
  1464. // This is a real file or directory. Mark it delete pending.
  1465. //
  1466. SetFlag( Fcb->Flags, FCB_FLAGS_DELETE_ON_CLOSE );
  1467. pIrpContext->pNpScb = Fcb->Scb->pNpScb;
  1468. pIrpContext->Icb = Icb;
  1469. Icb->State = ICB_STATE_CLOSE_PENDING;
  1470. //
  1471. // Go ahead, delete the file.
  1472. //
  1473. Status = NwDeleteFile( pIrpContext );
  1474. }
  1475. return( Status );
  1476. }
  1477. NTSTATUS
  1478. NwDeleteFile(
  1479. PIRP_CONTEXT pIrpContext
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. This routine continues processing of the SetDispositionInfo request.
  1484. It must run in the redirector FSP.
  1485. Arguments:
  1486. pIrpContext - A pointer to the IRP context information for the
  1487. request in progress.
  1488. Return Value:
  1489. The status of the operation.
  1490. --*/
  1491. {
  1492. PICB Icb;
  1493. PFCB Fcb;
  1494. NTSTATUS Status;
  1495. PAGED_CODE();
  1496. Icb = pIrpContext->Icb;
  1497. Fcb = Icb->SuperType.Fcb;
  1498. ClearFlag( Fcb->Flags, FCB_FLAGS_DELETE_ON_CLOSE );
  1499. //
  1500. // To a delete a file, first close the remote handle.
  1501. //
  1502. if ( Icb->HasRemoteHandle ) {
  1503. Icb->HasRemoteHandle = FALSE;
  1504. Status = ExchangeWithWait(
  1505. pIrpContext,
  1506. SynchronousResponseCallback,
  1507. "F-r",
  1508. NCP_CLOSE,
  1509. Icb->Handle, sizeof( Icb->Handle ) );
  1510. }
  1511. //
  1512. // Note that this request cannot be reconnectable since, it can
  1513. // be called via NwCloseIcb(). See comment in that routine for
  1514. // more info.
  1515. //
  1516. if ( Fcb->NodeTypeCode == NW_NTC_FCB ) {
  1517. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1518. Status = ExchangeWithWait(
  1519. pIrpContext,
  1520. SynchronousResponseCallback,
  1521. "FbbJ",
  1522. NCP_DELETE_FILE,
  1523. Fcb->Vcb->Specific.Disk.Handle,
  1524. SEARCH_ALL_FILES,
  1525. &Fcb->RelativeFileName );
  1526. } else {
  1527. Status = ExchangeWithWait(
  1528. pIrpContext,
  1529. SynchronousResponseCallback,
  1530. "LbbW-DbC",
  1531. NCP_LFN_DELETE_FILE,
  1532. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1533. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1534. NW_ATTRIBUTE_SYSTEM | NW_ATTRIBUTE_HIDDEN,
  1535. Fcb->Vcb->Specific.Disk.Handle,
  1536. LFN_FLAG_SHORT_DIRECTORY,
  1537. &Fcb->RelativeFileName );
  1538. }
  1539. } else {
  1540. ASSERT( Fcb->NodeTypeCode == NW_NTC_DCB );
  1541. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1542. Status = ExchangeWithWait(
  1543. pIrpContext,
  1544. SynchronousResponseCallback,
  1545. "SbbJ",
  1546. NCP_DIR_FUNCTION, NCP_DELETE_DIRECTORY,
  1547. Fcb->Vcb->Specific.Disk.Handle,
  1548. SEARCH_ALL_DIRECTORIES,
  1549. &Fcb->RelativeFileName );
  1550. } else {
  1551. Status = ExchangeWithWait(
  1552. pIrpContext,
  1553. SynchronousResponseCallback,
  1554. "LbbW-DbC",
  1555. NCP_LFN_DELETE_FILE,
  1556. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1557. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1558. SEARCH_ALL_DIRECTORIES,
  1559. Fcb->Vcb->Specific.Disk.Handle,
  1560. LFN_FLAG_SHORT_DIRECTORY,
  1561. &Fcb->RelativeFileName );
  1562. }
  1563. }
  1564. if ( NT_SUCCESS( Status )) {
  1565. Status = ParseResponse(
  1566. pIrpContext,
  1567. pIrpContext->rsp,
  1568. pIrpContext->ResponseLength,
  1569. "N" );
  1570. } else {
  1571. //
  1572. // We can map all failures to STATUS_NO_SUCH_FILE
  1573. // except ACCESS_DENIED, which happens with a read
  1574. // only file.
  1575. //
  1576. if ( Status != STATUS_ACCESS_DENIED ) {
  1577. Status = STATUS_NO_SUCH_FILE;
  1578. }
  1579. }
  1580. return Status;
  1581. }
  1582. NTSTATUS
  1583. NwSetRenameInfo (
  1584. IN PIRP_CONTEXT IrpContext,
  1585. IN PICB Icb,
  1586. IN PFILE_RENAME_INFORMATION Buffer
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. This routine set rename information for a file.
  1591. Arguments:
  1592. pIrpContext - A pointer to the IRP context information for the
  1593. request in progress.
  1594. Icb - A pointer to the ICB of the file to set.
  1595. Buffer - The request buffer.
  1596. Return Value:
  1597. The status of the operation.
  1598. --*/
  1599. {
  1600. PIRP Irp;
  1601. PIO_STACK_LOCATION irpSp;
  1602. NTSTATUS Status;
  1603. NTSTATUS Status2;
  1604. PFCB Fcb;
  1605. PFCB TargetFcb;
  1606. BOOLEAN HandleAllocated = FALSE;
  1607. BYTE Handle;
  1608. PICB TargetIcb = NULL;
  1609. UNICODE_STRING OldDrive;
  1610. UNICODE_STRING OldServer;
  1611. UNICODE_STRING OldVolume;
  1612. UNICODE_STRING OldPath;
  1613. UNICODE_STRING OldFileName;
  1614. UNICODE_STRING OldFullName;
  1615. WCHAR OldDriveLetter;
  1616. UNICODE_STRING OldFcbFullName;
  1617. UNICODE_STRING NewDrive;
  1618. UNICODE_STRING NewServer;
  1619. UNICODE_STRING NewVolume;
  1620. UNICODE_STRING NewPath;
  1621. UNICODE_STRING NewFileName;
  1622. UNICODE_STRING NewFullName;
  1623. WCHAR NewDriveLetter;
  1624. UNICODE_STRING NewFcbFullName;
  1625. USHORT i;
  1626. PAGED_CODE();
  1627. DebugTrace(+1, Dbg, "SetRenameInfo...\n", 0);
  1628. //
  1629. // Can't try to set rename info on a print queue.
  1630. //
  1631. Fcb = Icb->SuperType.Fcb;
  1632. if ( FlagOn( Fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  1633. return( STATUS_INVALID_PARAMETER );
  1634. }
  1635. //
  1636. // It is ok to attempt a reconnect if this request fails with a
  1637. // connection error.
  1638. //
  1639. SetFlag( IrpContext->Flags, IRP_FLAG_RECONNECTABLE );
  1640. //
  1641. // Get the current stack location.
  1642. //
  1643. Irp = IrpContext->pOriginalIrp;
  1644. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1645. DebugTrace( 0, Dbg, " ->FullFileName = %wZ\n",
  1646. &Fcb->FullFileName);
  1647. if (irpSp->Parameters.SetFile.FileObject != NULL) {
  1648. TargetIcb = irpSp->Parameters.SetFile.FileObject->FsContext2;
  1649. DebugTrace( 0, Dbg, " ->FullFileName = %wZ\n",
  1650. &TargetIcb->SuperType.Fcb->FullFileName);
  1651. if ( TargetIcb->SuperType.Fcb->Scb != Icb->SuperType.Fcb->Scb ) {
  1652. return STATUS_NOT_SAME_DEVICE;
  1653. }
  1654. } else {
  1655. DebugTrace( 0, Dbg, " ->FullFileName in users buffer\n", 0);
  1656. DebugTrace(-1, Dbg, "SetRenameInfo %08lx\n", STATUS_NOT_IMPLEMENTED);
  1657. return STATUS_NOT_IMPLEMENTED;
  1658. }
  1659. DebugTrace( 0, Dbg, " ->TargetFileName = %wZ\n",
  1660. &irpSp->Parameters.SetFile.FileObject->FileName);
  1661. TargetFcb = ((PNONPAGED_FCB)irpSp->Parameters.SetFile.FileObject->FsContext)->Fcb;
  1662. IrpContext->pNpScb = Fcb->Scb->pNpScb;
  1663. NwAppendToQueueAndWait( IrpContext );
  1664. NwAcquireExclusiveFcb( Fcb->NonPagedFcb, TRUE );
  1665. try {
  1666. //
  1667. // If either source or destination is a long name, use
  1668. // the long name path.
  1669. //
  1670. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) &&
  1671. IsFatNameValid( &TargetFcb->RelativeFileName ) &&
  1672. !BooleanFlagOn( Fcb->Vcb->Flags, VCB_FLAG_LONG_NAME ) ) {
  1673. //
  1674. // Strip to UID portion of the FCB name.
  1675. //
  1676. for ( i = 0 ; i < Fcb->FullFileName.Length / sizeof(WCHAR) ; i++ ) {
  1677. if ( Fcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR ) {
  1678. break;
  1679. }
  1680. }
  1681. ASSERT( Fcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR );
  1682. OldFcbFullName.Length = Fcb->FullFileName.Length - i*sizeof(WCHAR);
  1683. OldFcbFullName.Buffer = Fcb->FullFileName.Buffer + i;
  1684. Status = CrackPath (
  1685. &OldFcbFullName,
  1686. &OldDrive,
  1687. &OldDriveLetter,
  1688. &OldServer,
  1689. &OldVolume,
  1690. &OldPath,
  1691. &OldFileName,
  1692. &OldFullName );
  1693. ASSERT(NT_SUCCESS(Status));
  1694. //
  1695. // Strip to UID portion of the FCB name.
  1696. //
  1697. TargetFcb = ((PNONPAGED_FCB)(irpSp->Parameters.SetFile.FileObject->FsContext))->Fcb;
  1698. for ( i = 0 ; i < TargetFcb->FullFileName.Length / sizeof(WCHAR) ; i++ ) {
  1699. if ( TargetFcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR ) {
  1700. break;
  1701. }
  1702. }
  1703. ASSERT( TargetFcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR );
  1704. NewFcbFullName.Length = TargetFcb->FullFileName.Length - i*sizeof(WCHAR);
  1705. NewFcbFullName.Buffer = TargetFcb->FullFileName.Buffer + i;
  1706. Status = CrackPath (
  1707. &NewFcbFullName,
  1708. &NewDrive,
  1709. &NewDriveLetter,
  1710. &NewServer,
  1711. &NewVolume,
  1712. &NewPath,
  1713. &NewFileName,
  1714. &NewFullName );
  1715. ASSERT(NT_SUCCESS(Status));
  1716. //
  1717. // Make sure that this is the same volume.
  1718. //
  1719. if ( RtlCompareUnicodeString( &NewVolume, &OldVolume, TRUE ) != 0 ) {
  1720. try_return( Status = STATUS_NOT_SAME_DEVICE );
  1721. }
  1722. if (Icb->SuperType.Fcb->IcbCount != 1) {
  1723. try_return( Status = STATUS_ACCESS_DENIED );
  1724. }
  1725. //
  1726. // After a rename, the only operation allowed on the handle is an
  1727. // NtClose.
  1728. //
  1729. Icb->State = ICB_STATE_CLOSE_PENDING;
  1730. if ((irpSp->Parameters.SetFile.ReplaceIfExists ) &&
  1731. (TargetIcb->Exists)) {
  1732. // Delete the file
  1733. Status2 = ExchangeWithWait(
  1734. IrpContext,
  1735. SynchronousResponseCallback,
  1736. "Fb-J",
  1737. NCP_DELETE_FILE,
  1738. TargetFcb->Vcb->Specific.Disk.Handle,
  1739. &TargetFcb->RelativeFileName );
  1740. #ifdef NWDBG
  1741. if ( NT_SUCCESS( Status2 ) ) {
  1742. Status2 = ParseResponse(
  1743. IrpContext,
  1744. IrpContext->rsp,
  1745. IrpContext->ResponseLength,
  1746. "N" );
  1747. }
  1748. ASSERT(NT_SUCCESS(Status2));
  1749. #endif
  1750. }
  1751. //
  1752. // Need to create a handle to the directory containing the old
  1753. // file/directory name because directory rename does not contain a
  1754. // path and there might not be room for two paths in a file rename.
  1755. //
  1756. // The way we do this is to allocate a temporary handle on the server.
  1757. // This request is at the front of the Scb->Requests queue and so can
  1758. // use the temporary handle and delete it without affecting any other
  1759. // requests.
  1760. //
  1761. if ( OldPath.Length == 0 ) {
  1762. // In the root so use the VCB handle.
  1763. Handle = Fcb->Vcb->Specific.Disk.Handle;
  1764. } else {
  1765. Status = ExchangeWithWait (
  1766. IrpContext,
  1767. SynchronousResponseCallback,
  1768. "SbbJ", // NCP Allocate temporary directory handle
  1769. NCP_DIR_FUNCTION, NCP_ALLOCATE_TEMP_DIR_HANDLE,
  1770. Fcb->Vcb->Specific.Disk.Handle,
  1771. '[',
  1772. &OldPath );
  1773. if ( NT_SUCCESS( Status ) ) {
  1774. Status = ParseResponse(
  1775. IrpContext,
  1776. IrpContext->rsp,
  1777. IrpContext->ResponseLength,
  1778. "Nb",
  1779. &Handle );
  1780. }
  1781. if (!NT_SUCCESS(Status)) {
  1782. try_return(Status);
  1783. }
  1784. HandleAllocated = TRUE;
  1785. }
  1786. if ( Fcb->NodeTypeCode == NW_NTC_DCB ) {
  1787. //
  1788. // We can only rename files in the same directory
  1789. //
  1790. if ( RtlCompareUnicodeString( &NewPath, &OldPath, TRUE ) != 0 ) {
  1791. try_return(Status = STATUS_NOT_SUPPORTED);
  1792. } else {
  1793. Status = ExchangeWithWait ( IrpContext,
  1794. SynchronousResponseCallback,
  1795. "SbJJ",
  1796. NCP_DIR_FUNCTION, NCP_RENAME_DIRECTORY,
  1797. Handle,
  1798. &OldFileName,
  1799. &NewFileName);
  1800. }
  1801. } else {
  1802. //
  1803. // We have to close the handle associated with the Icb that
  1804. // is doing the rename. Close that handle or the rename will
  1805. // fail for sure.
  1806. //
  1807. if ( Icb->HasRemoteHandle ) {
  1808. Status2 = ExchangeWithWait(
  1809. IrpContext,
  1810. SynchronousResponseCallback,
  1811. "F-r",
  1812. NCP_CLOSE,
  1813. Icb->Handle, sizeof( Icb->Handle ) );
  1814. Icb->HasRemoteHandle = FALSE;
  1815. #ifdef NWDBG
  1816. if ( NT_SUCCESS( Status2 ) ) {
  1817. Status2 = ParseResponse(
  1818. IrpContext,
  1819. IrpContext->rsp,
  1820. IrpContext->ResponseLength,
  1821. "N" );
  1822. }
  1823. ASSERT(NT_SUCCESS(Status2));
  1824. #endif
  1825. }
  1826. //
  1827. // Do the file rename Ncp.
  1828. //
  1829. Status = ExchangeWithWait (
  1830. IrpContext,
  1831. SynchronousResponseCallback,
  1832. "FbbJbJ",
  1833. NCP_RENAME_FILE,
  1834. Handle,
  1835. SEARCH_ALL_FILES,
  1836. &OldFileName,
  1837. Fcb->Vcb->Specific.Disk.Handle,
  1838. &NewFullName);
  1839. }
  1840. } else {
  1841. //
  1842. // We are going through the long name path. Ensure that the
  1843. // VCB supports long names.
  1844. //
  1845. if ( Icb->SuperType.Fcb->Vcb->Specific.Disk.LongNameSpace ==
  1846. LFN_NO_OS2_NAME_SPACE) {
  1847. try_return( Status = STATUS_OBJECT_PATH_SYNTAX_BAD );
  1848. }
  1849. if (Icb->SuperType.Fcb->IcbCount != 1) {
  1850. try_return( Status = STATUS_ACCESS_DENIED);
  1851. }
  1852. //
  1853. // After a rename, the only operation allowed on the handle is an
  1854. // NtClose.
  1855. //
  1856. Icb->State = ICB_STATE_CLOSE_PENDING;
  1857. if ((irpSp->Parameters.SetFile.ReplaceIfExists ) &&
  1858. (TargetIcb->Exists)) {
  1859. // Delete the file
  1860. Status = ExchangeWithWait(
  1861. IrpContext,
  1862. SynchronousResponseCallback,
  1863. "LbbW-DbC",
  1864. NCP_LFN_DELETE_FILE,
  1865. TargetFcb->Vcb->Specific.Disk.LongNameSpace,
  1866. TargetFcb->Vcb->Specific.Disk.VolumeNumber,
  1867. SEARCH_ALL_FILES,
  1868. TargetFcb->Vcb->Specific.Disk.Handle,
  1869. LFN_FLAG_SHORT_DIRECTORY,
  1870. &TargetFcb->RelativeFileName );
  1871. #ifdef NWDBG
  1872. if ( NT_SUCCESS( Status ) ) {
  1873. Status2 = ParseResponse(
  1874. IrpContext,
  1875. IrpContext->rsp,
  1876. IrpContext->ResponseLength,
  1877. "N" );
  1878. }
  1879. ASSERT(NT_SUCCESS(Status2));
  1880. #endif
  1881. }
  1882. if ( Fcb->NodeTypeCode == NW_NTC_DCB ) {
  1883. //
  1884. // We can only rename files in the same directory
  1885. //
  1886. if ( Fcb->Vcb != TargetFcb->Vcb ) {
  1887. try_return(Status = STATUS_NOT_SUPPORTED);
  1888. } else {
  1889. Status = ExchangeWithWait (
  1890. IrpContext,
  1891. SynchronousResponseCallback,
  1892. "LbbWbDbbbDbbNN",
  1893. NCP_LFN_RENAME_FILE,
  1894. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1895. 0, // Rename flag
  1896. SEARCH_ALL_DIRECTORIES,
  1897. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1898. Fcb->Vcb->Specific.Disk.Handle,
  1899. LFN_FLAG_SHORT_DIRECTORY,
  1900. OccurenceCount( &Fcb->RelativeFileName, OBJ_NAME_PATH_SEPARATOR ) + 1,
  1901. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1902. Fcb->Vcb->Specific.Disk.Handle,
  1903. LFN_FLAG_SHORT_DIRECTORY,
  1904. OccurenceCount( &TargetFcb->RelativeFileName, OBJ_NAME_PATH_SEPARATOR ) + 1,
  1905. &Fcb->RelativeFileName,
  1906. &TargetFcb->RelativeFileName );
  1907. }
  1908. } else {
  1909. //
  1910. // We have to close the handle associated with the Icb that
  1911. // is doing the rename. Close that handle or the rename will
  1912. // fail for sure.
  1913. //
  1914. if ( Icb->HasRemoteHandle ) {
  1915. Status2 = ExchangeWithWait(
  1916. IrpContext,
  1917. SynchronousResponseCallback,
  1918. "F-r",
  1919. NCP_CLOSE,
  1920. Icb->Handle, sizeof( Icb->Handle ) );
  1921. Icb->HasRemoteHandle = FALSE;
  1922. #ifdef NWDBG
  1923. if ( NT_SUCCESS( Status2 ) ) {
  1924. Status2 = ParseResponse(
  1925. IrpContext,
  1926. IrpContext->rsp,
  1927. IrpContext->ResponseLength,
  1928. "N" );
  1929. }
  1930. ASSERT(NT_SUCCESS(Status2));
  1931. #endif
  1932. }
  1933. //
  1934. // Do the file rename Ncp.
  1935. //
  1936. Status = ExchangeWithWait (
  1937. IrpContext,
  1938. SynchronousResponseCallback,
  1939. "LbbWbDbbbDbbNN",
  1940. NCP_LFN_RENAME_FILE,
  1941. Fcb->Vcb->Specific.Disk.LongNameSpace,
  1942. 0, // Rename flag
  1943. SEARCH_ALL_FILES,
  1944. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1945. Fcb->Vcb->Specific.Disk.Handle,
  1946. LFN_FLAG_SHORT_DIRECTORY,
  1947. OccurenceCount( &Fcb->RelativeFileName, OBJ_NAME_PATH_SEPARATOR ) + 1,
  1948. Fcb->Vcb->Specific.Disk.VolumeNumber,
  1949. Fcb->Vcb->Specific.Disk.Handle,
  1950. LFN_FLAG_SHORT_DIRECTORY,
  1951. OccurenceCount( &TargetFcb->RelativeFileName, OBJ_NAME_PATH_SEPARATOR ) + 1,
  1952. &Fcb->RelativeFileName,
  1953. &TargetFcb->RelativeFileName );
  1954. }
  1955. }
  1956. try_exit: NOTHING;
  1957. } finally {
  1958. if (HandleAllocated) {
  1959. Status2 = ExchangeWithWait (
  1960. IrpContext,
  1961. SynchronousResponseCallback,
  1962. "Sb", // NCP Deallocate directory handle
  1963. NCP_DIR_FUNCTION, NCP_DEALLOCATE_DIR_HANDLE,
  1964. Handle);
  1965. #ifdef NWDBG
  1966. if ( NT_SUCCESS( Status2 ) ) {
  1967. Status2 = ParseResponse(
  1968. IrpContext,
  1969. IrpContext->rsp,
  1970. IrpContext->ResponseLength,
  1971. "N" );
  1972. }
  1973. ASSERT(NT_SUCCESS(Status2));
  1974. #endif
  1975. }
  1976. NwReleaseFcb( Fcb->NonPagedFcb );
  1977. }
  1978. DebugTrace(-1, Dbg, "SetRenameInfo %08lx\n", Status );
  1979. //
  1980. // We're done with this request. Dequeue the IRP context from
  1981. // SCB and complete the request.
  1982. //
  1983. if ( Status != STATUS_PENDING ) {
  1984. NwDequeueIrpContext( IrpContext, FALSE );
  1985. }
  1986. return Status;
  1987. }
  1988. NTSTATUS
  1989. NwSetPositionInfo (
  1990. IN PIRP_CONTEXT IrpContext,
  1991. IN PICB Icb,
  1992. IN PFILE_POSITION_INFORMATION Buffer
  1993. )
  1994. /*++
  1995. Routine Description:
  1996. This routine sets position information for a file.
  1997. Arguments:
  1998. pIrpContext - A pointer to the IRP context information for the
  1999. request in progress.
  2000. Icb - A pointer to the ICB of the file to set.
  2001. Buffer - The request buffer.
  2002. Return Value:
  2003. The status of the operation.
  2004. --*/
  2005. {
  2006. PAGED_CODE();
  2007. ASSERT( Buffer->CurrentByteOffset.HighPart == 0 );
  2008. if ( Icb->FileObject ) {
  2009. Icb->FileObject->CurrentByteOffset.QuadPart = Buffer->CurrentByteOffset.QuadPart;
  2010. }
  2011. return( STATUS_SUCCESS );
  2012. }
  2013. NTSTATUS
  2014. NwSetAllocationInfo (
  2015. IN PIRP_CONTEXT IrpContext,
  2016. IN PICB Icb,
  2017. IN PFILE_ALLOCATION_INFORMATION Buffer
  2018. )
  2019. /*++
  2020. Routine Description:
  2021. This routine sets allocation information for a file.
  2022. Arguments:
  2023. pIrpContext - A pointer to the IRP context information for the
  2024. request in progress.
  2025. Icb - A pointer to the ICB of the file to set.
  2026. Buffer - The request buffer.
  2027. Return Value:
  2028. The status of the operation.
  2029. --*/
  2030. {
  2031. NTSTATUS Status;
  2032. PIRP irp;
  2033. PIO_STACK_LOCATION irpSp;
  2034. PFCB fcb = (PFCB)Icb->SuperType.Fcb;
  2035. PULONG pFileSize;
  2036. PAGED_CODE();
  2037. ASSERT( Buffer->AllocationSize.HighPart == 0);
  2038. if ( fcb->NodeTypeCode == NW_NTC_FCB ) {
  2039. pFileSize = &Icb->NpFcb->Header.FileSize.LowPart;
  2040. IrpContext->pNpScb = fcb->Scb->pNpScb;
  2041. if (BooleanFlagOn( fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  2042. if (IsTerminalServer()) {
  2043. // 2/10/97 cjc Fix problem for binary files not printing correctly
  2044. // if done via the COPY command. Works with NT RDR so
  2045. // changed this to behave same way.
  2046. return(STATUS_INVALID_PARAMETER);
  2047. } else {
  2048. return STATUS_SUCCESS;
  2049. }
  2050. }
  2051. } else if ( fcb->NodeTypeCode == NW_NTC_SCB ) {
  2052. pFileSize = &Icb->FileSize;
  2053. IrpContext->pNpScb = ((PSCB)fcb)->pNpScb;
  2054. } else {
  2055. DebugTrace(0, Dbg, "Not a file or a server\n", 0);
  2056. DebugTrace( 0, Dbg, "NwSetAllocationInfo -> %08lx\n", STATUS_INVALID_PARAMETER );
  2057. return STATUS_INVALID_PARAMETER;
  2058. }
  2059. NwAppendToQueueAndWait( IrpContext );
  2060. if ( !Icb->HasRemoteHandle ) {
  2061. Status = STATUS_INVALID_PARAMETER;
  2062. } else if ( Buffer->AllocationSize.LowPart == *pFileSize ) {
  2063. Status = STATUS_SUCCESS;
  2064. } else {
  2065. irp = IrpContext->pOriginalIrp;
  2066. irpSp = IoGetCurrentIrpStackLocation( irp );
  2067. #ifndef QFE_BUILD
  2068. if ( Buffer->AllocationSize.LowPart < *pFileSize ) {
  2069. //
  2070. // Before we actually truncate, check to see if the purge
  2071. // is going to fail.
  2072. //
  2073. if (!MmCanFileBeTruncated( irpSp->FileObject->SectionObjectPointer,
  2074. &Buffer->AllocationSize )) {
  2075. return( STATUS_USER_MAPPED_FILE );
  2076. }
  2077. }
  2078. #endif
  2079. if ( fcb->NodeTypeCode == NW_NTC_FCB ) {
  2080. AcquireFcbAndFlushCache( IrpContext, fcb->NonPagedFcb );
  2081. }
  2082. Status = ExchangeWithWait(
  2083. IrpContext,
  2084. SynchronousResponseCallback,
  2085. "F-rd=",
  2086. NCP_WRITE_FILE,
  2087. &Icb->Handle, sizeof( Icb->Handle ),
  2088. Buffer->AllocationSize.LowPart );
  2089. if ( NT_SUCCESS( Status ) ) {
  2090. *pFileSize = Buffer->AllocationSize.LowPart;
  2091. }
  2092. }
  2093. NwDequeueIrpContext( IrpContext, FALSE );
  2094. return( Status );
  2095. }
  2096. NTSTATUS
  2097. NwSetEndOfFileInfo (
  2098. IN PIRP_CONTEXT IrpContext,
  2099. IN PICB Icb,
  2100. IN PFILE_END_OF_FILE_INFORMATION Buffer
  2101. )
  2102. /*++
  2103. Routine Description:
  2104. This routine sets end of file information for a file.
  2105. Arguments:
  2106. pIrpContext - A pointer to the IRP context information for the
  2107. request in progress.
  2108. Icb - A pointer to the ICB of the file to set.
  2109. Buffer - The request buffer.
  2110. Return Value:
  2111. The status of the operation.
  2112. --*/
  2113. {
  2114. NTSTATUS Status;
  2115. PIRP irp;
  2116. PIO_STACK_LOCATION irpSp;
  2117. PFCB fcb = (PFCB)Icb->SuperType.Fcb;
  2118. PULONG pFileSize;
  2119. PAGED_CODE();
  2120. ASSERT( Buffer->EndOfFile.HighPart == 0);
  2121. if ( fcb->NodeTypeCode == NW_NTC_FCB ) {
  2122. pFileSize = &Icb->NpFcb->Header.FileSize.LowPart;
  2123. IrpContext->pNpScb = fcb->Scb->pNpScb;
  2124. if (BooleanFlagOn( fcb->Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  2125. return STATUS_SUCCESS;
  2126. }
  2127. } else if ( fcb->NodeTypeCode == NW_NTC_SCB ) {
  2128. pFileSize = &Icb->FileSize;
  2129. IrpContext->pNpScb = ((PSCB)fcb)->pNpScb;
  2130. } else {
  2131. DebugTrace(0, Dbg, "Not a file or a server\n", 0);
  2132. DebugTrace( 0, Dbg, "NwSetAllocationInfo -> %08lx\n", STATUS_INVALID_PARAMETER );
  2133. return STATUS_INVALID_PARAMETER;
  2134. }
  2135. NwAppendToQueueAndWait( IrpContext );
  2136. if ( !Icb->HasRemoteHandle ) {
  2137. Status = STATUS_INVALID_PARAMETER;
  2138. } else if ( Buffer->EndOfFile.LowPart == *pFileSize ) {
  2139. Status = STATUS_SUCCESS;
  2140. } else {
  2141. irp = IrpContext->pOriginalIrp;
  2142. irpSp = IoGetCurrentIrpStackLocation( irp );
  2143. #ifndef QFE_BUILD
  2144. if ( Buffer->EndOfFile.LowPart < *pFileSize ) {
  2145. //
  2146. // Before we actually truncate, check to see if the purge
  2147. // is going to fail.
  2148. //
  2149. if (!MmCanFileBeTruncated( irpSp->FileObject->SectionObjectPointer,
  2150. &Buffer->EndOfFile )) {
  2151. return( STATUS_USER_MAPPED_FILE );
  2152. }
  2153. }
  2154. #endif
  2155. if ( fcb->NodeTypeCode == NW_NTC_FCB ) {
  2156. AcquireFcbAndFlushCache( IrpContext, fcb->NonPagedFcb );
  2157. }
  2158. Status = ExchangeWithWait(
  2159. IrpContext,
  2160. SynchronousResponseCallback,
  2161. "F-rd=",
  2162. NCP_WRITE_FILE,
  2163. &Icb->Handle, sizeof( Icb->Handle ),
  2164. Buffer->EndOfFile.LowPart );
  2165. if ( NT_SUCCESS( Status ) ) {
  2166. *pFileSize = Buffer->EndOfFile.LowPart;
  2167. }
  2168. }
  2169. NwDequeueIrpContext( IrpContext, FALSE );
  2170. return( Status );
  2171. }
  2172. ULONG
  2173. OccurenceCount (
  2174. IN PUNICODE_STRING String,
  2175. IN WCHAR SearchChar
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. This routine counts the number of occurences of a search character
  2180. in a string
  2181. Arguments:
  2182. String - The string to search
  2183. SearchChar - The character to search for.
  2184. Return Value:
  2185. The occurence count.
  2186. --*/
  2187. {
  2188. PWCH currentChar;
  2189. PWCH endOfString;
  2190. ULONG count = 0;
  2191. PAGED_CODE();
  2192. currentChar = String->Buffer;
  2193. endOfString = &String->Buffer[ String->Length / sizeof(WCHAR) ];
  2194. while ( currentChar < endOfString ) {
  2195. if ( *currentChar == SearchChar ) {
  2196. count++;
  2197. }
  2198. currentChar++;
  2199. }
  2200. return( count );
  2201. }