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

972 lines
24 KiB

  1. #include "brian.h"
  2. typedef struct _ASYNC_QVOLUME {
  3. USHORT FileIndex;
  4. PUSHORT BufferIndexPtr;
  5. USHORT BufferIndex;
  6. ULONG Length;
  7. FILE_INFORMATION_CLASS FileInfoClass;
  8. BOOLEAN DisplayParms;
  9. BOOLEAN VerboseResults;
  10. USHORT AsyncIndex;
  11. } ASYNC_QVOLUME, *PASYNC_QVOLUME;
  12. #define QVOLUME_LENGTH_DEFAULT 100
  13. #define FILE_INFO_CLASS_DEFAULT FileFsVolumeInformation
  14. #define DISPLAY_PARMS_DEFAULT FALSE
  15. #define VERBOSE_DEFAULT FALSE
  16. #define DISPLAY_INDEX_DEFAULT 0
  17. VOID
  18. FullQVolume(
  19. IN OUT PASYNC_QVOLUME AsyncQVolume
  20. );
  21. VOID
  22. DisplayFsVolumeInformation (
  23. IN USHORT BufferIndex
  24. );
  25. VOID
  26. DisplayFsSizeInformation (
  27. IN USHORT BufferIndex
  28. );
  29. VOID
  30. DisplayFsDeviceInformation (
  31. IN USHORT BufferIndex
  32. );
  33. VOID
  34. DisplayFsAttributeInformation (
  35. IN USHORT BufferIndex
  36. );
  37. VOID
  38. InputQVolume (
  39. IN PCHAR ParamBuffer
  40. )
  41. {
  42. ULONG FileIndex;
  43. PUSHORT BufferIndexPtr;
  44. USHORT BufferIndex;
  45. ULONG Length;
  46. FILE_INFORMATION_CLASS FileInfoClass;
  47. BOOLEAN DisplayParms;
  48. BOOLEAN VerboseResults;
  49. USHORT AsyncIndex;
  50. BOOLEAN ParamReceived;
  51. BOOLEAN LastInput;
  52. //
  53. // Set the defaults.
  54. //
  55. BufferIndexPtr = NULL;
  56. BufferIndex = 0;
  57. Length = QVOLUME_LENGTH_DEFAULT;
  58. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  59. DisplayParms = DISPLAY_PARMS_DEFAULT;
  60. VerboseResults = VERBOSE_DEFAULT;
  61. AsyncIndex = 0;
  62. ParamReceived = FALSE;
  63. LastInput = TRUE;
  64. //
  65. // While there is more input, analyze the parameter and update the
  66. // query flags.
  67. //
  68. while (TRUE) {
  69. ULONG DummyCount;
  70. ULONG TempIndex;
  71. //
  72. // Swallow leading white spaces.
  73. //
  74. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  75. if (*ParamBuffer) {
  76. //
  77. // If the next parameter is legal then check the paramter value.
  78. // Update the parameter value.
  79. //
  80. if ((*ParamBuffer == '-'
  81. || *ParamBuffer == '/')
  82. && (ParamBuffer++, *ParamBuffer != '\0')) {
  83. BOOLEAN SwitchBool;
  84. //
  85. // Switch on the next character.
  86. //
  87. switch (*ParamBuffer) {
  88. //
  89. // Update the buffer index.
  90. //
  91. case 'b' :
  92. case 'B' :
  93. //
  94. // Move to the next character, as long as there
  95. // are no white spaces continue analyzing letters.
  96. // On the first bad letter, skip to the next
  97. // parameter.
  98. //
  99. ParamBuffer++;
  100. TempIndex = AsciiToInteger( ParamBuffer );
  101. BufferIndex = (USHORT) TempIndex;
  102. BufferIndexPtr = &BufferIndex;
  103. Length = Buffers[BufferIndex].Length;
  104. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  105. break;
  106. //
  107. // Update the byte count.
  108. //
  109. case 'l' :
  110. case 'L' :
  111. //
  112. // Move to the next character, as long as there
  113. // are no white spaces continue analyzing letters.
  114. // On the first bad letter, skip to the next
  115. // parameter.
  116. //
  117. ParamBuffer++;
  118. Length = AsciiToInteger( ParamBuffer );
  119. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  120. break;
  121. //
  122. // Update the file handle index.
  123. //
  124. case 'i' :
  125. case 'I' :
  126. //
  127. // Move to the next character, as long as there
  128. // are no white spaces continue analyzing letters.
  129. // On the first bad letter, skip to the next
  130. // parameter.
  131. //
  132. ParamBuffer++;
  133. FileIndex = AsciiToInteger( ParamBuffer );
  134. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  135. ParamReceived = TRUE;
  136. break;
  137. //
  138. // Update the information class.
  139. //
  140. case 'c' :
  141. case 'C' :
  142. //
  143. // Move to the next character, as long as there
  144. // are no white spaces continue analyzing letters.
  145. // On the first bad letter, skip to the next
  146. // parameter.
  147. //
  148. ParamBuffer++;
  149. SwitchBool = TRUE;
  150. while (*ParamBuffer
  151. && *ParamBuffer != ' '
  152. && *ParamBuffer != '\t') {
  153. //
  154. // Perform switch on character.
  155. //
  156. switch (*ParamBuffer) {
  157. case 'a' :
  158. case 'A' :
  159. FileInfoClass = FileFsVolumeInformation;
  160. break;
  161. case 'b' :
  162. case 'B' :
  163. FileInfoClass = FileFsSizeInformation;
  164. break;
  165. case 'c' :
  166. case 'C' :
  167. FileInfoClass = FileFsDeviceInformation;
  168. break;
  169. case 'd' :
  170. case 'D' :
  171. FileInfoClass = FileFsAttributeInformation;
  172. break;
  173. default :
  174. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  175. SwitchBool = FALSE;
  176. }
  177. if (!SwitchBool) {
  178. break;
  179. }
  180. ParamBuffer++;
  181. }
  182. break;
  183. case 'v' :
  184. case 'V' :
  185. //
  186. // Legal values for params are T/t or F/f.
  187. //
  188. ParamBuffer++;
  189. if( *ParamBuffer == 'T'
  190. || *ParamBuffer == 't' ) {
  191. VerboseResults = TRUE;
  192. ParamBuffer++;
  193. } else if( *ParamBuffer == 'F'
  194. || *ParamBuffer == 'f' ) {
  195. VerboseResults = FALSE;
  196. ParamBuffer++;
  197. }
  198. break;
  199. case 'y' :
  200. case 'Y' :
  201. //
  202. // Set the display parms flag and jump over this
  203. // character.
  204. //
  205. DisplayParms = TRUE;
  206. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  207. break;
  208. case 'z' :
  209. case 'Z' :
  210. //
  211. // Set flag for more input and jump over this char.
  212. //
  213. LastInput = FALSE;
  214. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  215. break;
  216. default :
  217. //
  218. // Swallow to the next white space and continue the
  219. // loop.
  220. //
  221. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  222. }
  223. }
  224. //
  225. // Else the text is invalid, skip the entire block.
  226. //
  227. //
  228. //
  229. // Else if there is no input then exit.
  230. //
  231. } else if( LastInput ) {
  232. break;
  233. //
  234. // Else try to read another line for open parameters.
  235. //
  236. } else {
  237. }
  238. }
  239. //
  240. // If no parameters were received then display the syntax message.
  241. //
  242. if (!ParamReceived) {
  243. printf( "\n Usage: qv [options]* -i<index> [options]*\n" );
  244. printf( "\n Options:" );
  245. printf( "\n -i<digits> File index" );
  246. printf( "\n -l<digits> Buffer length" );
  247. printf( "\n -b<digits> Buffer index" );
  248. printf( "\n -c<char> File information class" );
  249. printf( "\n -v[t|f] Verbose results" );
  250. printf( "\n -y Display parameters to query" );
  251. printf( "\n -z Additional input line" );
  252. printf( "\n\n" );
  253. //
  254. // Else call our read routine.
  255. //
  256. } else {
  257. NTSTATUS Status;
  258. SIZE_T RegionSize;
  259. ULONG TempIndex;
  260. PASYNC_QVOLUME AsyncQVolume;
  261. HANDLE ThreadHandle;
  262. ULONG ThreadId;
  263. RegionSize = sizeof( ASYNC_QVOLUME );
  264. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  265. AsyncIndex = (USHORT) TempIndex;
  266. if (!NT_SUCCESS( Status )) {
  267. printf("\n\tInputQVolume: Unable to allocate async structure" );
  268. } else {
  269. AsyncQVolume = (PASYNC_QVOLUME) Buffers[AsyncIndex].Buffer;
  270. AsyncQVolume->FileIndex = (USHORT) FileIndex;
  271. AsyncQVolume->BufferIndex = BufferIndex;
  272. AsyncQVolume->BufferIndexPtr = BufferIndexPtr
  273. ? &AsyncQVolume->BufferIndex
  274. : BufferIndexPtr;
  275. AsyncQVolume->Length = Length;
  276. AsyncQVolume->FileInfoClass = FileInfoClass;
  277. AsyncQVolume->DisplayParms = DisplayParms;
  278. AsyncQVolume->VerboseResults = VerboseResults;
  279. AsyncQVolume->AsyncIndex = AsyncIndex;
  280. if (!SynchronousCmds) {
  281. ThreadHandle = CreateThread( NULL,
  282. 0,
  283. FullQVolume,
  284. AsyncQVolume,
  285. 0,
  286. &ThreadId );
  287. if (ThreadHandle == 0) {
  288. printf( "\nInputQVolume: Spawning thread fails -> %d\n", GetLastError() );
  289. DeallocateBuffer( AsyncIndex );
  290. return;
  291. }
  292. } else {
  293. FullQVolume( AsyncQVolume );
  294. }
  295. }
  296. }
  297. return;
  298. }
  299. VOID
  300. FullQVolume(
  301. IN OUT PASYNC_QVOLUME AsyncQVolume
  302. )
  303. {
  304. NTSTATUS Status;
  305. IO_STATUS_BLOCK Iosb;
  306. USHORT ThisBufferIndex;
  307. BOOLEAN UnwindQVolumeBuffer = FALSE;
  308. Status = STATUS_SUCCESS;
  309. if (AsyncQVolume->DisplayParms) {
  310. bprint "\nQVolume Parameters" );
  311. bprint "\n File Handle Index -> %d", AsyncQVolume->FileIndex );
  312. bprint "\n Buffer Index Ptr -> %08lx", AsyncQVolume->BufferIndexPtr );
  313. if (AsyncQVolume->BufferIndexPtr) {
  314. bprint "\n BufferIndex value -> %04x", AsyncQVolume->BufferIndex );
  315. }
  316. bprint "\n Length -> %08lx", AsyncQVolume->Length );
  317. bprint "\n FileInfoClass -> %08lx", AsyncQVolume->FileInfoClass );
  318. bprint "\n\n" );
  319. }
  320. try {
  321. SIZE_T ThisLength;
  322. //
  323. // If we need a buffer, allocate it now.
  324. //
  325. if (AsyncQVolume->BufferIndexPtr == NULL) {
  326. ULONG TempIndex;
  327. ThisLength = 4096;
  328. Status = AllocateBuffer( 0L, &ThisLength, &TempIndex );
  329. ThisBufferIndex = (USHORT) TempIndex;
  330. if (!NT_SUCCESS( Status )) {
  331. bprint "\n\tFullQVolume: Unable to allocate a query buffer" );
  332. try_return( Status );
  333. }
  334. bprint "\n\tFullQVolume: Reading into buffer -> %04x\n", ThisBufferIndex );
  335. bprint "\n" );
  336. UnwindQVolumeBuffer = TRUE;
  337. AsyncQVolume->Length = (ULONG) ThisLength;
  338. } else {
  339. ThisBufferIndex = AsyncQVolume->BufferIndex;
  340. }
  341. //
  342. // Check that the buffer index is valid.
  343. //
  344. if (ThisBufferIndex >= MAX_BUFFERS) {
  345. bprint "\n\tFullQVolume: The read buffer index is invalid" );
  346. try_return( Status = STATUS_INVALID_HANDLE );
  347. }
  348. //
  349. // Check that the file index is valid.
  350. //
  351. if (AsyncQVolume->FileIndex >= MAX_HANDLES) {
  352. bprint "\n\tFullQVolume: The file index is invalid" );
  353. try_return( Status = STATUS_INVALID_HANDLE );
  354. }
  355. //
  356. // Call the query file routine.
  357. //
  358. Status = NtQueryVolumeInformationFile( Handles[AsyncQVolume->FileIndex].Handle,
  359. &Iosb,
  360. Buffers[ThisBufferIndex].Buffer,
  361. AsyncQVolume->Length,
  362. AsyncQVolume->FileInfoClass );
  363. UnwindQVolumeBuffer = FALSE;
  364. if (AsyncQVolume->VerboseResults) {
  365. bprint "\nQuery File: Status -> %08lx", Status );
  366. if (NT_SUCCESS( Status )) {
  367. bprint "\n Iosb.Information -> %08lx", Iosb.Information );
  368. bprint "\n Iosb.Status -> %08lx", Iosb.Status );
  369. }
  370. bprint "\n" );
  371. }
  372. try_return( Status );
  373. try_exit: NOTHING;
  374. } finally {
  375. if (UnwindQVolumeBuffer) {
  376. DeallocateBuffer( ThisBufferIndex );
  377. }
  378. DeallocateBuffer( AsyncQVolume->AsyncIndex );
  379. }
  380. NtTerminateThread( 0, STATUS_SUCCESS );
  381. }
  382. VOID
  383. InputDisplayQVolume (
  384. IN PCHAR ParamBuffer
  385. )
  386. {
  387. FILE_INFORMATION_CLASS FileInfoClass;
  388. ULONG BufferIndex;
  389. BOOLEAN ParamReceived;
  390. BOOLEAN LastInput;
  391. //
  392. // Set the defaults.
  393. //
  394. BufferIndex = DISPLAY_INDEX_DEFAULT;
  395. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  396. ParamReceived = FALSE;
  397. LastInput = TRUE;
  398. //
  399. // While there is more input, analyze the parameter and update the
  400. // query flags.
  401. //
  402. while (TRUE) {
  403. ULONG DummyCount;
  404. //
  405. // Swallow leading white spaces.
  406. //
  407. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  408. if (*ParamBuffer) {
  409. //
  410. // If the next parameter is legal then check the paramter value.
  411. // Update the parameter value.
  412. //
  413. if ((*ParamBuffer == '-'
  414. || *ParamBuffer == '/')
  415. && (ParamBuffer++, *ParamBuffer != '\0')) {
  416. BOOLEAN SwitchBool;
  417. //
  418. // Switch on the next character.
  419. //
  420. switch( *ParamBuffer ) {
  421. //
  422. // Check the buffer index.
  423. //
  424. case 'b' :
  425. case 'B' :
  426. //
  427. // Move to the next character, as long as there
  428. // are no white spaces continue analyzing letters.
  429. // On the first bad letter, skip to the next
  430. // parameter.
  431. //
  432. ParamBuffer++;
  433. BufferIndex = AsciiToInteger( ParamBuffer );
  434. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  435. ParamReceived = TRUE;
  436. break;
  437. //
  438. // Update the desired access.
  439. //
  440. case 'c' :
  441. case 'C' :
  442. //
  443. // Move to the next character, as long as there
  444. // are no white spaces continue analyzing letters.
  445. // On the first bad letter, skip to the next
  446. // parameter.
  447. //
  448. ParamBuffer++;
  449. SwitchBool = TRUE;
  450. while (*ParamBuffer
  451. && *ParamBuffer != ' '
  452. && *ParamBuffer != '\t') {
  453. //
  454. // Perform switch on character.
  455. //
  456. switch (*ParamBuffer) {
  457. case 'a' :
  458. case 'A' :
  459. FileInfoClass = FileFsVolumeInformation;
  460. break;
  461. case 'b' :
  462. case 'B' :
  463. FileInfoClass = FileFsSizeInformation;
  464. break;
  465. case 'c' :
  466. case 'C' :
  467. FileInfoClass = FileFsDeviceInformation;
  468. break;
  469. case 'd' :
  470. case 'D' :
  471. FileInfoClass = FileFsAttributeInformation;
  472. break;
  473. default :
  474. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  475. SwitchBool = FALSE;
  476. }
  477. if (!SwitchBool) {
  478. break;
  479. }
  480. ParamBuffer++;
  481. }
  482. break;
  483. default :
  484. //
  485. // Swallow to the next white space and continue the
  486. // loop.
  487. //
  488. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  489. }
  490. }
  491. //
  492. // Else the text is invalid, skip the entire block.
  493. //
  494. //
  495. //
  496. // Else if there is no input then exit.
  497. //
  498. } else if ( LastInput ) {
  499. break;
  500. //
  501. // Else try to read another line for open parameters.
  502. //
  503. } else {
  504. }
  505. }
  506. //
  507. // If no parameters were received then display the syntax message.
  508. //
  509. if (!ParamReceived) {
  510. printf( "\n Usage: dqv [options]* -b<digits> [options]*\n" );
  511. printf( "\n Options:" );
  512. printf( "\n -b<digits> Buffer index" );
  513. printf( "\n -c<char> Key to buffer format" );
  514. printf( "\n\n" );
  515. //
  516. // Else call our display buffer routine.
  517. //
  518. } else {
  519. switch (FileInfoClass) {
  520. case FileFsVolumeInformation :
  521. DisplayFsVolumeInformation( (USHORT) BufferIndex );
  522. break;
  523. case FileFsSizeInformation:
  524. DisplayFsSizeInformation( (USHORT) BufferIndex );
  525. break;
  526. case FileFsDeviceInformation:
  527. DisplayFsDeviceInformation( (USHORT) BufferIndex );
  528. break;
  529. case FileFsAttributeInformation:
  530. DisplayFsAttributeInformation( (USHORT) BufferIndex );
  531. break;
  532. }
  533. }
  534. }
  535. VOID
  536. DisplayFsVolumeInformation (
  537. IN USHORT BufferIndex
  538. )
  539. {
  540. PFILE_FS_VOLUME_INFORMATION FileInfo;
  541. NTSTATUS Status;
  542. ANSI_STRING AnsiString;
  543. UNICODE_STRING UnicodeString;
  544. BOOLEAN UnwindFreeAnsiString = FALSE;
  545. if (!Buffers[BufferIndex].Used) {
  546. printf( "\nDisplayFsVolumeInformation: Invalid buffer\n" );
  547. return;
  548. }
  549. try {
  550. FileInfo = (PFILE_FS_VOLUME_INFORMATION) Buffers[BufferIndex].Buffer;
  551. printf( "\n\nFs Volume Information\n" );
  552. printf( "\n\tVolume Creation Time -> " );
  553. PrintTime( &FileInfo->VolumeCreationTime );
  554. printf( "\n\tVolume Serial Number -> %08lx", FileInfo->VolumeSerialNumber );
  555. printf( "\n\tVolume Label Length -> %08d", FileInfo->VolumeLabelLength );
  556. printf( "\n\tVolume Supports Objects -> %01d", FileInfo->SupportsObjects );
  557. UnicodeString.MaximumLength =
  558. UnicodeString.Length = (USHORT) FileInfo->VolumeLabelLength;
  559. UnicodeString.Buffer = (PWSTR) &FileInfo->VolumeLabel;
  560. UnicodeString.MaximumLength += 2;
  561. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  562. &UnicodeString,
  563. TRUE );
  564. if (!NT_SUCCESS( Status )) {
  565. printf( "\nDisplay Volume Information: Unable to allocate Ansi -> %08lx\n", Status );
  566. try_return( NOTHING );
  567. }
  568. UnwindFreeAnsiString = TRUE;
  569. printf( "\n\tVolume Label -> %s", AnsiString.Buffer );
  570. printf( "\n" );
  571. try_return( NOTHING );
  572. try_exit: NOTHING;
  573. } finally {
  574. if (AbnormalTermination()) {
  575. printf( "\nDisplayFsVolumeInformation: AbnormalTermination\n" );
  576. }
  577. if (UnwindFreeAnsiString) {
  578. RtlFreeAnsiString( &AnsiString );
  579. }
  580. }
  581. return;
  582. }
  583. VOID
  584. DisplayFsSizeInformation (
  585. IN USHORT BufferIndex
  586. )
  587. {
  588. PFILE_FS_SIZE_INFORMATION FileInfo;
  589. if (!Buffers[BufferIndex].Used) {
  590. printf( "\nDisplayFsSizeInformation: Invalid buffer\n" );
  591. return;
  592. }
  593. try {
  594. FileInfo = (PFILE_FS_SIZE_INFORMATION) Buffers[BufferIndex].Buffer;
  595. printf( "\n\nFs Size Information\n" );
  596. printf( "\n\tTotal Allocation Units -> " );
  597. PrintLargeInteger( &FileInfo->TotalAllocationUnits );
  598. printf( "\n\tAvail Allocation Units -> " );
  599. PrintLargeInteger( &FileInfo->AvailableAllocationUnits );
  600. printf( "\n\tSectors Per Alloc Unit -> %08lx", FileInfo->SectorsPerAllocationUnit );
  601. printf( "\n\tBytes Per Sector -> %08lx", FileInfo->BytesPerSector );
  602. printf( "\n" );
  603. try_return( NOTHING );
  604. try_exit: NOTHING;
  605. } finally {
  606. if (AbnormalTermination()) {
  607. printf( "\nDisplayFsSizeInformation: AbnormalTermination\n" );
  608. }
  609. }
  610. return;
  611. }
  612. VOID
  613. DisplayFsDeviceInformation (
  614. IN USHORT BufferIndex
  615. )
  616. {
  617. PFILE_FS_DEVICE_INFORMATION FileInfo;
  618. if (!Buffers[BufferIndex].Used) {
  619. printf( "\nDisplayFsDeviceInformation: Invalid buffer\n" );
  620. return;
  621. }
  622. try {
  623. FileInfo = (PFILE_FS_DEVICE_INFORMATION) Buffers[BufferIndex].Buffer;
  624. printf( "\n\nFs Device Information\n" );
  625. printf( "\n\tDevice Type -> %08lx", FileInfo->DeviceType );
  626. printf( "\n\tCharacteristics -> %08lx", FileInfo->Characteristics );
  627. printf( "\n" );
  628. try_return( NOTHING );
  629. try_exit: NOTHING;
  630. } finally {
  631. if (AbnormalTermination()) {
  632. printf( "\nDisplayFsDeviceInformation: AbnormalTermination\n" );
  633. }
  634. }
  635. return;
  636. }
  637. VOID
  638. DisplayFsAttributeInformation (
  639. IN USHORT BufferIndex
  640. )
  641. {
  642. PFILE_FS_ATTRIBUTE_INFORMATION FileInfo;
  643. NTSTATUS Status;
  644. ANSI_STRING AnsiString;
  645. UNICODE_STRING UnicodeString;
  646. BOOLEAN UnwindFreeAnsiString = FALSE;
  647. if (!Buffers[BufferIndex].Used) {
  648. printf( "\nDisplayFsAttributeInformation: Invalid buffer\n" );
  649. return;
  650. }
  651. try {
  652. FileInfo = (PFILE_FS_ATTRIBUTE_INFORMATION) Buffers[BufferIndex].Buffer;
  653. printf( "\n\nFs Attribute Information\n" );
  654. printf( "\n\tFile System Attributes -> %08lx", FileInfo->FileSystemAttributes );
  655. printf( "\n\tMax Component Name Length -> %08d", FileInfo->MaximumComponentNameLength );
  656. printf( "\n\tFile System Name Length -> %08d", FileInfo->FileSystemNameLength );
  657. UnicodeString.MaximumLength =
  658. UnicodeString.Length = (USHORT) FileInfo->FileSystemNameLength;
  659. UnicodeString.Buffer = (PWSTR) &FileInfo->FileSystemName;
  660. UnicodeString.MaximumLength += 2;
  661. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  662. &UnicodeString,
  663. TRUE );
  664. if (!NT_SUCCESS( Status )) {
  665. printf( "\nDisplay Fs Attribute Information: Unable to allocate Ansi -> %08lx\n", Status );
  666. try_return( NOTHING );
  667. }
  668. UnwindFreeAnsiString = TRUE;
  669. printf( "\n\tFile System Name -> %s", AnsiString.Buffer );
  670. printf( "\n" );
  671. try_return( NOTHING );
  672. try_exit: NOTHING;
  673. } finally {
  674. if (AbnormalTermination()) {
  675. printf( "\nDisplayFsAttributeInformation: AbnormalTermination\n" );
  676. }
  677. if (UnwindFreeAnsiString) {
  678. RtlFreeAnsiString( &AnsiString );
  679. }
  680. }
  681. return;
  682. }