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.

975 lines
26 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. if (!SynchronousCmds) {
  381. NtTerminateThread( 0, STATUS_SUCCESS );
  382. }
  383. }
  384. VOID
  385. InputDisplayQVolume (
  386. IN PCHAR ParamBuffer
  387. )
  388. {
  389. FILE_INFORMATION_CLASS FileInfoClass;
  390. ULONG BufferIndex;
  391. BOOLEAN ParamReceived;
  392. BOOLEAN LastInput;
  393. //
  394. // Set the defaults.
  395. //
  396. BufferIndex = DISPLAY_INDEX_DEFAULT;
  397. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  398. ParamReceived = FALSE;
  399. LastInput = TRUE;
  400. //
  401. // While there is more input, analyze the parameter and update the
  402. // query flags.
  403. //
  404. while (TRUE) {
  405. ULONG DummyCount;
  406. //
  407. // Swallow leading white spaces.
  408. //
  409. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  410. if (*ParamBuffer) {
  411. //
  412. // If the next parameter is legal then check the paramter value.
  413. // Update the parameter value.
  414. //
  415. if ((*ParamBuffer == '-'
  416. || *ParamBuffer == '/')
  417. && (ParamBuffer++, *ParamBuffer != '\0')) {
  418. BOOLEAN SwitchBool;
  419. //
  420. // Switch on the next character.
  421. //
  422. switch( *ParamBuffer ) {
  423. //
  424. // Check the buffer index.
  425. //
  426. case 'b' :
  427. case 'B' :
  428. //
  429. // Move to the next character, as long as there
  430. // are no white spaces continue analyzing letters.
  431. // On the first bad letter, skip to the next
  432. // parameter.
  433. //
  434. ParamBuffer++;
  435. BufferIndex = AsciiToInteger( ParamBuffer );
  436. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  437. ParamReceived = TRUE;
  438. break;
  439. //
  440. // Update the desired access.
  441. //
  442. case 'c' :
  443. case 'C' :
  444. //
  445. // Move to the next character, as long as there
  446. // are no white spaces continue analyzing letters.
  447. // On the first bad letter, skip to the next
  448. // parameter.
  449. //
  450. ParamBuffer++;
  451. SwitchBool = TRUE;
  452. while (*ParamBuffer
  453. && *ParamBuffer != ' '
  454. && *ParamBuffer != '\t') {
  455. //
  456. // Perform switch on character.
  457. //
  458. switch (*ParamBuffer) {
  459. case 'a' :
  460. case 'A' :
  461. FileInfoClass = FileFsVolumeInformation;
  462. break;
  463. case 'b' :
  464. case 'B' :
  465. FileInfoClass = FileFsSizeInformation;
  466. break;
  467. case 'c' :
  468. case 'C' :
  469. FileInfoClass = FileFsDeviceInformation;
  470. break;
  471. case 'd' :
  472. case 'D' :
  473. FileInfoClass = FileFsAttributeInformation;
  474. break;
  475. default :
  476. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  477. SwitchBool = FALSE;
  478. }
  479. if (!SwitchBool) {
  480. break;
  481. }
  482. ParamBuffer++;
  483. }
  484. break;
  485. default :
  486. //
  487. // Swallow to the next white space and continue the
  488. // loop.
  489. //
  490. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  491. }
  492. }
  493. //
  494. // Else the text is invalid, skip the entire block.
  495. //
  496. //
  497. //
  498. // Else if there is no input then exit.
  499. //
  500. } else if ( LastInput ) {
  501. break;
  502. //
  503. // Else try to read another line for open parameters.
  504. //
  505. } else {
  506. }
  507. }
  508. //
  509. // If no parameters were received then display the syntax message.
  510. //
  511. if (!ParamReceived) {
  512. printf( "\n Usage: dqv [options]* -b<digits> [options]*\n" );
  513. printf( "\n Options:" );
  514. printf( "\n -b<digits> Buffer index" );
  515. printf( "\n -c<char> Key to buffer format" );
  516. printf( "\n\n" );
  517. //
  518. // Else call our display buffer routine.
  519. //
  520. } else {
  521. switch (FileInfoClass) {
  522. case FileFsVolumeInformation :
  523. DisplayFsVolumeInformation( (USHORT) BufferIndex );
  524. break;
  525. case FileFsSizeInformation:
  526. DisplayFsSizeInformation( (USHORT) BufferIndex );
  527. break;
  528. case FileFsDeviceInformation:
  529. DisplayFsDeviceInformation( (USHORT) BufferIndex );
  530. break;
  531. case FileFsAttributeInformation:
  532. DisplayFsAttributeInformation( (USHORT) BufferIndex );
  533. break;
  534. }
  535. }
  536. }
  537. VOID
  538. DisplayFsVolumeInformation (
  539. IN USHORT BufferIndex
  540. )
  541. {
  542. PFILE_FS_VOLUME_INFORMATION FileInfo;
  543. NTSTATUS Status;
  544. ANSI_STRING AnsiString;
  545. UNICODE_STRING UnicodeString;
  546. BOOLEAN UnwindFreeAnsiString = FALSE;
  547. if (!Buffers[BufferIndex].Used) {
  548. printf( "\nDisplayFsVolumeInformation: Invalid buffer\n" );
  549. return;
  550. }
  551. try {
  552. FileInfo = (PFILE_FS_VOLUME_INFORMATION) Buffers[BufferIndex].Buffer;
  553. printf( "\n\nFs Volume Information\n" );
  554. printf( "\n\tVolume Creation Time -> " );
  555. PrintTime( &FileInfo->VolumeCreationTime );
  556. printf( "\n\tVolume Serial Number -> %08lx", FileInfo->VolumeSerialNumber );
  557. printf( "\n\tVolume Label Length -> %08d", FileInfo->VolumeLabelLength );
  558. printf( "\n\tVolume Supports Objects -> %01d", FileInfo->SupportsObjects );
  559. UnicodeString.MaximumLength =
  560. UnicodeString.Length = (USHORT) FileInfo->VolumeLabelLength;
  561. UnicodeString.Buffer = (PWSTR) &FileInfo->VolumeLabel;
  562. UnicodeString.MaximumLength += 2;
  563. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  564. &UnicodeString,
  565. TRUE );
  566. if (!NT_SUCCESS( Status )) {
  567. printf( "\nDisplay Volume Information: Unable to allocate Ansi -> %08lx\n", Status );
  568. try_return( NOTHING );
  569. }
  570. UnwindFreeAnsiString = TRUE;
  571. printf( "\n\tVolume Label -> %s", AnsiString.Buffer );
  572. printf( "\n" );
  573. try_return( NOTHING );
  574. try_exit: NOTHING;
  575. } finally {
  576. if (AbnormalTermination()) {
  577. printf( "\nDisplayFsVolumeInformation: AbnormalTermination\n" );
  578. }
  579. if (UnwindFreeAnsiString) {
  580. RtlFreeAnsiString( &AnsiString );
  581. }
  582. }
  583. return;
  584. }
  585. VOID
  586. DisplayFsSizeInformation (
  587. IN USHORT BufferIndex
  588. )
  589. {
  590. PFILE_FS_SIZE_INFORMATION FileInfo;
  591. if (!Buffers[BufferIndex].Used) {
  592. printf( "\nDisplayFsSizeInformation: Invalid buffer\n" );
  593. return;
  594. }
  595. try {
  596. FileInfo = (PFILE_FS_SIZE_INFORMATION) Buffers[BufferIndex].Buffer;
  597. printf( "\n\nFs Size Information\n" );
  598. printf( "\n\tTotal Allocation Units -> " );
  599. PrintLargeInteger( &FileInfo->TotalAllocationUnits );
  600. printf( "\n\tAvail Allocation Units -> " );
  601. PrintLargeInteger( &FileInfo->AvailableAllocationUnits );
  602. printf( "\n\tSectors Per Alloc Unit -> %08lx", FileInfo->SectorsPerAllocationUnit );
  603. printf( "\n\tBytes Per Sector -> %08lx", FileInfo->BytesPerSector );
  604. printf( "\n" );
  605. try_return( NOTHING );
  606. try_exit: NOTHING;
  607. } finally {
  608. if (AbnormalTermination()) {
  609. printf( "\nDisplayFsSizeInformation: AbnormalTermination\n" );
  610. }
  611. }
  612. return;
  613. }
  614. VOID
  615. DisplayFsDeviceInformation (
  616. IN USHORT BufferIndex
  617. )
  618. {
  619. PFILE_FS_DEVICE_INFORMATION FileInfo;
  620. if (!Buffers[BufferIndex].Used) {
  621. printf( "\nDisplayFsDeviceInformation: Invalid buffer\n" );
  622. return;
  623. }
  624. try {
  625. FileInfo = (PFILE_FS_DEVICE_INFORMATION) Buffers[BufferIndex].Buffer;
  626. printf( "\n\nFs Device Information\n" );
  627. printf( "\n\tDevice Type -> %08lx", FileInfo->DeviceType );
  628. printf( "\n\tCharacteristics -> %08lx", FileInfo->Characteristics );
  629. printf( "\n" );
  630. try_return( NOTHING );
  631. try_exit: NOTHING;
  632. } finally {
  633. if (AbnormalTermination()) {
  634. printf( "\nDisplayFsDeviceInformation: AbnormalTermination\n" );
  635. }
  636. }
  637. return;
  638. }
  639. VOID
  640. DisplayFsAttributeInformation (
  641. IN USHORT BufferIndex
  642. )
  643. {
  644. PFILE_FS_ATTRIBUTE_INFORMATION FileInfo;
  645. NTSTATUS Status;
  646. ANSI_STRING AnsiString;
  647. UNICODE_STRING UnicodeString;
  648. BOOLEAN UnwindFreeAnsiString = FALSE;
  649. if (!Buffers[BufferIndex].Used) {
  650. printf( "\nDisplayFsAttributeInformation: Invalid buffer\n" );
  651. return;
  652. }
  653. try {
  654. FileInfo = (PFILE_FS_ATTRIBUTE_INFORMATION) Buffers[BufferIndex].Buffer;
  655. printf( "\n\nFs Attribute Information\n" );
  656. printf( "\n\tFile System Attributes -> %08lx", FileInfo->FileSystemAttributes );
  657. printf( "\n\tMax Component Name Length -> %08d", FileInfo->MaximumComponentNameLength );
  658. printf( "\n\tFile System Name Length -> %08d", FileInfo->FileSystemNameLength );
  659. UnicodeString.MaximumLength =
  660. UnicodeString.Length = (USHORT) FileInfo->FileSystemNameLength;
  661. UnicodeString.Buffer = (PWSTR) &FileInfo->FileSystemName;
  662. UnicodeString.MaximumLength += 2;
  663. Status = RtlUnicodeStringToAnsiString( &AnsiString,
  664. &UnicodeString,
  665. TRUE );
  666. if (!NT_SUCCESS( Status )) {
  667. printf( "\nDisplay Fs Attribute Information: Unable to allocate Ansi -> %08lx\n", Status );
  668. try_return( NOTHING );
  669. }
  670. UnwindFreeAnsiString = TRUE;
  671. printf( "\n\tFile System Name -> %s", AnsiString.Buffer );
  672. printf( "\n" );
  673. try_return( NOTHING );
  674. try_exit: NOTHING;
  675. } finally {
  676. if (AbnormalTermination()) {
  677. printf( "\nDisplayFsAttributeInformation: AbnormalTermination\n" );
  678. }
  679. if (UnwindFreeAnsiString) {
  680. RtlFreeAnsiString( &AnsiString );
  681. }
  682. }
  683. return;
  684. }