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.

1954 lines
53 KiB

  1. #include "brian.h"
  2. #define PEAN_INDEX_DEFAULT 0
  3. #define PEAN_OFFSET_DEFAULT 0
  4. #define PEAN_NEXT_OFFSET_DEFAULT NULL
  5. #define PEAN_ACT_NEXT_OFF_DEFAULT 0
  6. #define PEAN_NAME_DEFAULT NULL
  7. #define PEAN_VERBOSE_DEFAULT TRUE
  8. #define PEAN_DISPLAY_PARMS_DEFAULT FALSE
  9. #define PEAN_MORE_EAS_DEFAULT FALSE
  10. #define FEA_INDEX_DEFAULT 0
  11. #define FEA_OFFSET_DEFAULT 0
  12. #define FEA_NEXT_OFFSET_DEFAULT NULL
  13. #define FEA_ACT_NEXT_OFF_DEFAULT 0
  14. #define FEA_NAME_DEFAULT NULL
  15. #define FEA_VALUE_DEFAULT NULL
  16. #define FEA_FLAGS_DEFAULT NULL
  17. #define FEA_ACTUAL_FLAGS_DEFAULT 0
  18. #define FEA_VERBOSE_DEFAULT TRUE
  19. #define FEA_DISPLAY_PARMS_DEFAULT FALSE
  20. #define FEA_MORE_EAS_DEFAULT FALSE
  21. #define QEA_FILE_HANDLE_DEFAULT 0
  22. #define QEA_BUFFER_INDEX_DEFAULT 0
  23. #define QEA_BUFFER_LENGTH_DEFAULT NULL
  24. #define QEA_RETURN_SINGLE_DEFAULT FALSE
  25. #define QEA_EA_NAME_BUFFER_DEFAULT NULL
  26. #define QEA_EA_NAME_BUFFER_LEN_DEFAULT NULL
  27. #define QEA_EA_INDEX_DEFAULT NULL
  28. #define QEA_RESTART_SCAN_DEFAULT FALSE
  29. #define QEA_VERBOSE_DEFAULT TRUE
  30. #define SEA_FILE_HANDLE_DEFAULT 0
  31. #define SEA_BUFFER_INDEX_DEFAULT 0
  32. #define SEA_BUFFER_LENGTH_DEFAULT NULL
  33. #define SEA_VERBOSE_DEFAULT FALSE
  34. NTSTATUS
  35. PutEaName(
  36. IN ULONG BufferIndex,
  37. IN ULONG Offset,
  38. IN PULONG NextOffset,
  39. IN PSTRING Name,
  40. IN BOOLEAN Verbose,
  41. IN BOOLEAN DisplayParms,
  42. IN BOOLEAN MoreEas
  43. );
  44. NTSTATUS
  45. FillEaBuffer(
  46. IN ULONG BufferIndex,
  47. IN ULONG Offset,
  48. IN PULONG NextOffset,
  49. IN PUCHAR Flags,
  50. IN PSTRING Name,
  51. IN PSTRING Value,
  52. IN BOOLEAN MoreEas,
  53. IN BOOLEAN Verbose,
  54. IN BOOLEAN DisplayParms
  55. );
  56. NTSTATUS
  57. QueryEa(
  58. IN ULONG FileHandleIndex,
  59. OUT PIO_STATUS_BLOCK IoStatusBlock,
  60. IN ULONG BufferIndex,
  61. IN PULONG BufferLength OPTIONAL,
  62. IN BOOLEAN ReturnSingleEntry,
  63. IN PULONG EaNameBuffer OPTIONAL,
  64. IN PULONG EaNameBufferLength OPTIONAL,
  65. IN PULONG EaIndex,
  66. IN BOOLEAN RestartScan,
  67. IN BOOLEAN VerboseResults,
  68. IN BOOLEAN DisplayParms
  69. );
  70. NTSTATUS
  71. SetEa(
  72. IN ULONG FileHandleIndex,
  73. OUT PIO_STATUS_BLOCK IoStatusBlock,
  74. IN ULONG BufferIndex,
  75. IN PULONG BufferLength OPTIONAL,
  76. IN BOOLEAN VerboseResults,
  77. IN BOOLEAN DisplayParms
  78. );
  79. VOID
  80. InputPutEaName(
  81. IN PCHAR ParamBuffer
  82. )
  83. {
  84. ULONG BufferIndex;
  85. ULONG Offset;
  86. PULONG NextOffset;
  87. ULONG ActualNextOffset;
  88. PSTRING Name;
  89. STRING ActualName;
  90. BOOLEAN VerboseResults;
  91. BOOLEAN DisplayParms;
  92. BOOLEAN ParamReceived;
  93. BOOLEAN LastInput;
  94. PCHAR EaNameTemp;
  95. BOOLEAN MoreEas;
  96. BufferIndex = PEAN_INDEX_DEFAULT;
  97. Offset = PEAN_OFFSET_DEFAULT;
  98. NextOffset = PEAN_NEXT_OFFSET_DEFAULT;
  99. ActualNextOffset = PEAN_ACT_NEXT_OFF_DEFAULT;
  100. Name = PEAN_NAME_DEFAULT;
  101. VerboseResults = PEAN_VERBOSE_DEFAULT;
  102. DisplayParms = PEAN_DISPLAY_PARMS_DEFAULT;
  103. MoreEas = PEAN_MORE_EAS_DEFAULT;
  104. ParamReceived = FALSE;
  105. LastInput = TRUE;
  106. //
  107. // While there is more input, analyze the parameter and update the
  108. // query flags.
  109. //
  110. while(TRUE) {
  111. ULONG DummyCount;
  112. //
  113. // Swallow leading white spaces.
  114. //
  115. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  116. if (*ParamBuffer) {
  117. //
  118. // If the next parameter is legal then check the paramter value.
  119. // Update the parameter value.
  120. //
  121. if((*ParamBuffer == '-'
  122. || *ParamBuffer == '/')
  123. && (ParamBuffer++, *ParamBuffer != '\0')) {
  124. //
  125. // Switch on the next character.
  126. //
  127. switch (*ParamBuffer) {
  128. //
  129. // Update buffer to use.
  130. //
  131. case 'b' :
  132. case 'B' :
  133. //
  134. // Move to the next character, as long as there
  135. // are no white spaces continue analyzing letters.
  136. // On the first bad letter, skip to the next
  137. // parameter.
  138. //
  139. ParamBuffer++;
  140. BufferIndex = AsciiToInteger( ParamBuffer );
  141. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  142. break;
  143. //
  144. // Check if we're adding more eas.
  145. //
  146. case 'm' :
  147. case 'M' :
  148. //
  149. // Legal values for params are T/t or F/f.
  150. //
  151. ParamBuffer++;
  152. if (*ParamBuffer == 'T'
  153. || *ParamBuffer == 't') {
  154. MoreEas = TRUE;
  155. ParamBuffer++;
  156. } else if (*ParamBuffer == 'F'
  157. || *ParamBuffer == 'f' ) {
  158. MoreEas = FALSE;
  159. ParamBuffer++;
  160. }
  161. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  162. break;
  163. //
  164. // Get the Ea name.
  165. //
  166. case 'n' :
  167. case 'N' :
  168. //
  169. // Remember the buffer offset and get the filename.
  170. //
  171. ParamBuffer++;
  172. EaNameTemp = ParamBuffer;
  173. DummyCount = 0;
  174. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  175. //
  176. // If the name length is 0, then ignore this entry.
  177. //
  178. if (DummyCount) {
  179. ActualName.Buffer = EaNameTemp;
  180. ActualName.Length = (SHORT) DummyCount;
  181. ActualName.MaximumLength = (SHORT) DummyCount;
  182. Name = &ActualName;
  183. } else {
  184. Name = NULL;
  185. }
  186. ParamReceived = TRUE;
  187. break;
  188. //
  189. // Update offset to store the information.
  190. //
  191. case 'o' :
  192. case 'O' :
  193. //
  194. // Move to the next character, as long as there
  195. // are no white spaces continue analyzing letters.
  196. // On the first bad letter, skip to the next
  197. // parameter.
  198. //
  199. ParamBuffer++;
  200. Offset = AsciiToInteger( ParamBuffer );
  201. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  202. break;
  203. //
  204. // Update the next offset field.
  205. //
  206. case 'x' :
  207. case 'X' :
  208. //
  209. // Move to the next character, as long as there
  210. // are no white spaces continue analyzing letters.
  211. // On the first bad letter, skip to the next
  212. // parameter.
  213. //
  214. ParamBuffer++;
  215. ActualNextOffset = AsciiToInteger( ParamBuffer );
  216. NextOffset = &ActualNextOffset;
  217. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  218. ParamReceived = TRUE;
  219. break;
  220. case 'v' :
  221. case 'V' :
  222. //
  223. // Legal values for params are T/t or F/f.
  224. //
  225. ParamBuffer++;
  226. if (*ParamBuffer == 'T'
  227. || *ParamBuffer == 't') {
  228. VerboseResults = TRUE;
  229. ParamBuffer++;
  230. } else if (*ParamBuffer == 'F'
  231. || *ParamBuffer == 'f') {
  232. VerboseResults = FALSE;
  233. ParamBuffer++;
  234. }
  235. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  236. break;
  237. case 'y' :
  238. case 'Y' :
  239. //
  240. // Set the display parms flag and jump over this
  241. // character.
  242. //
  243. DisplayParms = TRUE;
  244. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  245. break;
  246. case 'z' :
  247. case 'Z' :
  248. //
  249. // Set flag for more input and jump over this char.
  250. //
  251. LastInput = FALSE;
  252. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  253. break;
  254. default :
  255. //
  256. // Swallow to the next white space and continue the
  257. // loop.
  258. //
  259. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  260. }
  261. }
  262. //
  263. // Else the text is invalid, skip the entire block.
  264. //
  265. //
  266. //
  267. // Else if there is no input then exit.
  268. //
  269. } else if (LastInput) {
  270. break;
  271. //
  272. // Else try to read another line for open parameters.
  273. //
  274. } else {
  275. }
  276. }
  277. //
  278. // If no parameters were received then display the syntax message.
  279. //
  280. if( !ParamReceived ) {
  281. printf( "\n Usage: pea [options]* -b<digits> [options]*\n" );
  282. printf( "\n Options:" );
  283. printf( "\n -b<digits> Buffer index" );
  284. printf( "\n -n<ea name> EaName to store in buffer" );
  285. printf( "\n -o<digits> Offset in buffer to store data" );
  286. printf( "\n -x<digits> Value for next offset field" );
  287. printf( "\n -m[t|f] More Eas coming (Fills next offset field)" );
  288. printf( "\n -v[t|f] Verbose results" );
  289. printf( "\n -y Display parameters to query" );
  290. printf( "\n -z Additional input line" );
  291. printf( "\n\n" );
  292. //
  293. // Else call our put ea name routine.
  294. //
  295. } else {
  296. PutEaName( BufferIndex,
  297. Offset,
  298. NextOffset,
  299. Name,
  300. VerboseResults,
  301. DisplayParms,
  302. MoreEas );
  303. }
  304. }
  305. NTSTATUS
  306. PutEaName(
  307. IN ULONG BufferIndex,
  308. IN ULONG Offset,
  309. IN PULONG NextOffset,
  310. IN PSTRING Name,
  311. IN BOOLEAN Verbose,
  312. IN BOOLEAN DisplayParms,
  313. IN BOOLEAN MoreEas
  314. )
  315. {
  316. NTSTATUS Status;
  317. ULONG DataLength;
  318. //
  319. // Display parameters if requested.
  320. //
  321. if (DisplayParms) {
  322. printf( "\nPut Ea Name Parameters" );
  323. printf( "\n Buffer index -> %ld", BufferIndex );
  324. printf( "\n Buffer offset -> %08lx", Offset );
  325. if (NextOffset) {
  326. printf( "\n Next offset -> %08lx", *NextOffset );
  327. }
  328. if (Name) {
  329. printf( "\n Ea name -> %S", &Name );
  330. }
  331. printf( "\n MoreEas -> %d", MoreEas );
  332. printf( "\n\n" );
  333. }
  334. if (Name) {
  335. DataLength = 6 + Name->Length;
  336. } else {
  337. DataLength = 5;
  338. }
  339. //
  340. // If the index is unused, display message but take no action.
  341. //
  342. if (!Buffers[BufferIndex].Used) {
  343. printf( "\nPutEaName: Index refers to invalid buffer" );
  344. Status = STATUS_INVALID_HANDLE;
  345. //
  346. // Else if the start offset is invalid, then display error
  347. // message.
  348. //
  349. } else if (Offset >= Buffers[BufferIndex].Length) {
  350. printf( "\nPutEaName: Start offset is invalid" );
  351. Status = STATUS_INVALID_HANDLE;
  352. //
  353. // Else if length is insufficient to store all of the data
  354. // display message.
  355. //
  356. } else if (DataLength >= Buffers[BufferIndex].Length) {
  357. printf( "\nPutEaName: Data won't fit in buffer" );
  358. Status = STATUS_INVALID_HANDLE;
  359. //
  360. // Else store the data in the buffer.
  361. //
  362. } else {
  363. PFILE_GET_EA_INFORMATION EaNameBuffer;
  364. EaNameBuffer = (PFILE_GET_EA_INFORMATION)
  365. (Buffers[BufferIndex].Buffer + Offset);
  366. //
  367. // Store the next offset if specified.
  368. //
  369. if (NextOffset) {
  370. EaNameBuffer->NextEntryOffset = *NextOffset;
  371. }
  372. //
  373. // Store the name and name length if specified.
  374. //
  375. if (Name) {
  376. EaNameBuffer->EaNameLength = (UCHAR) Name->Length;
  377. RtlMoveMemory( EaNameBuffer->EaName, Name->Buffer, Name->Length );
  378. }
  379. if (MoreEas) {
  380. EaNameBuffer->NextEntryOffset = (DataLength + 3) & ~3;
  381. }
  382. Status = STATUS_SUCCESS;
  383. }
  384. if (Verbose) {
  385. printf( "\nPutEaName: Status -> %08lx\n", Status );
  386. printf( " Following offset -> %ld\n",
  387. (DataLength + Offset + 3) & ~3 );
  388. }
  389. return Status;
  390. }
  391. VOID
  392. InputFillEaBuffer(
  393. IN PCHAR ParamBuffer
  394. )
  395. {
  396. ULONG BufferIndex;
  397. ULONG Offset;
  398. PULONG NextOffset;
  399. ULONG ActualNextOffset;
  400. PSTRING Name;
  401. STRING ActualName;
  402. PSTRING Value;
  403. STRING ActualValue;
  404. PUCHAR Flags;
  405. UCHAR ActualFlags;
  406. BOOLEAN VerboseResults;
  407. BOOLEAN DisplayParms;
  408. BOOLEAN ParamReceived;
  409. BOOLEAN LastInput;
  410. BOOLEAN MoreEas;
  411. PCHAR StringTemp;
  412. BufferIndex = FEA_INDEX_DEFAULT;
  413. Offset = FEA_OFFSET_DEFAULT;
  414. NextOffset = FEA_NEXT_OFFSET_DEFAULT;
  415. ActualNextOffset = FEA_ACT_NEXT_OFF_DEFAULT;
  416. Name = FEA_NAME_DEFAULT;
  417. Value = FEA_VALUE_DEFAULT;
  418. Flags = FEA_FLAGS_DEFAULT;
  419. ActualFlags = FEA_ACTUAL_FLAGS_DEFAULT;
  420. MoreEas = FEA_MORE_EAS_DEFAULT;
  421. VerboseResults = FEA_VERBOSE_DEFAULT;
  422. DisplayParms = FEA_DISPLAY_PARMS_DEFAULT;
  423. ParamReceived = FALSE;
  424. LastInput = TRUE;
  425. //
  426. // While there is more input, analyze the parameter and update the
  427. // query flags.
  428. //
  429. while (TRUE) {
  430. ULONG DummyCount;
  431. //
  432. // Swallow leading white spaces.
  433. //
  434. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  435. if (*ParamBuffer) {
  436. //
  437. // If the next parameter is legal then check the paramter value.
  438. // Update the parameter value.
  439. //
  440. if((*ParamBuffer == '-'
  441. || *ParamBuffer == '/')
  442. && (ParamBuffer++, *ParamBuffer != '\0')) {
  443. BOOLEAN SwitchBool;
  444. //
  445. // Switch on the next character.
  446. //
  447. switch (*ParamBuffer) {
  448. //
  449. // Update buffer to use.
  450. //
  451. case 'b' :
  452. case 'B' :
  453. //
  454. // Move to the next character, as long as there
  455. // are no white spaces continue analyzing letters.
  456. // On the first bad letter, skip to the next
  457. // parameter.
  458. //
  459. ParamBuffer++;
  460. BufferIndex = AsciiToInteger( ParamBuffer );
  461. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  462. ParamReceived = TRUE;
  463. break;
  464. //
  465. // Update the flags field.
  466. //
  467. case 'f' :
  468. case 'F' :
  469. //
  470. // Move to the next character, as long as there
  471. // are no white spaces continue analyzing letters.
  472. // On the first bad letter, skip to the next
  473. // parameter.
  474. //
  475. ParamBuffer++;
  476. SwitchBool = TRUE;
  477. while( *ParamBuffer
  478. && *ParamBuffer != ' '
  479. && *ParamBuffer != '\t' ) {
  480. //
  481. // Perform switch on character.
  482. //
  483. switch (*ParamBuffer) {
  484. case 'a' :
  485. case 'A' :
  486. ActualFlags |= FILE_NEED_EA;
  487. Flags = &ActualFlags;
  488. break;
  489. default :
  490. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  491. SwitchBool = FALSE;
  492. }
  493. if (!SwitchBool) {
  494. break;
  495. }
  496. ParamBuffer++;
  497. }
  498. break;
  499. //
  500. // Get the Ea name.
  501. //
  502. case 'n' :
  503. case 'N' :
  504. //
  505. // Remember the buffer offset and get the filename.
  506. //
  507. ParamBuffer++;
  508. StringTemp = ParamBuffer;
  509. DummyCount = 0;
  510. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  511. ActualName.Buffer = StringTemp;
  512. ActualName.Length = (SHORT) DummyCount;
  513. ActualName.MaximumLength = (SHORT) DummyCount;
  514. Name = &ActualName;
  515. break;
  516. //
  517. // Get the Ea value.
  518. //
  519. case 'l' :
  520. case 'L' :
  521. //
  522. // Remember the buffer offset and get the value.
  523. //
  524. ParamBuffer++;
  525. StringTemp = ParamBuffer;
  526. DummyCount = 0;
  527. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  528. ActualValue.Buffer = StringTemp;
  529. ActualValue.Length = (SHORT) DummyCount;
  530. ActualValue.MaximumLength = (SHORT) DummyCount;
  531. Value = &ActualValue;
  532. break;
  533. //
  534. // Check if we're adding more eas.
  535. //
  536. case 'm' :
  537. case 'M' :
  538. //
  539. // Legal values for params are T/t or F/f.
  540. //
  541. ParamBuffer++;
  542. if (*ParamBuffer == 'T'
  543. || *ParamBuffer == 't') {
  544. MoreEas = TRUE;
  545. ParamBuffer++;
  546. } else if (*ParamBuffer == 'F'
  547. || *ParamBuffer == 'f') {
  548. MoreEas = FALSE;
  549. ParamBuffer++;
  550. }
  551. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  552. break;
  553. //
  554. // Update offset to store the information.
  555. //
  556. case 'o' :
  557. case 'O' :
  558. //
  559. // Move to the next character, as long as there
  560. // are no white spaces continue analyzing letters.
  561. // On the first bad letter, skip to the next
  562. // parameter.
  563. //
  564. ParamBuffer++;
  565. Offset = AsciiToInteger( ParamBuffer );
  566. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  567. break;
  568. //
  569. // Update the next offset field.
  570. //
  571. case 'x' :
  572. case 'X' :
  573. //
  574. // Move to the next character, as long as there
  575. // are no white spaces continue analyzing letters.
  576. // On the first bad letter, skip to the next
  577. // parameter.
  578. //
  579. ParamBuffer++;
  580. ActualNextOffset = AsciiToInteger( ParamBuffer );
  581. NextOffset = &ActualNextOffset;
  582. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  583. break;
  584. case 'v' :
  585. case 'V' :
  586. //
  587. // Legal values for params are T/t or F/f.
  588. //
  589. ParamBuffer++;
  590. if (*ParamBuffer == 'T'
  591. || *ParamBuffer == 't') {
  592. VerboseResults = TRUE;
  593. ParamBuffer++;
  594. } else if (*ParamBuffer == 'F'
  595. || *ParamBuffer == 'f') {
  596. VerboseResults = FALSE;
  597. ParamBuffer++;
  598. }
  599. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  600. break;
  601. case 'y' :
  602. case 'Y' :
  603. //
  604. // Set the display parms flag and jump over this
  605. // character.
  606. //
  607. DisplayParms = TRUE;
  608. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  609. break;
  610. case 'z' :
  611. case 'Z' :
  612. //
  613. // Set flag for more input and jump over this char.
  614. //
  615. LastInput = FALSE;
  616. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  617. break;
  618. default :
  619. //
  620. // Swallow to the next white space and continue the
  621. // loop.
  622. //
  623. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  624. }
  625. }
  626. //
  627. // Else the text is invalid, skip the entire block.
  628. //
  629. //
  630. //
  631. // Else if there is no input then exit.
  632. //
  633. } else if (LastInput) {
  634. break;
  635. //
  636. // Else try to read another line for open parameters.
  637. //
  638. } else {
  639. }
  640. }
  641. //
  642. // If no parameters were received then display the syntax message.
  643. //
  644. if (!ParamReceived) {
  645. printf( "\n Usage: fea [options]* -b<digits> [options]*\n" );
  646. printf( "\n Options:" );
  647. printf( "\n -b<digits> Buffer index" );
  648. printf( "\n -f<chars> Ea flags to store in buffer" );
  649. printf( "\n -n<chars> EaName to store in buffer" );
  650. printf( "\n -l<chars> Ea value to store in buffer" );
  651. printf( "\n -m[t|f] More Eas coming (Fills next offset field)" );
  652. printf( "\n -o<digits> Offset in buffer to store data" );
  653. printf( "\n -x<digits> Value for next offset field" );
  654. printf( "\n -v[t|f] Verbose results" );
  655. printf( "\n -y Display parameters to query" );
  656. printf( "\n -z Additional input line" );
  657. printf( "\n\n" );
  658. //
  659. // Else call our put ea name routine.
  660. //
  661. } else {
  662. FillEaBuffer( BufferIndex,
  663. Offset,
  664. NextOffset,
  665. Flags,
  666. Name,
  667. Value,
  668. MoreEas,
  669. VerboseResults,
  670. DisplayParms );
  671. }
  672. return;
  673. }
  674. NTSTATUS
  675. FillEaBuffer(
  676. IN ULONG BufferIndex,
  677. IN ULONG Offset,
  678. IN PULONG NextOffset,
  679. IN PUCHAR Flags,
  680. IN PSTRING Name,
  681. IN PSTRING Value,
  682. IN BOOLEAN MoreEas,
  683. IN BOOLEAN Verbose,
  684. IN BOOLEAN DisplayParms
  685. )
  686. {
  687. NTSTATUS Status;
  688. ULONG DataLength;
  689. //
  690. // Display parameters if requested.
  691. //
  692. if (DisplayParms) {
  693. printf( "\nFill Ea Buffer Parameters" );
  694. printf( "\n Buffer index -> %ld", BufferIndex );
  695. printf( "\n Buffer offset -> %08lx", Offset );
  696. if (NextOffset) {
  697. printf( "\n Next offset -> %08lx", *NextOffset );
  698. }
  699. if (Flags) {
  700. printf( "\n Flags -> %02x", *Flags );
  701. }
  702. if (Name) {
  703. printf( "\n Ea name -> %S", Name );
  704. }
  705. if (Value) {
  706. printf( "\n Value -> %S", Value );
  707. }
  708. printf( "\n MoreEas -> %d", MoreEas );
  709. printf( "\n\n" );
  710. }
  711. DataLength = 0;
  712. if (NextOffset) {
  713. DataLength = 4;
  714. }
  715. if (Flags) {
  716. DataLength = 5;
  717. }
  718. if (Name) {
  719. DataLength = 9 + Name->Length;
  720. if (Value) {
  721. if (Value->Length) {
  722. DataLength += (Value->Length + 4);
  723. }
  724. }
  725. } else if (Value) {
  726. DataLength = 9;
  727. if (Value->Length) {
  728. DataLength = 9 + (Value->Length + 4);
  729. }
  730. }
  731. //
  732. // If the index is unused, display message but take no action.
  733. //
  734. if (!Buffers[BufferIndex].Used) {
  735. printf( "\nFillEaBuffer: Index refers to invalid buffer" );
  736. Status = STATUS_INVALID_HANDLE;
  737. //
  738. // Else if the start offset is invalid, then display error
  739. // message.
  740. //
  741. } else if (Offset >= Buffers[BufferIndex].Length) {
  742. printf( "\nFillEaBuffer: Start offset is invalid" );
  743. Status = STATUS_INVALID_HANDLE;
  744. //
  745. // Else if length is insufficient to store all of the data
  746. // display message.
  747. //
  748. } else if (DataLength >= Buffers[BufferIndex].Length) {
  749. printf( "\nFillEaBuffer: Data won't fit in buffer" );
  750. Status = STATUS_INVALID_HANDLE;
  751. //
  752. // Else store the data in the buffer.
  753. //
  754. } else {
  755. PFILE_FULL_EA_INFORMATION EaBuffer;
  756. EaBuffer = (PFILE_FULL_EA_INFORMATION)
  757. (Buffers[BufferIndex].Buffer + Offset);
  758. //
  759. // Store the next offset if specified.
  760. //
  761. if (NextOffset) {
  762. EaBuffer->NextEntryOffset = *NextOffset;
  763. }
  764. //
  765. // Store the flags if specified.
  766. //
  767. if (Flags) {
  768. EaBuffer->Flags = *Flags;
  769. }
  770. //
  771. // Store the name and name length if specified.
  772. //
  773. if (Name) {
  774. EaBuffer->EaNameLength = (UCHAR) Name->Length;
  775. RtlMoveMemory( EaBuffer->EaName, Name->Buffer, Name->Length );
  776. EaBuffer->EaName[Name->Length] = '\0';
  777. }
  778. //
  779. // Store the value if specified.
  780. //
  781. if (Value) {
  782. ULONG Index;
  783. USHORT ValueLength;
  784. PUSHORT ActualValueLength;
  785. ValueLength = (USHORT) (Value->Length ? Value->Length + 4 : 0);
  786. Index = DataLength - 8 - Value->Length - 4;
  787. EaBuffer->EaValueLength = ValueLength;
  788. if (ValueLength) {
  789. EaBuffer->EaName[Index++] = (CHAR) 0xFD;
  790. EaBuffer->EaName[Index++] = (CHAR) 0xFF;
  791. ActualValueLength = (PUSHORT) &EaBuffer->EaName[Index++];
  792. *ActualValueLength = Value->Length;
  793. Index++;
  794. RtlMoveMemory( &EaBuffer->EaName[Index],
  795. Value->Buffer,
  796. Value->Length );
  797. }
  798. }
  799. //
  800. // Update the next entry field automatically.
  801. //
  802. if (MoreEas && !NextOffset) {
  803. EaBuffer->NextEntryOffset = (DataLength + 3) & ~3;
  804. }
  805. Status = STATUS_SUCCESS;
  806. }
  807. if (Verbose) {
  808. printf( "\nFillEaBuffer: Status -> %08lx\n", Status );
  809. printf( " Following offset -> %ld\n",
  810. (DataLength + Offset + 3) & ~3 );
  811. }
  812. return Status;
  813. }
  814. VOID
  815. InputQueryEa(
  816. IN PCHAR ParamBuffer
  817. )
  818. {
  819. ULONG FileHandleIndex;
  820. IO_STATUS_BLOCK IoStatusBlock;
  821. ULONG BufferIndex;
  822. PULONG BufferLength;
  823. ULONG ActualBufferLength;
  824. BOOLEAN ReturnSingleEntry;
  825. PULONG EaNameBuffer;
  826. ULONG ActualEaNameBuffer;
  827. PULONG EaNameBufferLength;
  828. ULONG ActualEaNameBufferLength;
  829. PULONG EaIndex;
  830. ULONG ActualEaIndex;
  831. BOOLEAN RestartScan;
  832. BOOLEAN VerboseResults;
  833. BOOLEAN DisplayParms;
  834. BOOLEAN ParamReceived;
  835. BOOLEAN LastInput;
  836. //
  837. // Initialize to the default value.
  838. //
  839. FileHandleIndex = QEA_FILE_HANDLE_DEFAULT;
  840. BufferIndex = QEA_BUFFER_INDEX_DEFAULT;
  841. BufferLength = QEA_BUFFER_LENGTH_DEFAULT;
  842. ReturnSingleEntry = QEA_RETURN_SINGLE_DEFAULT;
  843. EaNameBuffer = QEA_EA_NAME_BUFFER_DEFAULT;
  844. EaNameBufferLength = QEA_EA_NAME_BUFFER_LEN_DEFAULT;
  845. EaIndex = QEA_EA_INDEX_DEFAULT;
  846. RestartScan = QEA_RESTART_SCAN_DEFAULT;
  847. VerboseResults = QEA_VERBOSE_DEFAULT;
  848. //
  849. // Initialize the other interesting values.
  850. //
  851. ActualBufferLength = 0;
  852. ActualEaNameBuffer = 0;
  853. ActualEaNameBufferLength = 0;
  854. ActualEaIndex = 0;
  855. DisplayParms = FALSE;
  856. ParamReceived = FALSE;
  857. LastInput = TRUE;
  858. //
  859. // While there is more input, analyze the parameter and update the
  860. // query flags.
  861. //
  862. while (TRUE) {
  863. ULONG DummyCount;
  864. //
  865. // Swallow leading white spaces.
  866. //
  867. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  868. if (*ParamBuffer) {
  869. //
  870. // If the next parameter is legal then check the paramter value.
  871. // Update the parameter value.
  872. //
  873. if ((*ParamBuffer == '-'
  874. || *ParamBuffer == '/')
  875. && (ParamBuffer++, *ParamBuffer != '\0')) {
  876. //
  877. // Switch on the next character.
  878. //
  879. switch (*ParamBuffer) {
  880. //
  881. // Update buffer to use.
  882. //
  883. case 'b' :
  884. case 'B' :
  885. //
  886. // Move to the next character, as long as there
  887. // are no white spaces continue analyzing letters.
  888. // On the first bad letter, skip to the next
  889. // parameter.
  890. //
  891. ParamBuffer++;
  892. BufferIndex = AsciiToInteger( ParamBuffer );
  893. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  894. ParamReceived = TRUE;
  895. break;
  896. //
  897. // Update the length of the Ea name buffer.
  898. //
  899. case 'g' :
  900. case 'G' :
  901. //
  902. // Move to the next character, as long as there
  903. // are no white spaces continue analyzing letters.
  904. // On the first bad letter, skip to the next
  905. // parameter.
  906. //
  907. ParamBuffer++;
  908. ActualEaNameBufferLength = AsciiToInteger( ParamBuffer );
  909. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  910. EaNameBufferLength = &ActualEaNameBufferLength;
  911. ParamReceived = TRUE;
  912. break;
  913. //
  914. // Update the file handle index.
  915. //
  916. case 'i' :
  917. case 'I' :
  918. //
  919. // Move to the next character, as long as there
  920. // are no white spaces continue analyzing letters.
  921. // On the first bad letter, skip to the next
  922. // parameter.
  923. //
  924. ParamBuffer++;
  925. FileHandleIndex = AsciiToInteger( ParamBuffer );
  926. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  927. ParamReceived = TRUE;
  928. break;
  929. //
  930. // Update the EA index to start from.
  931. //
  932. case 'e' :
  933. case 'E' :
  934. //
  935. // Move to the next character, as long as there
  936. // are no white spaces continue analyzing letters.
  937. // On the first bad letter, skip to the next
  938. // parameter.
  939. //
  940. ParamBuffer++;
  941. ActualEaIndex = AsciiToInteger( ParamBuffer );
  942. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  943. EaIndex = &ActualEaIndex;
  944. ParamReceived = TRUE;
  945. break;
  946. //
  947. // Update buffer length to pass.
  948. //
  949. case 'l' :
  950. case 'L' :
  951. //
  952. // Move to the next character, as long as there
  953. // are no white spaces continue analyzing letters.
  954. // On the first bad letter, skip to the next
  955. // parameter.
  956. //
  957. ParamBuffer++;
  958. ActualBufferLength = AsciiToInteger( ParamBuffer );
  959. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  960. BufferLength = &ActualBufferLength;
  961. ParamReceived = TRUE;
  962. break;
  963. //
  964. // Update the ea name buffer to use.
  965. //
  966. case 'n' :
  967. case 'N' :
  968. //
  969. // Move to the next character, as long as there
  970. // are no white spaces continue analyzing letters.
  971. // On the first bad letter, skip to the next
  972. // parameter.
  973. //
  974. ParamBuffer++;
  975. ActualEaNameBuffer = AsciiToInteger( ParamBuffer );
  976. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  977. EaNameBuffer = &ActualEaNameBuffer;
  978. ParamReceived = TRUE;
  979. break;
  980. //
  981. // Set or clear the restart flag
  982. //
  983. case 'r' :
  984. case 'R' :
  985. //
  986. // Legal values for params are T/t or F/f.
  987. //
  988. ParamBuffer++;
  989. if (*ParamBuffer == 'T'
  990. || *ParamBuffer == 't') {
  991. RestartScan = TRUE;
  992. ParamBuffer++;
  993. } else if (*ParamBuffer == 'F'
  994. || *ParamBuffer == 'f') {
  995. RestartScan = FALSE;
  996. ParamBuffer++;
  997. }
  998. ParamReceived = TRUE;
  999. break;
  1000. //
  1001. // Set or clear the single ea flag.
  1002. //
  1003. case 's' :
  1004. case 'S' :
  1005. //
  1006. // Legal values for params are T/t or F/f.
  1007. //
  1008. ParamBuffer++;
  1009. if (*ParamBuffer == 'T'
  1010. || *ParamBuffer == 't') {
  1011. ReturnSingleEntry = TRUE;
  1012. ParamBuffer++;
  1013. } else if (*ParamBuffer == 'F'
  1014. || *ParamBuffer == 'f') {
  1015. ReturnSingleEntry = FALSE;
  1016. ParamBuffer++;
  1017. }
  1018. ParamReceived = TRUE;
  1019. break;
  1020. case 'v' :
  1021. case 'V' :
  1022. //
  1023. // Legal values for params are T/t or F/f.
  1024. //
  1025. ParamBuffer++;
  1026. if (*ParamBuffer == 'T'
  1027. || *ParamBuffer == 't') {
  1028. VerboseResults = TRUE;
  1029. ParamBuffer++;
  1030. } else if (*ParamBuffer == 'F'
  1031. || *ParamBuffer == 'f') {
  1032. VerboseResults = FALSE;
  1033. ParamBuffer++;
  1034. }
  1035. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1036. case 'y' :
  1037. case 'Y' :
  1038. //
  1039. // Set the display parms flag and jump over this
  1040. // character.
  1041. //
  1042. DisplayParms = TRUE;
  1043. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1044. break;
  1045. case 'z' :
  1046. case 'Z' :
  1047. //
  1048. // Set flag for more input and jump over this char.
  1049. //
  1050. LastInput = FALSE;
  1051. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1052. break;
  1053. default :
  1054. //
  1055. // Swallow to the next white space and continue the
  1056. // loop.
  1057. //
  1058. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1059. }
  1060. }
  1061. //
  1062. // Else the text is invalid, skip the entire block.
  1063. //
  1064. //
  1065. //
  1066. // Else if there is no input then exit.
  1067. //
  1068. } else if (LastInput) {
  1069. break;
  1070. //
  1071. // Else try to read another line for open parameters.
  1072. //
  1073. } else {
  1074. }
  1075. }
  1076. //
  1077. // If no parameters were received then display the syntax message.
  1078. //
  1079. if (!ParamReceived) {
  1080. printf( "\n Usage: qea [options]*\n" );
  1081. printf( "\n Options:" );
  1082. printf( "\n -i<digits> Open file handle" );
  1083. printf( "\n -b<digits> Output buffer index" );
  1084. printf( "\n -l<digits> Declared length of output buffer (Optional)" );
  1085. printf( "\n -n<digits> Ea name buffer index" );
  1086. printf( "\n -g<digits> Declared length of ea name buffer (Optional)" );
  1087. printf( "\n -e<digits> Ea index to start from" );
  1088. printf( "\n -r[t|f] Restart scan" );
  1089. printf( "\n -s[t|f] Return single entry" );
  1090. printf( "\n -v[t|f] Verbose results" );
  1091. printf( "\n -y Display parameters to query" );
  1092. printf( "\n -z Additional input line" );
  1093. printf( "\n\n" );
  1094. //
  1095. // Else call our query ea routine.
  1096. //
  1097. } else {
  1098. QueryEa( FileHandleIndex,
  1099. &IoStatusBlock,
  1100. BufferIndex,
  1101. BufferLength,
  1102. ReturnSingleEntry,
  1103. EaNameBuffer,
  1104. EaNameBufferLength,
  1105. EaIndex,
  1106. RestartScan,
  1107. VerboseResults,
  1108. DisplayParms );
  1109. }
  1110. return;
  1111. }
  1112. NTSTATUS
  1113. QueryEa (
  1114. IN ULONG FileHandleIndex,
  1115. OUT PIO_STATUS_BLOCK IoStatusBlock,
  1116. IN ULONG BufferIndex,
  1117. IN PULONG BufferLength OPTIONAL,
  1118. IN BOOLEAN ReturnSingleEntry,
  1119. IN PULONG EaNameBuffer OPTIONAL,
  1120. IN PULONG EaNameBufferLength OPTIONAL,
  1121. IN PULONG EaIndex,
  1122. IN BOOLEAN RestartScan,
  1123. IN BOOLEAN VerboseResults,
  1124. IN BOOLEAN DisplayParms
  1125. )
  1126. {
  1127. NTSTATUS Status;
  1128. //
  1129. // Perform initialization.
  1130. //
  1131. IoStatusBlock->Status = STATUS_SUCCESS;
  1132. IoStatusBlock->Information = 0;
  1133. //
  1134. // If the buffer index is unused, display an error message.
  1135. //
  1136. if (!Buffers[BufferIndex].Used) {
  1137. printf( "\nQueryEa: Index refers to invalid buffer" );
  1138. IoStatusBlock->Status = STATUS_INVALID_HANDLE;
  1139. //
  1140. // Else if the ea name buffer is specified but unused, display
  1141. // an error message.
  1142. //
  1143. } else if (EaNameBuffer && !Buffers[*EaNameBuffer].Used) {
  1144. printf( "\nQueryEa: Index refers to invalid buffer" );
  1145. IoStatusBlock->Status = STATUS_INVALID_HANDLE;
  1146. //
  1147. // Display the parameters if requested, then call the query Ea
  1148. // routine. Display the results if requested.
  1149. //
  1150. } else {
  1151. if (DisplayParms) {
  1152. printf( "\nQuery Ea Parameters" );
  1153. printf( "\n Handle index -> %ld", FileHandleIndex );
  1154. printf( "\n Buffer index length -> %lx",
  1155. BufferLength ? *BufferLength : Buffers[BufferIndex].Length );
  1156. printf( "\n Return single entry -> %ld", ReturnSingleEntry );
  1157. if (EaNameBuffer) {
  1158. printf( "\n Ea name buffer index -> %ld",
  1159. *EaNameBuffer );
  1160. printf( "\n Ea name buffer length -> %lx",
  1161. EaNameBufferLength ? *EaNameBufferLength : Buffers[*EaNameBuffer].Length );
  1162. }
  1163. if (EaIndex) {
  1164. printf( "\n Ea index to start at -> %ld", *EaIndex );
  1165. }
  1166. printf( "\n Restart scan -> %ld", RestartScan );
  1167. printf( "\n\n" );
  1168. }
  1169. Status = NtQueryEaFile( Handles[FileHandleIndex].Handle,
  1170. IoStatusBlock,
  1171. Buffers[BufferIndex].Buffer,
  1172. BufferLength
  1173. ? *BufferLength
  1174. : Buffers[BufferIndex].Length,
  1175. ReturnSingleEntry,
  1176. EaNameBuffer
  1177. ? Buffers[*EaNameBuffer].Buffer
  1178. : NULL,
  1179. EaNameBuffer
  1180. ? (EaNameBufferLength
  1181. ? *EaNameBufferLength
  1182. : Buffers[*EaNameBuffer].Length)
  1183. : 0,
  1184. EaIndex,
  1185. RestartScan );
  1186. }
  1187. if (VerboseResults) {
  1188. printf( "\nQuery Ea: Status -> %08lx\n", Status );
  1189. if (NT_SUCCESS( Status )) {
  1190. printf( " Iosb.Information -> %08lx\n", IoStatusBlock->Information );
  1191. printf( " Iosb.Status -> %08lx", IoStatusBlock->Status );
  1192. }
  1193. printf( "\n" );
  1194. }
  1195. return Status;
  1196. }
  1197. VOID
  1198. InputSetEa(
  1199. IN PCHAR ParamBuffer
  1200. )
  1201. {
  1202. ULONG FileHandleIndex;
  1203. IO_STATUS_BLOCK IoStatusBlock;
  1204. ULONG BufferIndex;
  1205. PULONG BufferLength;
  1206. ULONG ActualBufferLength;
  1207. BOOLEAN VerboseResults;
  1208. BOOLEAN DisplayParms;
  1209. BOOLEAN ParamReceived;
  1210. BOOLEAN LastInput;
  1211. //
  1212. // Initialize to the default value.
  1213. //
  1214. FileHandleIndex = SEA_FILE_HANDLE_DEFAULT;
  1215. BufferIndex = SEA_BUFFER_INDEX_DEFAULT;
  1216. BufferLength = SEA_BUFFER_LENGTH_DEFAULT;
  1217. VerboseResults = SEA_VERBOSE_DEFAULT;
  1218. //
  1219. // Initialize the other interesting values.
  1220. //
  1221. ActualBufferLength = 0;
  1222. DisplayParms = FALSE;
  1223. ParamReceived = FALSE;
  1224. LastInput = TRUE;
  1225. //
  1226. // While there is more input, analyze the parameter and update the
  1227. // query flags.
  1228. //
  1229. while (TRUE) {
  1230. ULONG DummyCount;
  1231. //
  1232. // Swallow leading white spaces.
  1233. //
  1234. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  1235. if (*ParamBuffer) {
  1236. //
  1237. // If the next parameter is legal then check the paramter value.
  1238. // Update the parameter value.
  1239. //
  1240. if ((*ParamBuffer == '-'
  1241. || *ParamBuffer == '/')
  1242. && (ParamBuffer++, *ParamBuffer != '\0')) {
  1243. //
  1244. // Switch on the next character.
  1245. //
  1246. switch (*ParamBuffer) {
  1247. //
  1248. // Update buffer to use.
  1249. //
  1250. case 'b' :
  1251. case 'B' :
  1252. //
  1253. // Move to the next character, as long as there
  1254. // are no white spaces continue analyzing letters.
  1255. // On the first bad letter, skip to the next
  1256. // parameter.
  1257. //
  1258. ParamBuffer++;
  1259. BufferIndex = AsciiToInteger( ParamBuffer );
  1260. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1261. ParamReceived = TRUE;
  1262. break;
  1263. //
  1264. // Update the file handle index.
  1265. //
  1266. case 'i' :
  1267. case 'I' :
  1268. //
  1269. // Move to the next character, as long as there
  1270. // are no white spaces continue analyzing letters.
  1271. // On the first bad letter, skip to the next
  1272. // parameter.
  1273. //
  1274. ParamBuffer++;
  1275. FileHandleIndex = AsciiToInteger( ParamBuffer );
  1276. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1277. ParamReceived =TRUE;
  1278. break;
  1279. //
  1280. // Update buffer length to pass.
  1281. //
  1282. case 'l' :
  1283. case 'L' :
  1284. //
  1285. // Move to the next character, as long as there
  1286. // are no white spaces continue analyzing letters.
  1287. // On the first bad letter, skip to the next
  1288. // parameter.
  1289. //
  1290. ParamBuffer++;
  1291. ActualBufferLength = AsciiToInteger( ParamBuffer );
  1292. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1293. BufferLength = &ActualBufferLength;
  1294. ParamReceived = TRUE;
  1295. break;
  1296. case 'v' :
  1297. case 'V' :
  1298. //
  1299. // Legal values for params are T/t or F/f.
  1300. //
  1301. ParamBuffer++;
  1302. if( *ParamBuffer == 'T'
  1303. || *ParamBuffer == 't' ) {
  1304. VerboseResults = TRUE;
  1305. ParamBuffer++;
  1306. } else if( *ParamBuffer == 'F'
  1307. || *ParamBuffer == 'f' ) {
  1308. VerboseResults = FALSE;
  1309. ParamBuffer++;
  1310. }
  1311. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1312. case 'y' :
  1313. case 'Y' :
  1314. //
  1315. // Set the display parms flag and jump over this
  1316. // character.
  1317. //
  1318. DisplayParms = TRUE;
  1319. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1320. break;
  1321. case 'z' :
  1322. case 'Z' :
  1323. //
  1324. // Set flag for more input and jump over this char.
  1325. //
  1326. LastInput = FALSE;
  1327. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1328. break;
  1329. default :
  1330. //
  1331. // Swallow to the next white space and continue the
  1332. // loop.
  1333. //
  1334. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  1335. }
  1336. }
  1337. //
  1338. // Else the text is invalid, skip the entire block.
  1339. //
  1340. //
  1341. //
  1342. // Else if there is no input then exit.
  1343. //
  1344. } else if (LastInput) {
  1345. break;
  1346. //
  1347. // Else try to read another line for open parameters.
  1348. //
  1349. } else {
  1350. }
  1351. }
  1352. //
  1353. // If no parameters were received then display the syntax message.
  1354. //
  1355. if (!ParamReceived) {
  1356. printf( "\n Usage: sea [options]*\n" );
  1357. printf( "\n Options:" );
  1358. printf( "\n -i<digits> Open file handle" );
  1359. printf( "\n -b<digits> Output buffer index" );
  1360. printf( "\n -l<digits> Declared length of output buffer (Optional)" );
  1361. printf( "\n -v[t|f] Verbose results" );
  1362. printf( "\n -y Display parameters to query" );
  1363. printf( "\n -z Additional input line" );
  1364. printf( "\n\n" );
  1365. //
  1366. // Else call our query ea routine.
  1367. //
  1368. } else {
  1369. SetEa( FileHandleIndex,
  1370. &IoStatusBlock,
  1371. BufferIndex,
  1372. BufferLength,
  1373. VerboseResults,
  1374. DisplayParms );
  1375. }
  1376. return;
  1377. }
  1378. NTSTATUS
  1379. SetEa(
  1380. IN ULONG FileHandleIndex,
  1381. OUT PIO_STATUS_BLOCK IoStatusBlock,
  1382. IN ULONG BufferIndex,
  1383. IN PULONG BufferLength OPTIONAL,
  1384. IN BOOLEAN VerboseResults,
  1385. IN BOOLEAN DisplayParms
  1386. )
  1387. {
  1388. NTSTATUS Status;
  1389. if (DisplayParms) {
  1390. printf( "\nSet Ea Parameters" );
  1391. printf( "\n Handle index -> %ld", FileHandleIndex );
  1392. printf( "\n Buffer index -> %ld", BufferIndex );
  1393. printf( "\n Buffer index length -> %lx",
  1394. BufferLength ? *BufferLength : Buffers[BufferIndex].Length );
  1395. printf( "\n\n" );
  1396. }
  1397. //
  1398. // Perform initialization.
  1399. //
  1400. Status = STATUS_SUCCESS;
  1401. IoStatusBlock->Status = STATUS_SUCCESS;
  1402. IoStatusBlock->Information = 0;
  1403. //
  1404. // If the buffer index is unused, display an error message.
  1405. //
  1406. if (!Buffers[BufferIndex].Used) {
  1407. printf( "\nSetEa: Index refers to invalid buffer" );
  1408. IoStatusBlock->Status = STATUS_INVALID_HANDLE;
  1409. //
  1410. // If the handle index is unused, display an error message.
  1411. //
  1412. } else if (!Handles[FileHandleIndex].Used) {
  1413. printf( "\nSetEa: Index refers to invalid file handle" );
  1414. IoStatusBlock->Status = STATUS_INVALID_HANDLE;
  1415. //
  1416. // Display the parameters if requested, then call the query Ea
  1417. // routine. Display the results if requested.
  1418. //
  1419. } else {
  1420. Status = NtSetEaFile( Handles[FileHandleIndex].Handle,
  1421. IoStatusBlock,
  1422. Buffers[BufferIndex].Buffer,
  1423. BufferLength
  1424. ? *BufferLength
  1425. : Buffers[BufferIndex].Length );
  1426. }
  1427. if (VerboseResults) {
  1428. printf( "\nSet Ea: Status -> %08lx\n", Status );
  1429. if (NT_SUCCESS( Status )) {
  1430. printf( " Iosb.Information -> %08lx\n", IoStatusBlock->Information );
  1431. printf( " Iosb.Status -> %08lx", IoStatusBlock->Status );
  1432. }
  1433. printf( "\n" );
  1434. }
  1435. return IoStatusBlock->Status;
  1436. }