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.

1568 lines
46 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. if (!SynchronousCmds) {
  597. NtTerminateThread( 0, STATUS_SUCCESS );
  598. }
  599. }
  600. VOID
  601. InputDisplayQDir (
  602. IN PCHAR ParamBuffer
  603. )
  604. {
  605. FILE_INFORMATION_CLASS FileInfoClass;
  606. ULONG BufferIndex;
  607. BOOLEAN ParamReceived;
  608. BOOLEAN LastInput;
  609. //
  610. // Set the defaults.
  611. //
  612. BufferIndex = DISPLAY_INDEX_DEFAULT;
  613. FileInfoClass = FILE_INFO_CLASS_DEFAULT;
  614. ParamReceived = FALSE;
  615. LastInput = TRUE;
  616. //
  617. // While there is more input, analyze the parameter and update the
  618. // query flags.
  619. //
  620. while (TRUE) {
  621. ULONG DummyCount;
  622. //
  623. // Swallow leading white spaces.
  624. //
  625. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  626. if (*ParamBuffer) {
  627. //
  628. // If the next parameter is legal then check the paramter value.
  629. // Update the parameter value.
  630. //
  631. if ((*ParamBuffer == '-'
  632. || *ParamBuffer == '/')
  633. && (ParamBuffer++, *ParamBuffer != '\0')) {
  634. BOOLEAN SwitchBool;
  635. //
  636. // Switch on the next character.
  637. //
  638. switch( *ParamBuffer ) {
  639. //
  640. // Check the buffer index.
  641. //
  642. case 'b' :
  643. case 'B' :
  644. //
  645. // Move to the next character, as long as there
  646. // are no white spaces continue analyzing letters.
  647. // On the first bad letter, skip to the next
  648. // parameter.
  649. //
  650. ParamBuffer++;
  651. BufferIndex = AsciiToInteger( ParamBuffer );
  652. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  653. ParamReceived = TRUE;
  654. break;
  655. //
  656. // Update the desired access.
  657. //
  658. case 'c' :
  659. case 'C' :
  660. //
  661. // Move to the next character, as long as there
  662. // are no white spaces continue analyzing letters.
  663. // On the first bad letter, skip to the next
  664. // parameter.
  665. //
  666. ParamBuffer++;
  667. SwitchBool = TRUE;
  668. while (*ParamBuffer
  669. && *ParamBuffer != ' '
  670. && *ParamBuffer != '\t') {
  671. //
  672. // Perform switch on character.
  673. //
  674. switch (*ParamBuffer) {
  675. case 'a' :
  676. case 'A' :
  677. FileInfoClass = FileNamesInformation;
  678. break;
  679. case 'b' :
  680. case 'B' :
  681. FileInfoClass = FileDirectoryInformation;
  682. break;
  683. case 'c' :
  684. case 'C' :
  685. FileInfoClass = FileFullDirectoryInformation;
  686. break;
  687. case 'd' :
  688. case 'D' :
  689. FileInfoClass = FileIdFullDirectoryInformation;
  690. break;
  691. case 'e' :
  692. case 'E' :
  693. FileInfoClass = FileBothDirectoryInformation;
  694. break;
  695. case 'f' :
  696. case 'F' :
  697. FileInfoClass = FileIdBothDirectoryInformation;
  698. break;
  699. default :
  700. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  701. SwitchBool = FALSE;
  702. }
  703. if (!SwitchBool) {
  704. break;
  705. }
  706. ParamBuffer++;
  707. }
  708. break;
  709. default :
  710. //
  711. // Swallow to the next white space and continue the
  712. // loop.
  713. //
  714. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  715. }
  716. }
  717. //
  718. // Else the text is invalid, skip the entire block.
  719. //
  720. //
  721. //
  722. // Else if there is no input then exit.
  723. //
  724. } else if ( LastInput ) {
  725. break;
  726. //
  727. // Else try to read another line for open parameters.
  728. //
  729. } else {
  730. }
  731. }
  732. //
  733. // If no parameters were received then display the syntax message.
  734. //
  735. if (!ParamReceived) {
  736. printf( "\n Usage: dqd [options]* -b<digits> [options]*\n" );
  737. printf( "\n Options:" );
  738. printf( "\n -b<digits> Buffer index" );
  739. printf( "\n -c<char> Key to buffer format" );
  740. printf( "\n\n" );
  741. //
  742. // Else call our display buffer routine.
  743. //
  744. } else {
  745. switch (FileInfoClass) {
  746. case FileNamesInformation:
  747. DisplayQDirNames( (USHORT) BufferIndex );
  748. break;
  749. case FileDirectoryInformation:
  750. DisplayQDirDirs( (USHORT) BufferIndex );
  751. break;
  752. case FileFullDirectoryInformation:
  753. DisplayQDirFullDirs( (USHORT) BufferIndex );
  754. break;
  755. case FileIdFullDirectoryInformation:
  756. DisplayQDirIdFullDirs( (USHORT) BufferIndex );
  757. break;
  758. case FileBothDirectoryInformation:
  759. DisplayQBothDirs( (USHORT) BufferIndex );
  760. break;
  761. case FileIdBothDirectoryInformation:
  762. DisplayQIdBothDirs( (USHORT) BufferIndex );
  763. break;
  764. }
  765. }
  766. }
  767. VOID
  768. DisplayQDirNames (
  769. IN USHORT BufferIndex
  770. )
  771. {
  772. PFILE_NAMES_INFORMATION FileInfo;
  773. PUCHAR BufferStart;
  774. ULONG Offset;
  775. ULONG AvailLength;
  776. if (!Buffers[BufferIndex].Used) {
  777. printf( "\nDisplayQDirNames: Invalid buffer\n" );
  778. return;
  779. }
  780. BufferStart = Buffers[BufferIndex].Buffer;
  781. AvailLength = Buffers[BufferIndex].Length;
  782. Offset = 0;
  783. try {
  784. printf( "\n\nNames Information" );
  785. do {
  786. ANSI_STRING AnsiString;
  787. UNICODE_STRING UnicodeString;
  788. FileInfo = (PFILE_NAMES_INFORMATION) ((PUCHAR) BufferStart + Offset);
  789. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  790. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  791. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  792. RtlUnicodeStringToAnsiString( &AnsiString,
  793. &UnicodeString,
  794. TRUE );
  795. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  796. RtlFreeAnsiString( &AnsiString );
  797. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  798. printf( "\tFile Index -> %08lx", FileInfo->FileIndex );
  799. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  800. Offset += FileInfo->NextEntryOffset;
  801. } while (FileInfo->NextEntryOffset > 0
  802. && Offset < AvailLength);
  803. printf( "\n" );
  804. try_return( NOTHING );
  805. try_exit: NOTHING;
  806. } finally {
  807. if (AbnormalTermination()) {
  808. printf( "\nDisplayQDirNames: AbnormalTermination\n" );
  809. }
  810. }
  811. return;
  812. }
  813. VOID
  814. DisplayQDirDirs (
  815. IN USHORT BufferIndex
  816. )
  817. {
  818. PFILE_DIRECTORY_INFORMATION FileInfo;
  819. PUCHAR BufferStart;
  820. ULONG Offset;
  821. ULONG AvailLength;
  822. if (!Buffers[BufferIndex].Used) {
  823. printf( "\nDisplayQDirDirs: Invalid buffer\n" );
  824. return;
  825. }
  826. BufferStart = Buffers[BufferIndex].Buffer;
  827. AvailLength = Buffers[BufferIndex].Length;
  828. Offset = 0;
  829. try {
  830. printf( "\n\nDirectory Information" );
  831. do {
  832. ANSI_STRING AnsiString;
  833. UNICODE_STRING UnicodeString;
  834. FileInfo = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR) BufferStart + Offset);
  835. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  836. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  837. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  838. RtlUnicodeStringToAnsiString( &AnsiString,
  839. &UnicodeString,
  840. TRUE );
  841. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  842. RtlFreeAnsiString( &AnsiString );
  843. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  844. printf( "\tCreation Time -> " );
  845. PrintTime( &FileInfo->CreationTime );
  846. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  847. printf( "\tLast Access Time -> " );
  848. PrintTime( &FileInfo->LastAccessTime );
  849. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  850. printf( "\tLast Write Time -> " );
  851. PrintTime( &FileInfo->LastWriteTime );
  852. printf( "\n\t " );
  853. printf( "\tChange Time -> " );
  854. PrintTime( &FileInfo->ChangeTime );
  855. printf( "\n\tEnd Of File -> " );
  856. PrintLargeInteger( &FileInfo->EndOfFile );
  857. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  858. printf( "\tAllocation Size -> " );
  859. PrintLargeInteger( &FileInfo->AllocationSize );
  860. Offset += FileInfo->NextEntryOffset;
  861. } while (FileInfo->NextEntryOffset > 0
  862. && Offset < AvailLength);
  863. printf( "\n" );
  864. try_return( NOTHING );
  865. try_exit: NOTHING;
  866. } finally {
  867. if (AbnormalTermination()) {
  868. printf( "\nDisplayQDirDirs: AbnormalTermination\n" );
  869. }
  870. }
  871. return;
  872. }
  873. VOID
  874. DisplayQDirFullDirs (
  875. IN USHORT BufferIndex
  876. )
  877. {
  878. PFILE_FULL_DIR_INFORMATION FileInfo;
  879. PUCHAR BufferStart;
  880. ULONG Offset;
  881. ULONG AvailLength;
  882. if (!Buffers[BufferIndex].Used) {
  883. printf( "\nDisplayQDirFullDirs: Invalid buffer\n" );
  884. return;
  885. }
  886. BufferStart = Buffers[BufferIndex].Buffer;
  887. AvailLength = Buffers[BufferIndex].Length;
  888. Offset = 0;
  889. try {
  890. printf( "\n\nFull Directory Information" );
  891. do {
  892. ANSI_STRING AnsiString;
  893. UNICODE_STRING UnicodeString;
  894. FileInfo = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  895. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  896. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  897. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  898. RtlUnicodeStringToAnsiString( &AnsiString,
  899. &UnicodeString,
  900. TRUE );
  901. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  902. RtlFreeAnsiString( &AnsiString );
  903. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  904. printf( "\tCreation Time -> " );
  905. PrintTime( &FileInfo->CreationTime );
  906. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  907. printf( "\tLast Access Time -> " );
  908. PrintTime( &FileInfo->LastAccessTime );
  909. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  910. printf( "\tLast Write Time -> " );
  911. PrintTime( &FileInfo->LastWriteTime );
  912. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  913. printf( "\tChange Time -> " );
  914. PrintTime( &FileInfo->ChangeTime );
  915. printf( "\n\tEnd Of File -> " );
  916. PrintLargeInteger( &FileInfo->EndOfFile );
  917. printf( "\n\tAllocation Size -> " );
  918. PrintLargeInteger( &FileInfo->AllocationSize );
  919. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  920. Offset += FileInfo->NextEntryOffset;
  921. } while (FileInfo->NextEntryOffset > 0
  922. && Offset < AvailLength);
  923. printf( "\n" );
  924. try_return( NOTHING );
  925. try_exit: NOTHING;
  926. } finally {
  927. if (AbnormalTermination()) {
  928. printf( "\nDisplayQDirFullDirs: AbnormalTermination\n" );
  929. }
  930. }
  931. return;
  932. }
  933. VOID
  934. DisplayQDirIdFullDirs (
  935. IN USHORT BufferIndex
  936. )
  937. {
  938. PFILE_ID_FULL_DIR_INFORMATION FileInfo;
  939. PUCHAR BufferStart;
  940. ULONG Offset;
  941. ULONG AvailLength;
  942. if (!Buffers[BufferIndex].Used) {
  943. printf( "\nDisplayQDirIDFullDirs: Invalid buffer\n" );
  944. return;
  945. }
  946. BufferStart = Buffers[BufferIndex].Buffer;
  947. AvailLength = Buffers[BufferIndex].Length;
  948. Offset = 0;
  949. try {
  950. printf( "\n\nFull Directory Information with ID" );
  951. do {
  952. ANSI_STRING AnsiString;
  953. UNICODE_STRING UnicodeString;
  954. FileInfo = (PFILE_ID_FULL_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  955. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  956. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  957. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  958. RtlUnicodeStringToAnsiString( &AnsiString,
  959. &UnicodeString,
  960. TRUE );
  961. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  962. RtlFreeAnsiString( &AnsiString );
  963. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  964. printf( "\tCreation Time -> " );
  965. PrintTime( &FileInfo->CreationTime );
  966. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  967. printf( "\tLast Access Time -> " );
  968. PrintTime( &FileInfo->LastAccessTime );
  969. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  970. printf( "\tLast Write Time -> " );
  971. PrintTime( &FileInfo->LastWriteTime );
  972. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  973. printf( "\tChange Time -> " );
  974. PrintTime( &FileInfo->ChangeTime );
  975. printf( "\n\tEnd Of File -> " );
  976. PrintLargeInteger( &FileInfo->EndOfFile );
  977. printf( "\n\tAllocation Size -> " );
  978. PrintLargeInteger( &FileInfo->AllocationSize );
  979. printf( "\n\tFile ID -> " );
  980. PrintLargeInteger( &FileInfo->FileId );
  981. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  982. Offset += FileInfo->NextEntryOffset;
  983. } while (FileInfo->NextEntryOffset > 0
  984. && Offset < AvailLength);
  985. printf( "\n" );
  986. try_return( NOTHING );
  987. try_exit: NOTHING;
  988. } finally {
  989. if (AbnormalTermination()) {
  990. printf( "\nDisplayQDirIdFullDirs: AbnormalTermination\n" );
  991. }
  992. }
  993. return;
  994. }
  995. VOID
  996. DisplayQBothDirs (
  997. IN USHORT BufferIndex
  998. )
  999. {
  1000. PFILE_BOTH_DIR_INFORMATION FileInfo;
  1001. PUCHAR BufferStart;
  1002. ULONG Offset;
  1003. ULONG AvailLength;
  1004. if (!Buffers[BufferIndex].Used) {
  1005. printf( "\nDisplayQBothDirs: Invalid buffer\n" );
  1006. return;
  1007. }
  1008. BufferStart = Buffers[BufferIndex].Buffer;
  1009. AvailLength = Buffers[BufferIndex].Length;
  1010. Offset = 0;
  1011. try {
  1012. printf( "\n\nBoth Directory Information" );
  1013. do {
  1014. ANSI_STRING AnsiString;
  1015. UNICODE_STRING UnicodeString;
  1016. FileInfo = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  1017. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  1018. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  1019. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  1020. RtlUnicodeStringToAnsiString( &AnsiString,
  1021. &UnicodeString,
  1022. TRUE );
  1023. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  1024. RtlFreeAnsiString( &AnsiString );
  1025. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  1026. printf( "\tCreation Time -> " );
  1027. PrintTime( &FileInfo->CreationTime );
  1028. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  1029. printf( "\tLast Access Time -> " );
  1030. PrintTime( &FileInfo->LastAccessTime );
  1031. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  1032. printf( "\tLast Write Time -> " );
  1033. PrintTime( &FileInfo->LastWriteTime );
  1034. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  1035. printf( "\tChange Time -> " );
  1036. PrintTime( &FileInfo->ChangeTime );
  1037. printf( "\n\tEnd Of File -> " );
  1038. PrintLargeInteger( &FileInfo->EndOfFile );
  1039. printf( "\n\tAllocation Size -> " );
  1040. PrintLargeInteger( &FileInfo->AllocationSize );
  1041. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  1042. printf( "\n\tShrt Name Length -> %04x", FileInfo->ShortNameLength );
  1043. UnicodeString.MaximumLength = (USHORT) FileInfo->ShortNameLength + 2;
  1044. UnicodeString.Length = (USHORT) FileInfo->ShortNameLength;
  1045. UnicodeString.Buffer = (PWSTR) &FileInfo->ShortName;
  1046. RtlUnicodeStringToAnsiString( &AnsiString,
  1047. &UnicodeString,
  1048. TRUE );
  1049. printf( "\n\tShort Name -> %s", AnsiString.Buffer );
  1050. RtlFreeAnsiString( &AnsiString );
  1051. Offset += FileInfo->NextEntryOffset;
  1052. } while (FileInfo->NextEntryOffset > 0
  1053. && Offset < AvailLength);
  1054. printf( "\n" );
  1055. try_return( NOTHING );
  1056. try_exit: NOTHING;
  1057. } finally {
  1058. if (AbnormalTermination()) {
  1059. printf( "\nDisplayQBothDirs: AbnormalTermination\n" );
  1060. }
  1061. }
  1062. return;
  1063. }
  1064. VOID
  1065. DisplayQIdBothDirs (
  1066. IN USHORT BufferIndex
  1067. )
  1068. {
  1069. PFILE_ID_BOTH_DIR_INFORMATION FileInfo;
  1070. PUCHAR BufferStart;
  1071. ULONG Offset;
  1072. ULONG AvailLength;
  1073. if (!Buffers[BufferIndex].Used) {
  1074. printf( "\nDisplayQIdBothDirs: Invalid buffer\n" );
  1075. return;
  1076. }
  1077. BufferStart = Buffers[BufferIndex].Buffer;
  1078. AvailLength = Buffers[BufferIndex].Length;
  1079. Offset = 0;
  1080. try {
  1081. printf( "\n\nBoth Directory Information with ID" );
  1082. do {
  1083. ANSI_STRING AnsiString;
  1084. UNICODE_STRING UnicodeString;
  1085. FileInfo = (PFILE_ID_BOTH_DIR_INFORMATION) ((PUCHAR) BufferStart + Offset);
  1086. UnicodeString.MaximumLength = (USHORT) FileInfo->FileNameLength + 2;
  1087. UnicodeString.Length = (USHORT) FileInfo->FileNameLength;
  1088. UnicodeString.Buffer = (PWSTR) &FileInfo->FileName;
  1089. RtlUnicodeStringToAnsiString( &AnsiString,
  1090. &UnicodeString,
  1091. TRUE );
  1092. printf( "\n\n\tFile Name -> %s", AnsiString.Buffer );
  1093. RtlFreeAnsiString( &AnsiString );
  1094. printf( "\n\tNext Offset -> %08lx", FileInfo->NextEntryOffset );
  1095. printf( "\tCreation Time -> " );
  1096. PrintTime( &FileInfo->CreationTime );
  1097. printf( "\n\tFile Index -> %08lx", FileInfo->FileIndex );
  1098. printf( "\tLast Access Time -> " );
  1099. PrintTime( &FileInfo->LastAccessTime );
  1100. printf( "\n\tFile Attributes -> %08lx", FileInfo->FileAttributes );
  1101. printf( "\tLast Write Time -> " );
  1102. PrintTime( &FileInfo->LastWriteTime );
  1103. printf( "\n\tEa Size -> %08lx", FileInfo->EaSize );
  1104. printf( "\tChange Time -> " );
  1105. PrintTime( &FileInfo->ChangeTime );
  1106. printf( "\n\tEnd Of File -> " );
  1107. PrintLargeInteger( &FileInfo->EndOfFile );
  1108. printf( "\n\tAllocation Size -> " );
  1109. PrintLargeInteger( &FileInfo->AllocationSize );
  1110. printf( "\n\tFile ID -> " );
  1111. PrintLargeInteger( &FileInfo->FileId );
  1112. printf( "\n\tFile Name Length -> %08lx", FileInfo->FileNameLength );
  1113. printf( "\n\tShrt Name Length -> %04x", FileInfo->ShortNameLength );
  1114. UnicodeString.MaximumLength = (USHORT) FileInfo->ShortNameLength + 2;
  1115. UnicodeString.Length = (USHORT) FileInfo->ShortNameLength;
  1116. UnicodeString.Buffer = (PWSTR) &FileInfo->ShortName;
  1117. RtlUnicodeStringToAnsiString( &AnsiString,
  1118. &UnicodeString,
  1119. TRUE );
  1120. printf( "\n\tShort Name -> %s", AnsiString.Buffer );
  1121. RtlFreeAnsiString( &AnsiString );
  1122. Offset += FileInfo->NextEntryOffset;
  1123. } while (FileInfo->NextEntryOffset > 0
  1124. && Offset < AvailLength);
  1125. printf( "\n" );
  1126. try_return( NOTHING );
  1127. try_exit: NOTHING;
  1128. } finally {
  1129. if (AbnormalTermination()) {
  1130. printf( "\nDisplayQIdBothDirs: AbnormalTermination\n" );
  1131. }
  1132. }
  1133. return;
  1134. }