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.

1565 lines
44 KiB

  1. #include "brian.h"
  2. typedef struct _ASYNC_QDIR {
  3. USHORT FileIndex;
  4. BOOLEAN UseEvent;
  5. PIO_APC_ROUTINE ApcRoutine;
  6. PVOID ApcContext;
  7. PUSHORT BufferIndexPtr;
  8. USHORT BufferIndex;
  9. ULONG Length;
  10. FILE_INFORMATION_CLASS FileInfoClass;
  11. PUNICODE_STRING FileNamePtr;
  12. UNICODE_STRING FileName;
  13. BOOLEAN SingleEntry;
  14. BOOLEAN Restart;
  15. BOOLEAN DisplayParms;
  16. BOOLEAN VerboseResults;
  17. USHORT AsyncIndex;
  18. USHORT NameIndex;
  19. } ASYNC_QDIR, *PASYNC_QDIR;
  20. #define USE_EVENT_DEFAULT TRUE
  21. #define APC_ROUTINE_DEFAULT NULL
  22. #define APC_CONTEXT_DEFAULT NULL
  23. #define QDIR_LENGTH_DEFAULT 100
  24. #define FILE_INFO_CLASS_DEFAULT FileBothDirectoryInformation
  25. #define SINGLE_ENTRY_DEFAULT FALSE
  26. #define RESTART_DEFAULT FALSE
  27. #define DISPLAY_PARMS_DEFAULT FALSE
  28. #define VERBOSE_DEFAULT FALSE
  29. #define DISPLAY_INDEX_DEFAULT 0
  30. VOID
  31. FullQDir(
  32. IN OUT PASYNC_QDIR AsyncQDir
  33. );
  34. VOID
  35. InputQDir (
  36. IN PCHAR ParamBuffer
  37. )
  38. {
  39. ULONG FileIndex;
  40. BOOLEAN UseEvent;
  41. PIO_APC_ROUTINE ApcRoutine;
  42. PVOID ApcContext;
  43. PUSHORT BufferIndexPtr;
  44. USHORT BufferIndex;
  45. ULONG Length;
  46. FILE_INFORMATION_CLASS FileInfoClass;
  47. PUNICODE_STRING FileNamePtr;
  48. UNICODE_STRING FileName;
  49. USHORT FileNameIndex;
  50. BOOLEAN SingleEntry;
  51. BOOLEAN Restart;
  52. BOOLEAN DisplayParms;
  53. BOOLEAN VerboseResults;
  54. USHORT AsyncIndex;
  55. PUCHAR FileNamePChar;
  56. BOOLEAN NameIndexAllocated;
  57. BOOLEAN ParamReceived;
  58. BOOLEAN LastInput;
  59. //
  60. // Set the defaults.
  61. //
  62. UseEvent = USE_EVENT_DEFAULT;
  63. ApcRoutine = APC_ROUTINE_DEFAULT;
  64. ApcContext = APC_CONTEXT_DEFAULT;
  65. BufferIndexPtr = NULL;
  66. BufferIndex = 0;
  67. Length = QDIR_LENGTH_DEFAULT;
  68. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  69. FileNamePtr = NULL;
  70. FileNameIndex = 0;
  71. SingleEntry = SINGLE_ENTRY_DEFAULT;
  72. Restart = RESTART_DEFAULT;
  73. DisplayParms = DISPLAY_PARMS_DEFAULT;
  74. VerboseResults = VERBOSE_DEFAULT;
  75. AsyncIndex = 0;
  76. NameIndexAllocated = FALSE;
  77. ParamReceived = FALSE;
  78. LastInput = TRUE;
  79. //
  80. // While there is more input, analyze the parameter and update the
  81. // query flags.
  82. //
  83. {
  84. NTSTATUS Status;
  85. SIZE_T RegionSize;
  86. ULONG TempIndex;
  87. RegionSize = 256;
  88. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  89. if (!NT_SUCCESS( Status )) {
  90. printf("\nInputQdir: Can't allocate name index buffer" );
  91. return;
  92. }
  93. NameIndexAllocated = TRUE;
  94. FileNameIndex = (USHORT) TempIndex;
  95. FileName.Length = 256;
  96. FileName.MaximumLength = 256;
  97. FileName.Buffer = (PWSTR) Buffers[FileNameIndex].Buffer;
  98. }
  99. while (TRUE) {
  100. ULONG DummyCount;
  101. ULONG TempIndex;
  102. //
  103. // Swallow leading white spaces.
  104. //
  105. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  106. if (*ParamBuffer) {
  107. //
  108. // If the next parameter is legal then check the paramter value.
  109. // Update the parameter value.
  110. //
  111. if ((*ParamBuffer == '-'
  112. || *ParamBuffer == '/')
  113. && (ParamBuffer++, *ParamBuffer != '\0')) {
  114. BOOLEAN SwitchBool;
  115. //
  116. // Switch on the next character.
  117. //
  118. switch (*ParamBuffer) {
  119. //
  120. // Update the buffer index.
  121. //
  122. case 'b' :
  123. case 'B' :
  124. //
  125. // Move to the next character, as long as there
  126. // are no white spaces continue analyzing letters.
  127. // On the first bad letter, skip to the next
  128. // parameter.
  129. //
  130. ParamBuffer++;
  131. TempIndex = AsciiToInteger( ParamBuffer );
  132. BufferIndex = (USHORT) TempIndex;
  133. BufferIndexPtr = &BufferIndex;
  134. Length = Buffers[BufferIndex].Length;
  135. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  136. break;
  137. //
  138. // Update the byte count.
  139. //
  140. case 'l' :
  141. case 'L' :
  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. Length = AsciiToInteger( ParamBuffer );
  150. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  151. break;
  152. //
  153. // Update the file handle index.
  154. //
  155. case 'i' :
  156. case 'I' :
  157. //
  158. // Move to the next character, as long as there
  159. // are no white spaces continue analyzing letters.
  160. // On the first bad letter, skip to the next
  161. // parameter.
  162. //
  163. ParamBuffer++;
  164. FileIndex = AsciiToInteger( ParamBuffer );
  165. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  166. ParamReceived = TRUE;
  167. break;
  168. //
  169. // Check whether we should use an event to signal
  170. // completion.
  171. //
  172. case 'e' :
  173. case 'E' :
  174. //
  175. // Legal values for use event are T/t or F/f.
  176. //
  177. ParamBuffer++;
  178. if (*ParamBuffer == 'T'
  179. || *ParamBuffer == 't') {
  180. UseEvent = TRUE;
  181. ParamBuffer++;
  182. } else if (*ParamBuffer == 'F'
  183. || *ParamBuffer == 'f') {
  184. UseEvent = FALSE;
  185. ParamBuffer++;
  186. }
  187. break;
  188. //
  189. // Check whether we want only a single entry.
  190. //
  191. case 's' :
  192. case 'S' :
  193. //
  194. // Legal values for use event are T/t or F/f.
  195. //
  196. ParamBuffer++;
  197. if (*ParamBuffer == 'T'
  198. || *ParamBuffer == 't') {
  199. SingleEntry = TRUE;
  200. ParamBuffer++;
  201. } else if (*ParamBuffer == 'F'
  202. || *ParamBuffer == 'f') {
  203. SingleEntry = FALSE;
  204. ParamBuffer++;
  205. }
  206. break;
  207. //
  208. // Check whether we want to restart the scan.
  209. //
  210. case 'r' :
  211. case 'R' :
  212. //
  213. // Legal values for use event are T/t or F/f.
  214. //
  215. ParamBuffer++;
  216. if (*ParamBuffer == 'T'
  217. || *ParamBuffer == 't') {
  218. Restart = TRUE;
  219. ParamBuffer++;
  220. } else if (*ParamBuffer == 'F'
  221. || *ParamBuffer == 'f') {
  222. Restart = FALSE;
  223. ParamBuffer++;
  224. }
  225. break;
  226. //
  227. // Get the filename.
  228. //
  229. case 'f' :
  230. case 'F' :
  231. //
  232. // Remember the buffer offset and get the filename.
  233. //
  234. ParamBuffer++;
  235. FileNamePChar = ParamBuffer;
  236. DummyCount = 0;
  237. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  238. //
  239. // If the name length is 0, then ignore this entry.
  240. //
  241. if (DummyCount) {
  242. ANSI_STRING AnsiString;
  243. AnsiString.Length = (USHORT) DummyCount;
  244. AnsiString.Buffer = FileNamePChar;
  245. RtlAnsiStringToUnicodeString( &FileName,
  246. &AnsiString,
  247. FALSE );
  248. FileNamePtr = (PUNICODE_STRING) &FileName;
  249. }
  250. break;
  251. //
  252. // Update the desired access.
  253. //
  254. case 'c' :
  255. case 'C' :
  256. //
  257. // Move to the next character, as long as there
  258. // are no white spaces continue analyzing letters.
  259. // On the first bad letter, skip to the next
  260. // parameter.
  261. //
  262. ParamBuffer++;
  263. SwitchBool = TRUE;
  264. while (*ParamBuffer
  265. && *ParamBuffer != ' '
  266. && *ParamBuffer != '\t') {
  267. //
  268. // Perform switch on character.
  269. //
  270. switch (*ParamBuffer) {
  271. case 'a' :
  272. case 'A' :
  273. FileInfoClass = FileNamesInformation;
  274. break;
  275. case 'b' :
  276. case 'B' :
  277. FileInfoClass = FileDirectoryInformation;
  278. break;
  279. case 'c' :
  280. case 'C' :
  281. FileInfoClass = FileFullDirectoryInformation;
  282. break;
  283. case 'd' :
  284. case 'D' :
  285. FileInfoClass = FileIdFullDirectoryInformation;
  286. break;
  287. case 'e' :
  288. case 'E' :
  289. FileInfoClass = FileBothDirectoryInformation;
  290. break;
  291. case 'f' :
  292. case 'F' :
  293. FileInfoClass = FileIdBothDirectoryInformation;
  294. break;
  295. case 'g' :
  296. case 'G' :
  297. FileInfoClass = FileObjectIdInformation;
  298. break;
  299. case 'h' :
  300. case 'H' :
  301. FileInfoClass = FileQuotaInformation;
  302. break;
  303. case 'i' :
  304. case 'I' :
  305. FileInfoClass = FileReparsePointInformation;
  306. break;
  307. default :
  308. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  309. SwitchBool = FALSE;
  310. }
  311. if (!SwitchBool) {
  312. break;
  313. }
  314. ParamBuffer++;
  315. }
  316. break;
  317. case 'v' :
  318. case 'V' :
  319. //
  320. // Legal values for params are T/t or F/f.
  321. //
  322. ParamBuffer++;
  323. if( *ParamBuffer == 'T'
  324. || *ParamBuffer == 't' ) {
  325. VerboseResults = TRUE;
  326. ParamBuffer++;
  327. } else if( *ParamBuffer == 'F'
  328. || *ParamBuffer == 'f' ) {
  329. VerboseResults = FALSE;
  330. ParamBuffer++;
  331. }
  332. break;
  333. case 'y' :
  334. case 'Y' :
  335. //
  336. // Set the display parms flag and jump over this
  337. // character.
  338. //
  339. DisplayParms = TRUE;
  340. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  341. break;
  342. case 'z' :
  343. case 'Z' :
  344. //
  345. // Set flag for more input and jump over this char.
  346. //
  347. LastInput = FALSE;
  348. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  349. break;
  350. default :
  351. //
  352. // Swallow to the next white space and continue the
  353. // loop.
  354. //
  355. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  356. }
  357. }
  358. //
  359. // Else the text is invalid, skip the entire block.
  360. //
  361. //
  362. //
  363. // Else if there is no input then exit.
  364. //
  365. } else if( LastInput ) {
  366. break;
  367. //
  368. // Else try to read another line for open parameters.
  369. //
  370. } else {
  371. }
  372. }
  373. //
  374. // If no parameters were received then display the syntax message.
  375. //
  376. if (!ParamReceived) {
  377. printf( "\n Usage: qd [options]* -i<index> [options]*\n" );
  378. printf( "\n Options:" );
  379. printf( "\n -i<digits> File index" );
  380. printf( "\n -l<digits> Buffer length" );
  381. printf( "\n -b<digits> Buffer index" );
  382. printf( "\n -f<chars> Search expression" );
  383. printf( "\n -c<char> File information class" );
  384. printf( "\n a FileNamesInformation" );
  385. printf( "\n b FileDirectoryInformation" );
  386. printf( "\n c FileFullDirectoryInformation" );
  387. printf( "\n d FileIdFullDirectoryInformation" );
  388. printf( "\n e FileBothDirectoryInformation" );
  389. printf( "\n f FileIdBothObjectIdInformation" );
  390. printf( "\n g FileObjectIdInformation" );
  391. printf( "\n h FileQuotaInformation" );
  392. printf( "\n i FileReparsePointInformation" );
  393. printf( "\n -e[t|f] Use event on completion" );
  394. printf( "\n -r[t|f] Restart the search" );
  395. printf( "\n -s[t|f] Return single entry" );
  396. printf( "\n -v[t|f] Verbose results" );
  397. printf( "\n -y Display parameters to query" );
  398. printf( "\n -z Additional input line" );
  399. printf( "\n\n" );
  400. //
  401. // Else call our read routine.
  402. //
  403. } else {
  404. NTSTATUS Status;
  405. SIZE_T RegionSize;
  406. ULONG TempIndex;
  407. PASYNC_QDIR AsyncQDir;
  408. HANDLE ThreadHandle;
  409. ULONG ThreadId;
  410. RegionSize = sizeof( ASYNC_QDIR );
  411. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  412. AsyncIndex = (USHORT) TempIndex;
  413. if (!NT_SUCCESS( Status )) {
  414. printf("\n\tInputQDir: Unable to allocate async structure" );
  415. } else {
  416. AsyncQDir = (PASYNC_QDIR) Buffers[AsyncIndex].Buffer;
  417. AsyncQDir->FileIndex = (USHORT) FileIndex;
  418. AsyncQDir->UseEvent = UseEvent;
  419. AsyncQDir->ApcRoutine = ApcRoutine;
  420. AsyncQDir->ApcContext = ApcContext;
  421. AsyncQDir->BufferIndex = BufferIndex;
  422. AsyncQDir->BufferIndexPtr = BufferIndexPtr
  423. ? &AsyncQDir->BufferIndex
  424. : BufferIndexPtr;
  425. AsyncQDir->Length = Length;
  426. AsyncQDir->FileInfoClass = FileInfoClass;
  427. AsyncQDir->FileName = FileName;
  428. AsyncQDir->FileNamePtr = FileNamePtr
  429. ? &AsyncQDir->FileName
  430. : NULL;
  431. AsyncQDir->SingleEntry = SingleEntry;
  432. AsyncQDir->Restart = Restart;
  433. AsyncQDir->DisplayParms = DisplayParms;
  434. AsyncQDir->VerboseResults = VerboseResults;
  435. AsyncQDir->AsyncIndex = AsyncIndex;
  436. AsyncQDir->NameIndex = FileNameIndex;
  437. if (!SynchronousCmds) {
  438. ThreadHandle = CreateThread( NULL,
  439. 0,
  440. FullQDir,
  441. AsyncQDir,
  442. 0,
  443. &ThreadId );
  444. if (ThreadHandle == 0) {
  445. printf( "\nInputQDir: Spawning thread fails -> %d\n", GetLastError() );
  446. if (AsyncQDir->FileNamePtr) {
  447. DeallocateBuffer( FileNameIndex );
  448. }
  449. DeallocateBuffer( AsyncIndex );
  450. return;
  451. }
  452. } else {
  453. FullQDir( AsyncQDir );
  454. }
  455. }
  456. }
  457. return;
  458. }
  459. VOID
  460. FullQDir(
  461. IN OUT PASYNC_QDIR AsyncQDir
  462. )
  463. {
  464. NTSTATUS Status;
  465. IO_STATUS_BLOCK Iosb;
  466. HANDLE ThisEvent;
  467. USHORT ThisEventIndex;
  468. USHORT ThisBufferIndex;
  469. BOOLEAN UnwindQDirBuffer = FALSE;
  470. BOOLEAN UnwindEvent = FALSE;
  471. Status = STATUS_SUCCESS;
  472. if (AsyncQDir->DisplayParms) {
  473. bprint "\n" );
  474. bprint " QDir Parameters\n" );
  475. bprint " File Handle Index -> %d\n", AsyncQDir->FileIndex );
  476. bprint " UseEvent -> %d\n", AsyncQDir->UseEvent );
  477. bprint " ApcRoutine -> %08lx\n", AsyncQDir->ApcRoutine );
  478. bprint " ApcContext -> %08lx\n", AsyncQDir->ApcContext );
  479. bprint " Buffer Index Ptr -> %08lx\n", AsyncQDir->BufferIndexPtr );
  480. if (AsyncQDir->BufferIndexPtr) {
  481. bprint " BufferIndex value -> %04x\n", AsyncQDir->BufferIndex );
  482. }
  483. bprint " Length -> %08lx\n", AsyncQDir->Length );
  484. bprint " FileInfoClass -> %08lx\n", AsyncQDir->FileInfoClass );
  485. bprint " FileNamePtr -> %08lx\n", AsyncQDir->FileNamePtr );
  486. if (AsyncQDir->FileNamePtr) {
  487. bprint " Filename -> %s\n", AsyncQDir->FileName.Buffer );
  488. }
  489. bprint " Single Entry -> %04x\n", AsyncQDir->SingleEntry );
  490. bprint " Restart Scan -> %04x\n", AsyncQDir->SingleEntry );
  491. bprint "\n" );
  492. }
  493. try {
  494. SIZE_T ThisLength;
  495. //
  496. // If we need a buffer, allocate it now.
  497. //
  498. if (AsyncQDir->BufferIndexPtr == NULL) {
  499. ULONG TempIndex;
  500. ThisLength = 4096;
  501. Status = AllocateBuffer( 0L, &ThisLength, &TempIndex );
  502. ThisBufferIndex = (USHORT) TempIndex;
  503. if (!NT_SUCCESS( Status )) {
  504. bprint "\n" );
  505. bprint "\tFullQDir: Unable to allocate a query buffer\n" );
  506. try_return( Status );
  507. }
  508. bprint "\tFullQDir: Reading into buffer -> %04x\n", ThisBufferIndex );
  509. bprint "\n" );
  510. bprint "\n" );
  511. UnwindQDirBuffer = TRUE;
  512. AsyncQDir->Length = (ULONG) ThisLength;
  513. } else {
  514. ThisBufferIndex = AsyncQDir->BufferIndex;
  515. }
  516. //
  517. // Check that the buffer index is valid.
  518. //
  519. if (ThisBufferIndex >= MAX_BUFFERS) {
  520. bprint "\n" );
  521. bprint "\tFullQDir: The read buffer index is invalid\n" );
  522. try_return( Status = STATUS_INVALID_HANDLE );
  523. }
  524. //
  525. // Check that the file index is valid.
  526. //
  527. if (AsyncQDir->FileIndex >= MAX_HANDLES) {
  528. bprint "\n" );
  529. bprint "\tFullQDir: The file index is invalid\n" );
  530. try_return( Status = STATUS_INVALID_HANDLE );
  531. }
  532. //
  533. // If we need an event, allocate and set it now.
  534. //
  535. if (AsyncQDir->UseEvent == TRUE) {
  536. Status = ObtainEvent( &ThisEventIndex );
  537. if (!NT_SUCCESS( Status )) {
  538. bprint "\n" );
  539. bprint "\tFullQDir: Unable to allocate an event\n" );
  540. try_return( Status );
  541. }
  542. UnwindEvent = TRUE;
  543. ThisEvent = Events[ThisEventIndex].Handle;
  544. } else {
  545. ThisEvent = 0;
  546. }
  547. //
  548. // Call the read routine.
  549. //
  550. Status = NtQueryDirectoryFile( Handles[AsyncQDir->FileIndex].Handle,
  551. ThisEvent,
  552. AsyncQDir->ApcRoutine,
  553. AsyncQDir->ApcContext,
  554. &Iosb,
  555. Buffers[ThisBufferIndex].Buffer,
  556. AsyncQDir->Length,
  557. AsyncQDir->FileInfoClass,
  558. AsyncQDir->SingleEntry,
  559. AsyncQDir->FileNamePtr,
  560. AsyncQDir->Restart );
  561. UnwindQDirBuffer = FALSE;
  562. if (AsyncQDir->VerboseResults) {
  563. bprint "\n" );
  564. bprint " Query Dir: Status -> %08lx\n", Status );
  565. if (AsyncQDir->UseEvent && NT_SUCCESS( Status )) {
  566. if ((Status = NtWaitForSingleObject( ThisEvent,
  567. FALSE,
  568. NULL )) != STATUS_SUCCESS) {
  569. bprint "\n" );
  570. bprint "\tQuery Dir: Wait for event failed -> %08lx", Status );
  571. bprint "\n" );
  572. try_return( Status );
  573. }
  574. }
  575. if (NT_SUCCESS( Status )) {
  576. bprint "\n" );
  577. bprint " Iosb.Information -> %08lx\n", Iosb.Information );
  578. bprint " Iosb.Status -> %08lx", Iosb.Status );
  579. }
  580. bprint "\n" );
  581. }
  582. try_return( Status );
  583. try_exit: NOTHING;
  584. } finally {
  585. if (UnwindQDirBuffer) {
  586. DeallocateBuffer( ThisBufferIndex );
  587. }
  588. if (UnwindEvent) {
  589. FreeEvent( ThisEventIndex );
  590. }
  591. if (AsyncQDir->FileNamePtr) {
  592. DeallocateBuffer( AsyncQDir->NameIndex );
  593. }
  594. DeallocateBuffer( AsyncQDir->AsyncIndex );
  595. }
  596. NtTerminateThread( 0, STATUS_SUCCESS );
  597. }
  598. VOID
  599. InputDisplayQDir (
  600. IN PCHAR ParamBuffer
  601. )
  602. {
  603. FILE_INFORMATION_CLASS FileInfoClass;
  604. ULONG BufferIndex;
  605. BOOLEAN ParamReceived;
  606. BOOLEAN LastInput;
  607. //
  608. // Set the defaults.
  609. //
  610. BufferIndex = DISPLAY_INDEX_DEFAULT;
  611. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  612. ParamReceived = FALSE;
  613. LastInput = TRUE;
  614. //
  615. // While there is more input, analyze the parameter and update the
  616. // query flags.
  617. //
  618. while (TRUE) {
  619. ULONG DummyCount;
  620. //
  621. // Swallow leading white spaces.
  622. //
  623. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  624. if (*ParamBuffer) {
  625. //
  626. // If the next parameter is legal then check the paramter value.
  627. // Update the parameter value.
  628. //
  629. if ((*ParamBuffer == '-'
  630. || *ParamBuffer == '/')
  631. && (ParamBuffer++, *ParamBuffer != '\0')) {
  632. BOOLEAN SwitchBool;
  633. //
  634. // Switch on the next character.
  635. //
  636. switch( *ParamBuffer ) {
  637. //
  638. // Check the buffer index.
  639. //
  640. case 'b' :
  641. case 'B' :
  642. //
  643. // Move to the next character, as long as there
  644. // are no white spaces continue analyzing letters.
  645. // On the first bad letter, skip to the next
  646. // parameter.
  647. //
  648. ParamBuffer++;
  649. BufferIndex = AsciiToInteger( ParamBuffer );
  650. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  651. ParamReceived = TRUE;
  652. break;
  653. //
  654. // Update the desired access.
  655. //
  656. case 'c' :
  657. case 'C' :
  658. //
  659. // Move to the next character, as long as there
  660. // are no white spaces continue analyzing letters.
  661. // On the first bad letter, skip to the next
  662. // parameter.
  663. //
  664. ParamBuffer++;
  665. SwitchBool = TRUE;
  666. while (*ParamBuffer
  667. && *ParamBuffer != ' '
  668. && *ParamBuffer != '\t') {
  669. //
  670. // Perform switch on character.
  671. //
  672. switch (*ParamBuffer) {
  673. case 'a' :
  674. case 'A' :
  675. FileInfoClass = FileNamesInformation;
  676. break;
  677. case 'b' :
  678. case 'B' :
  679. FileInfoClass = FileDirectoryInformation;
  680. break;
  681. case 'c' :
  682. case 'C' :
  683. FileInfoClass = FileFullDirectoryInformation;
  684. break;
  685. case 'd' :
  686. case 'D' :
  687. FileInfoClass = FileIdFullDirectoryInformation;
  688. break;
  689. case 'e' :
  690. case 'E' :
  691. FileInfoClass = FileBothDirectoryInformation;
  692. break;
  693. case 'f' :
  694. case 'F' :
  695. FileInfoClass = FileIdBothDirectoryInformation;
  696. break;
  697. default :
  698. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  699. SwitchBool = FALSE;
  700. }
  701. if (!SwitchBool) {
  702. break;
  703. }
  704. ParamBuffer++;
  705. }
  706. break;
  707. default :
  708. //
  709. // Swallow to the next white space and continue the
  710. // loop.
  711. //
  712. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  713. }
  714. }
  715. //
  716. // Else the text is invalid, skip the entire block.
  717. //
  718. //
  719. //
  720. // Else if there is no input then exit.
  721. //
  722. } else if ( LastInput ) {
  723. break;
  724. //
  725. // Else try to read another line for open parameters.
  726. //
  727. } else {
  728. }
  729. }
  730. //
  731. // If no parameters were received then display the syntax message.
  732. //
  733. if (!ParamReceived) {
  734. printf( "\n Usage: dqd [options]* -b<digits> [options]*\n" );
  735. printf( "\n Options:" );
  736. printf( "\n -b<digits> Buffer index" );
  737. printf( "\n -c<char> Key to buffer format" );
  738. printf( "\n\n" );
  739. //
  740. // Else call our display buffer routine.
  741. //
  742. } else {
  743. switch (FileInfoClass) {
  744. case FileNamesInformation:
  745. DisplayQDirNames( (USHORT) BufferIndex );
  746. break;
  747. case FileDirectoryInformation:
  748. DisplayQDirDirs( (USHORT) BufferIndex );
  749. break;
  750. case FileFullDirectoryInformation:
  751. DisplayQDirFullDirs( (USHORT) BufferIndex );
  752. break;
  753. case FileIdFullDirectoryInformation:
  754. DisplayQDirIdFullDirs( (USHORT) BufferIndex );
  755. break;
  756. case FileBothDirectoryInformation:
  757. DisplayQBothDirs( (USHORT) BufferIndex );
  758. break;
  759. case FileIdBothDirectoryInformation:
  760. DisplayQIdBothDirs( (USHORT) BufferIndex );
  761. break;
  762. }
  763. }
  764. }
  765. VOID
  766. DisplayQDirNames (
  767. IN USHORT BufferIndex
  768. )
  769. {
  770. PFILE_NAMES_INFORMATION FileInfo;
  771. PUCHAR BufferStart;
  772. ULONG Offset;
  773. ULONG AvailLength;
  774. if (!Buffers[BufferIndex].Used) {
  775. printf( "\nDisplayQDirNames: Invalid buffer\n" );
  776. return;
  777. }
  778. BufferStart = Buffers[BufferIndex].Buffer;
  779. AvailLength = Buffers[BufferIndex].Length;
  780. Offset = 0;
  781. try {
  782. printf( "\n\nNames Information" );
  783. do {
  784. ANSI_STRING AnsiString;
  785. UNICODE_STRING UnicodeString;
  786. FileInfo = (PFILE_NAMES_INFORMATION) ((PUCHAR) BufferStart + Offset);
  787. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  788. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  789. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  790. RtlUnicodeStringToAnsiString( &AnsiString,
  791. &UnicodeString,
  792. TRUE );
  793. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  794. RtlFreeAnsiString( &AnsiString );
  795. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  796. printf( "\tFile Index -> %08lx", FileInfo->FileIndex );
  797. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  798. Offset += FileInfo->NextEntryOffset;
  799. } while (FileInfo->NextEntryOffset > 0
  800. && Offset < AvailLength);
  801. printf( "\n" );
  802. try_return( NOTHING );
  803. try_exit: NOTHING;
  804. } finally {
  805. if (AbnormalTermination()) {
  806. printf( "\nDisplayQDirNames: AbnormalTermination\n" );
  807. }
  808. }
  809. return;
  810. }
  811. VOID
  812. DisplayQDirDirs (
  813. IN USHORT BufferIndex
  814. )
  815. {
  816. PFILE_DIRECTORY_INFORMATION FileInfo;
  817. PUCHAR BufferStart;
  818. ULONG Offset;
  819. ULONG AvailLength;
  820. if (!Buffers[BufferIndex].Used) {
  821. printf( "\nDisplayQDirDirs: Invalid buffer\n" );
  822. return;
  823. }
  824. BufferStart = Buffers[BufferIndex].Buffer;
  825. AvailLength = Buffers[BufferIndex].Length;
  826. Offset = 0;
  827. try {
  828. printf( "\n\nDirectory Information" );
  829. do {
  830. ANSI_STRING AnsiString;
  831. UNICODE_STRING UnicodeString;
  832. FileInfo = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR) BufferStart + Offset);
  833. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  834. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  835. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  836. RtlUnicodeStringToAnsiString( &AnsiString,
  837. &UnicodeString,
  838. TRUE );
  839. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  840. RtlFreeAnsiString( &AnsiString );
  841. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  842. printf( "\tCreation Time -> " );
  843. PrintTime( &FileInfo->CreationTime );
  844. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  845. printf( "\tLast Access Time -> " );
  846. PrintTime( &FileInfo->LastAccessTime );
  847. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  848. printf( "\tLast Write Time -> " );
  849. PrintTime( &FileInfo->LastWriteTime );
  850. printf( "\n\t " );
  851. printf( "\tChange Time -> " );
  852. PrintTime( &FileInfo->ChangeTime );
  853. printf( "\n\tEnd Of File -> " );
  854. PrintLargeInteger( &FileInfo->EndOfFile );
  855. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  856. printf( "\tAllocation Size -> " );
  857. PrintLargeInteger( &FileInfo->AllocationSize );
  858. Offset += FileInfo->NextEntryOffset;
  859. } while (FileInfo->NextEntryOffset > 0
  860. && Offset < AvailLength);
  861. printf( "\n" );
  862. try_return( NOTHING );
  863. try_exit: NOTHING;
  864. } finally {
  865. if (AbnormalTermination()) {
  866. printf( "\nDisplayQDirDirs: AbnormalTermination\n" );
  867. }
  868. }
  869. return;
  870. }
  871. VOID
  872. DisplayQDirFullDirs (
  873. IN USHORT BufferIndex
  874. )
  875. {
  876. PFILE_FULL_DIR_INFORMATION FileInfo;
  877. PUCHAR BufferStart;
  878. ULONG Offset;
  879. ULONG AvailLength;
  880. if (!Buffers[BufferIndex].Used) {
  881. printf( "\nDisplayQDirFullDirs: Invalid buffer\n" );
  882. return;
  883. }
  884. BufferStart = Buffers[BufferIndex].Buffer;
  885. AvailLength = Buffers[BufferIndex].Length;
  886. Offset = 0;
  887. try {
  888. printf( "\n\nFull Directory Information" );
  889. do {
  890. ANSI_STRING AnsiString;
  891. UNICODE_STRING UnicodeString;
  892. FileInfo = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  893. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  894. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  895. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  896. RtlUnicodeStringToAnsiString( &AnsiString,
  897. &UnicodeString,
  898. TRUE );
  899. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  900. RtlFreeAnsiString( &AnsiString );
  901. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  902. printf( "\tCreation Time -> " );
  903. PrintTime( &FileInfo->CreationTime );
  904. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  905. printf( "\tLast Access Time -> " );
  906. PrintTime( &FileInfo->LastAccessTime );
  907. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  908. printf( "\tLast Write Time -> " );
  909. PrintTime( &FileInfo->LastWriteTime );
  910. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  911. printf( "\tChange Time -> " );
  912. PrintTime( &FileInfo->ChangeTime );
  913. printf( "\n\tEnd Of File -> " );
  914. PrintLargeInteger( &FileInfo->EndOfFile );
  915. printf( "\n\tAllocation Size -> " );
  916. PrintLargeInteger( &FileInfo->AllocationSize );
  917. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  918. Offset += FileInfo->NextEntryOffset;
  919. } while (FileInfo->NextEntryOffset > 0
  920. && Offset < AvailLength);
  921. printf( "\n" );
  922. try_return( NOTHING );
  923. try_exit: NOTHING;
  924. } finally {
  925. if (AbnormalTermination()) {
  926. printf( "\nDisplayQDirFullDirs: AbnormalTermination\n" );
  927. }
  928. }
  929. return;
  930. }
  931. VOID
  932. DisplayQDirIdFullDirs (
  933. IN USHORT BufferIndex
  934. )
  935. {
  936. PFILE_ID_FULL_DIR_INFORMATION FileInfo;
  937. PUCHAR BufferStart;
  938. ULONG Offset;
  939. ULONG AvailLength;
  940. if (!Buffers[BufferIndex].Used) {
  941. printf( "\nDisplayQDirIDFullDirs: Invalid buffer\n" );
  942. return;
  943. }
  944. BufferStart = Buffers[BufferIndex].Buffer;
  945. AvailLength = Buffers[BufferIndex].Length;
  946. Offset = 0;
  947. try {
  948. printf( "\n\nFull Directory Information with ID" );
  949. do {
  950. ANSI_STRING AnsiString;
  951. UNICODE_STRING UnicodeString;
  952. FileInfo = (PFILE_ID_FULL_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  953. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  954. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  955. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  956. RtlUnicodeStringToAnsiString( &AnsiString,
  957. &UnicodeString,
  958. TRUE );
  959. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  960. RtlFreeAnsiString( &AnsiString );
  961. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  962. printf( "\tCreation Time -> " );
  963. PrintTime( &FileInfo->CreationTime );
  964. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  965. printf( "\tLast Access Time -> " );
  966. PrintTime( &FileInfo->LastAccessTime );
  967. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  968. printf( "\tLast Write Time -> " );
  969. PrintTime( &FileInfo->LastWriteTime );
  970. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  971. printf( "\tChange Time -> " );
  972. PrintTime( &FileInfo->ChangeTime );
  973. printf( "\n\tEnd Of File -> " );
  974. PrintLargeInteger( &FileInfo->EndOfFile );
  975. printf( "\n\tAllocation Size -> " );
  976. PrintLargeInteger( &FileInfo->AllocationSize );
  977. printf( "\n\tFile ID -> " );
  978. PrintLargeInteger( &FileInfo->FileId );
  979. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  980. Offset += FileInfo->NextEntryOffset;
  981. } while (FileInfo->NextEntryOffset > 0
  982. && Offset < AvailLength);
  983. printf( "\n" );
  984. try_return( NOTHING );
  985. try_exit: NOTHING;
  986. } finally {
  987. if (AbnormalTermination()) {
  988. printf( "\nDisplayQDirIdFullDirs: AbnormalTermination\n" );
  989. }
  990. }
  991. return;
  992. }
  993. VOID
  994. DisplayQBothDirs (
  995. IN USHORT BufferIndex
  996. )
  997. {
  998. PFILE_BOTH_DIR_INFORMATION FileInfo;
  999. PUCHAR BufferStart;
  1000. ULONG Offset;
  1001. ULONG AvailLength;
  1002. if (!Buffers[BufferIndex].Used) {
  1003. printf( "\nDisplayQBothDirs: Invalid buffer\n" );
  1004. return;
  1005. }
  1006. BufferStart = Buffers[BufferIndex].Buffer;
  1007. AvailLength = Buffers[BufferIndex].Length;
  1008. Offset = 0;
  1009. try {
  1010. printf( "\n\nBoth Directory Information" );
  1011. do {
  1012. ANSI_STRING AnsiString;
  1013. UNICODE_STRING UnicodeString;
  1014. FileInfo = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  1015. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  1016. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  1017. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  1018. RtlUnicodeStringToAnsiString( &AnsiString,
  1019. &UnicodeString,
  1020. TRUE );
  1021. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  1022. RtlFreeAnsiString( &AnsiString );
  1023. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  1024. printf( "\tCreation Time -> " );
  1025. PrintTime( &FileInfo->CreationTime );
  1026. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  1027. printf( "\tLast Access Time -> " );
  1028. PrintTime( &FileInfo->LastAccessTime );
  1029. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  1030. printf( "\tLast Write Time -> " );
  1031. PrintTime( &FileInfo->LastWriteTime );
  1032. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  1033. printf( "\tChange Time -> " );
  1034. PrintTime( &FileInfo->ChangeTime );
  1035. printf( "\n\tEnd Of File -> " );
  1036. PrintLargeInteger( &FileInfo->EndOfFile );
  1037. printf( "\n\tAllocation Size -> " );
  1038. PrintLargeInteger( &FileInfo->AllocationSize );
  1039. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  1040. printf( "\n\tShrt Name Length -> %04x", FileInfo->ShortNameLength );
  1041. UnicodeString.MaximumLength = (USHORT) FileInfo->ShortNameLength + 2;
  1042. UnicodeString.Length = (USHORT) FileInfo->ShortNameLength;
  1043. UnicodeString.Buffer = (PWSTR) &FileInfo->ShortName;
  1044. RtlUnicodeStringToAnsiString( &AnsiString,
  1045. &UnicodeString,
  1046. TRUE );
  1047. printf( "\n\tShort Name -> %s", AnsiString.Buffer );
  1048. RtlFreeAnsiString( &AnsiString );
  1049. Offset += FileInfo->NextEntryOffset;
  1050. } while (FileInfo->NextEntryOffset > 0
  1051. && Offset < AvailLength);
  1052. printf( "\n" );
  1053. try_return( NOTHING );
  1054. try_exit: NOTHING;
  1055. } finally {
  1056. if (AbnormalTermination()) {
  1057. printf( "\nDisplayQBothDirs: AbnormalTermination\n" );
  1058. }
  1059. }
  1060. return;
  1061. }
  1062. VOID
  1063. DisplayQIdBothDirs (
  1064. IN USHORT BufferIndex
  1065. )
  1066. {
  1067. PFILE_ID_BOTH_DIR_INFORMATION FileInfo;
  1068. PUCHAR BufferStart;
  1069. ULONG Offset;
  1070. ULONG AvailLength;
  1071. if (!Buffers[BufferIndex].Used) {
  1072. printf( "\nDisplayQIdBothDirs: Invalid buffer\n" );
  1073. return;
  1074. }
  1075. BufferStart = Buffers[BufferIndex].Buffer;
  1076. AvailLength = Buffers[BufferIndex].Length;
  1077. Offset = 0;
  1078. try {
  1079. printf( "\n\nBoth Directory Information with ID" );
  1080. do {
  1081. ANSI_STRING AnsiString;
  1082. UNICODE_STRING UnicodeString;
  1083. FileInfo = (PFILE_ID_BOTH_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  1084. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  1085. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  1086. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  1087. RtlUnicodeStringToAnsiString( &AnsiString,
  1088. &UnicodeString,
  1089. TRUE );
  1090. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  1091. RtlFreeAnsiString( &AnsiString );
  1092. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  1093. printf( "\tCreation Time -> " );
  1094. PrintTime( &FileInfo->CreationTime );
  1095. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  1096. printf( "\tLast Access Time -> " );
  1097. PrintTime( &FileInfo->LastAccessTime );
  1098. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  1099. printf( "\tLast Write Time -> " );
  1100. PrintTime( &FileInfo->LastWriteTime );
  1101. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  1102. printf( "\tChange Time -> " );
  1103. PrintTime( &FileInfo->ChangeTime );
  1104. printf( "\n\tEnd Of File -> " );
  1105. PrintLargeInteger( &FileInfo->EndOfFile );
  1106. printf( "\n\tAllocation Size -> " );
  1107. PrintLargeInteger( &FileInfo->AllocationSize );
  1108. printf( "\n\tFile ID -> " );
  1109. PrintLargeInteger( &FileInfo->FileId );
  1110. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  1111. printf( "\n\tShrt Name Length -> %04x", FileInfo->ShortNameLength );
  1112. UnicodeString.MaximumLength = (USHORT) FileInfo->ShortNameLength + 2;
  1113. UnicodeString.Length = (USHORT) FileInfo->ShortNameLength;
  1114. UnicodeString.Buffer = (PWSTR) &FileInfo->ShortName;
  1115. RtlUnicodeStringToAnsiString( &AnsiString,
  1116. &UnicodeString,
  1117. TRUE );
  1118. printf( "\n\tShort Name -> %s", AnsiString.Buffer );
  1119. RtlFreeAnsiString( &AnsiString );
  1120. Offset += FileInfo->NextEntryOffset;
  1121. } while (FileInfo->NextEntryOffset > 0
  1122. && Offset < AvailLength);
  1123. printf( "\n" );
  1124. try_return( NOTHING );
  1125. try_exit: NOTHING;
  1126. } finally {
  1127. if (AbnormalTermination()) {
  1128. printf( "\nDisplayQIdBothDirs: AbnormalTermination\n" );
  1129. }
  1130. }
  1131. return;
  1132. }