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.

1008 lines
22 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. rawchan.c
  5. Abstract:
  6. Routines for managing channels in the sac.
  7. Author:
  8. Sean Selitrennikoff (v-seans) Sept, 2000.
  9. Brian Guarraci (briangu) March, 2001.
  10. Revision History:
  11. --*/
  12. #include "sac.h"
  13. VOID
  14. RawChannelSetIBufferIndex(
  15. IN PSAC_CHANNEL Channel,
  16. IN ULONG IBufferIndex
  17. );
  18. ULONG
  19. RawChannelGetIBufferIndex(
  20. IN PSAC_CHANNEL Channel
  21. );
  22. NTSTATUS
  23. RawChannelCreate(
  24. IN OUT PSAC_CHANNEL Channel
  25. )
  26. /*++
  27. Routine Description:
  28. This routine allocates a channel and returns a pointer to it.
  29. Arguments:
  30. Channel - The resulting channel.
  31. OpenChannelCmd - All the parameters for the new channel
  32. Return Value:
  33. STATUS_SUCCESS if successful, else the appropriate error code.
  34. --*/
  35. {
  36. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER);
  37. Channel->OBuffer = (PUCHAR)ALLOCATE_POOL(SAC_RAW_OBUFFER_SIZE, GENERAL_POOL_TAG);
  38. ASSERT_STATUS(Channel->OBuffer, STATUS_NO_MEMORY);
  39. Channel->IBuffer = (PUCHAR)ALLOCATE_POOL(SAC_RAW_IBUFFER_SIZE, GENERAL_POOL_TAG);
  40. ASSERT_STATUS(Channel->IBuffer, STATUS_NO_MEMORY);
  41. Channel->OBufferIndex = 0;
  42. Channel->OBufferFirstGoodIndex = 0;
  43. ChannelSetIBufferHasNewData(Channel, FALSE);
  44. ChannelSetOBufferHasNewData(Channel, FALSE);
  45. return STATUS_SUCCESS;
  46. }
  47. NTSTATUS
  48. RawChannelDestroy(
  49. IN OUT PSAC_CHANNEL Channel
  50. )
  51. /*++
  52. Routine Description:
  53. This routine closes a channel.
  54. Arguments:
  55. Channel - The channel to be closed
  56. Return Value:
  57. STATUS_SUCCESS if successful, else the appropriate error code.
  58. --*/
  59. {
  60. NTSTATUS Status;
  61. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER);
  62. //
  63. // Free the dynamically allocated memory
  64. //
  65. if (Channel->OBuffer) {
  66. FREE_POOL(&(Channel->OBuffer));
  67. Channel->OBuffer = NULL;
  68. }
  69. if (Channel->IBuffer) {
  70. FREE_POOL(&(Channel->IBuffer));
  71. Channel->IBuffer = NULL;
  72. }
  73. //
  74. // Now that we've done our channel specific destroy,
  75. // Call the general channel destroy
  76. //
  77. Status = ChannelDestroy(Channel);
  78. return Status;
  79. }
  80. NTSTATUS
  81. RawChannelORead(
  82. IN PSAC_CHANNEL Channel,
  83. IN PUCHAR Buffer,
  84. IN ULONG BufferSize,
  85. OUT PULONG ByteCount
  86. )
  87. /*++
  88. Routine Description:
  89. This routine attempts to read BufferSize characters from the output buffer.
  90. Arguments:
  91. Channel - Previously created channel.
  92. Buffer - Outgoing buffer
  93. BufferSize - Outgoing buffer size
  94. ByteCount - The number of bytes actually read
  95. Note: if the buffered data stored in the channel has now been sent.
  96. If Channel is also in the Inactive state, the channel will
  97. now be qualified for removal.
  98. Return Value:
  99. Status
  100. --*/
  101. {
  102. NTSTATUS Status;
  103. PUCHAR RawBuffer;
  104. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  105. ASSERT_STATUS(Buffer, STATUS_INVALID_PARAMETER_2);
  106. ASSERT_STATUS(BufferSize > 0, STATUS_INVALID_PARAMETER_3);
  107. ASSERT_STATUS(ByteCount, STATUS_INVALID_PARAMETER_4);
  108. do {
  109. //
  110. // We read 0 characters
  111. //
  112. *ByteCount = 0;
  113. //
  114. // if there is no data to read,
  115. // then report this to the caller
  116. // else read as much data as we can
  117. //
  118. if (! ChannelHasNewOBufferData(Channel)) {
  119. //
  120. // We are out of data
  121. //
  122. Status = STATUS_NO_DATA_DETECTED;
  123. break;
  124. }
  125. //
  126. // Get the raw channel obuffer
  127. //
  128. RawBuffer = (PUCHAR)Channel->OBuffer;
  129. //
  130. // default: we succeded to copy data
  131. //
  132. Status = STATUS_SUCCESS;
  133. //
  134. // Attempt to read the buffer
  135. //
  136. do {
  137. //
  138. // Do a byte-wise copy of the OBuffer to the destination buffer
  139. //
  140. // Note: doing a byte-wise copy rather than an RtlCopyMemory is
  141. // ok here since in general, this routine is called with
  142. // a small buffer size. Naturally, if the use of Raw Channels
  143. // changes and becomes dependent on a faster ORead, this
  144. // will have to change.
  145. //
  146. //
  147. // copy the char
  148. //
  149. Buffer[*ByteCount] = RawBuffer[Channel->OBufferFirstGoodIndex];
  150. //
  151. // increment the byte count to what we actually read
  152. //
  153. *ByteCount += 1;
  154. //
  155. // advance the pointer to the next good index
  156. //
  157. Channel->OBufferFirstGoodIndex = (Channel->OBufferFirstGoodIndex + 1) % SAC_RAW_OBUFFER_SIZE;
  158. //
  159. // Make sure we don't pass the end of the buffer
  160. //
  161. if (Channel->OBufferFirstGoodIndex == Channel->OBufferIndex) {
  162. //
  163. // we have no new data
  164. //
  165. ChannelSetOBufferHasNewData(Channel, FALSE);
  166. break;
  167. }
  168. //
  169. // confirm the obvious
  170. //
  171. ASSERT(*ByteCount > 0);
  172. } while(*ByteCount < BufferSize);
  173. } while ( FALSE );
  174. #if DBG
  175. //
  176. // More sanity checking
  177. //
  178. if (Channel->OBufferFirstGoodIndex == Channel->OBufferIndex) {
  179. ASSERT(ChannelHasNewOBufferData(Channel) == FALSE);
  180. }
  181. if (ChannelHasNewOBufferData(Channel) == FALSE) {
  182. ASSERT(Channel->OBufferFirstGoodIndex == Channel->OBufferIndex);
  183. }
  184. #endif
  185. return Status;
  186. }
  187. NTSTATUS
  188. RawChannelOEcho(
  189. IN PSAC_CHANNEL Channel,
  190. IN PCUCHAR String,
  191. IN ULONG Size
  192. )
  193. /*++
  194. Routine Description:
  195. This routine puts the string out the headless port.
  196. Arguments:
  197. Channel - Previously created channel.
  198. String - Output string.
  199. Length - The # of String bytes to process
  200. Return Value:
  201. STATUS_SUCCESS if successful, otherwise status
  202. --*/
  203. {
  204. NTSTATUS Status;
  205. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  206. ASSERT_STATUS(String, STATUS_INVALID_PARAMETER_2);
  207. ASSERT(FIELD_OFFSET(HEADLESS_CMD_PUT_STRING, String) == 0); // ASSERT if anyone changes this structure.
  208. //
  209. // Default: we succeeded
  210. //
  211. Status = STATUS_SUCCESS;
  212. //
  213. // Only echo if the buffer has something to send
  214. //
  215. if (Size > 0) {
  216. //
  217. // Send the bytes
  218. //
  219. Status = IoMgrWriteData(
  220. Channel,
  221. String,
  222. Size
  223. );
  224. //
  225. // If we were successful, flush the channel's data in the iomgr
  226. //
  227. if (NT_SUCCESS(Status)) {
  228. Status = IoMgrFlushData(Channel);
  229. }
  230. }
  231. return Status;
  232. }
  233. NTSTATUS
  234. RawChannelOWrite(
  235. IN PSAC_CHANNEL Channel,
  236. IN PCUCHAR String,
  237. IN ULONG Size
  238. )
  239. /*++
  240. Routine Description:
  241. This routine takes a string and prints it to the specified channel. If the channel
  242. is the currently active channel, it puts the string out the headless port as well.
  243. Note: Current Channel lock must be held by caller
  244. Arguments:
  245. Channel - Previously created channel.
  246. String - Output string.
  247. Length - The # of String bytes to process
  248. Return Value:
  249. STATUS_SUCCESS if successful, otherwise status
  250. --*/
  251. {
  252. NTSTATUS Status;
  253. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  254. ASSERT_STATUS(String, STATUS_INVALID_PARAMETER_2);
  255. ASSERT(FIELD_OFFSET(HEADLESS_CMD_PUT_STRING, String) == 0); // ASSERT if anyone changes this structure.
  256. do {
  257. //
  258. // if the current channel is the active channel and the user has selected
  259. // to display this channel, relay the output directly to the user
  260. //
  261. if (IoMgrIsWriteEnabled(Channel) && ChannelSentToScreen(Channel)){
  262. Status = RawChannelOEcho(
  263. Channel,
  264. String,
  265. Size
  266. );
  267. if (! NT_SUCCESS(Status)) {
  268. break;
  269. }
  270. } else {
  271. //
  272. // Write the data to the channel's obuffer
  273. //
  274. Status = RawChannelOWrite2(
  275. Channel,
  276. String,
  277. Size
  278. );
  279. if (! NT_SUCCESS(Status)) {
  280. break;
  281. }
  282. }
  283. } while ( FALSE );
  284. return Status;
  285. }
  286. NTSTATUS
  287. RawChannelOWrite2(
  288. IN PSAC_CHANNEL Channel,
  289. IN PCUCHAR String,
  290. IN ULONG Size
  291. )
  292. /*++
  293. Routine Description:
  294. This routine takes a string and prints it into directly into the
  295. screen buffer with NO translation.
  296. Arguments:
  297. Channel - Previously created channel.
  298. String - String to print.
  299. Size - the # of bytes to write.
  300. Note: If String is a character string, the Size = strlen(String),
  301. otherwise, Size = the # of bytes to process.
  302. Return Value:
  303. STATUS_SUCCESS if successful, otherwise status
  304. --*/
  305. {
  306. ULONG i;
  307. BOOLEAN TrackIndex;
  308. PUCHAR RawBuffer;
  309. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  310. ASSERT_STATUS(String, STATUS_INVALID_PARAMETER_2);
  311. //
  312. // If size == 0, then we are done
  313. //
  314. if (Size == 0) {
  315. return STATUS_SUCCESS;
  316. }
  317. //
  318. // Get the raw channel obuffer
  319. //
  320. RawBuffer = (PUCHAR)Channel->OBuffer;
  321. //
  322. // We are not in direct IO mode, so we need to buffer the string
  323. //
  324. TrackIndex = FALSE;
  325. for (i = 0; i < Size; i++) {
  326. //
  327. // Did we span over Good Data? If so, then we need to
  328. // move the First Good pointer. The new First Good pointer position
  329. // is immediately after the newest data entry in the buffer.
  330. //
  331. // Note: Since both indices start at the same position,
  332. // we need to skip the case when RawBufferIndex == RawBufferFirstGoodIndex
  333. // and there is no data in the buffer ((i == 0) && RawBufferHasNewData == FALSE),
  334. // otherwise the RawBufferFirstGoodIndex will always track the RawBufferIndex.
  335. // We need to let RawBufferIndex go around the ring buffer once before we enable
  336. // tracking.
  337. //
  338. if ((Channel->OBufferIndex == Channel->OBufferFirstGoodIndex) &&
  339. ((i > 0) || (ChannelHasNewOBufferData(Channel) == TRUE))
  340. ) {
  341. TrackIndex = TRUE;
  342. }
  343. ASSERT(Channel->OBufferIndex < SAC_RAW_OBUFFER_SIZE);
  344. RawBuffer[Channel->OBufferIndex] = String[i];
  345. Channel->OBufferIndex = (Channel->OBufferIndex + 1) % SAC_RAW_OBUFFER_SIZE;
  346. if (TrackIndex) {
  347. Channel->OBufferFirstGoodIndex = Channel->OBufferIndex;
  348. }
  349. }
  350. ChannelSetOBufferHasNewData(Channel, TRUE);
  351. return STATUS_SUCCESS;
  352. }
  353. NTSTATUS
  354. RawChannelOFlush(
  355. IN PSAC_CHANNEL Channel
  356. )
  357. /*++
  358. Routine Description:
  359. Send all the data in the raw buffer since the channel was last active
  360. (or since the channel was created)
  361. Arguments:
  362. Channel - Previously created channel.
  363. Return Value:
  364. STATUS_SUCCESS if successful, otherwise status
  365. --*/
  366. {
  367. NTSTATUS Status;
  368. PUCHAR RawBuffer;
  369. UCHAR ch;
  370. ULONG ByteCount;
  371. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  372. //
  373. // Get the raw channel obuffer
  374. //
  375. RawBuffer = (PUCHAR)Channel->OBuffer;
  376. //
  377. // default: we succeeded
  378. //
  379. Status = STATUS_SUCCESS;
  380. //
  381. // Send the Obuffer out to the headless port
  382. //
  383. while ( ChannelHasNewOBufferData(Channel) == TRUE ) {
  384. //
  385. // get a byte from the OBuffer
  386. //
  387. Status = RawChannelORead(
  388. Channel,
  389. &ch,
  390. sizeof(ch),
  391. &ByteCount
  392. );
  393. if (! NT_SUCCESS(Status)) {
  394. break;
  395. }
  396. ASSERT(ByteCount == 1);
  397. if (ByteCount != 1) {
  398. Status = STATUS_UNSUCCESSFUL;
  399. break;
  400. }
  401. //
  402. // Send the byte
  403. //
  404. Status = IoMgrWriteData(
  405. Channel,
  406. &ch,
  407. sizeof(ch)
  408. );
  409. if (! NT_SUCCESS(Status)) {
  410. break;
  411. }
  412. }
  413. //
  414. // If we were successful, flush the channel's data in the iomgr
  415. //
  416. if (NT_SUCCESS(Status)) {
  417. Status = IoMgrFlushData(Channel);
  418. }
  419. return Status;
  420. }
  421. NTSTATUS
  422. RawChannelIWrite(
  423. IN PSAC_CHANNEL Channel,
  424. IN PCUCHAR Buffer,
  425. IN ULONG BufferSize
  426. )
  427. /*++
  428. Routine Description:
  429. This routine takes a single character and adds it to the buffered input for this channel.
  430. Arguments:
  431. Channel - Previously created channel.
  432. Buffer - Incoming buffer of UCHARs
  433. BufferSize - Incoming buffer size
  434. Return Value:
  435. STATUS_SUCCESS if successful, otherwise status
  436. --*/
  437. {
  438. NTSTATUS Status;
  439. BOOLEAN IBufferStatus;
  440. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  441. ASSERT_STATUS(Buffer, STATUS_INVALID_PARAMETER_2);
  442. ASSERT_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
  443. //
  444. // Make sure we aren't full
  445. //
  446. Status = RawChannelIBufferIsFull(
  447. Channel,
  448. &IBufferStatus
  449. );
  450. if (! NT_SUCCESS(Status)) {
  451. return Status;
  452. }
  453. //
  454. // If there is no more room, then fail
  455. //
  456. if (IBufferStatus == TRUE) {
  457. return STATUS_UNSUCCESSFUL;
  458. }
  459. //
  460. // make sure there is enough room for the buffer
  461. //
  462. // Note: this prevents us from writing a portion of the buffer
  463. // and then failing, leaving the caller in the state where
  464. // it doesn't know how much of the buffer was written.
  465. //
  466. if ((SAC_RAW_IBUFFER_SIZE - RawChannelGetIBufferIndex(Channel)) < BufferSize) {
  467. return STATUS_INSUFFICIENT_RESOURCES;
  468. }
  469. //
  470. // default: we succeeded
  471. //
  472. Status = STATUS_SUCCESS;
  473. //
  474. // Copy the new data to the ibuffer
  475. //
  476. RtlCopyMemory(
  477. &Channel->IBuffer[RawChannelGetIBufferIndex(Channel)],
  478. Buffer,
  479. BufferSize
  480. );
  481. //
  482. // Account for the newly appended data
  483. //
  484. RawChannelSetIBufferIndex(
  485. Channel,
  486. RawChannelGetIBufferIndex(Channel) + BufferSize
  487. );
  488. //
  489. // Fire the HasNewData event if specified
  490. //
  491. if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) {
  492. ASSERT(Channel->HasNewDataEvent);
  493. ASSERT(Channel->HasNewDataEventObjectBody);
  494. ASSERT(Channel->HasNewDataEventWaitObjectBody);
  495. KeSetEvent(
  496. Channel->HasNewDataEventWaitObjectBody,
  497. EVENT_INCREMENT,
  498. FALSE
  499. );
  500. }
  501. return Status;
  502. }
  503. NTSTATUS
  504. RawChannelIRead(
  505. IN PSAC_CHANNEL Channel,
  506. IN PUCHAR Buffer,
  507. IN ULONG BufferSize,
  508. OUT PULONG ByteCount
  509. )
  510. /*++
  511. Routine Description:
  512. This routine takes the first character in the input buffer, removes and returns it. If
  513. there is none, it returns 0x0.
  514. Arguments:
  515. Channel - Previously created channel.
  516. Buffer - The buffer to read into
  517. BufferSize - The size of the buffer
  518. ByteCount - The # of bytes read
  519. Return Value:
  520. Status
  521. --*/
  522. {
  523. ULONG CopyChars;
  524. ULONG CopySize;
  525. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  526. ASSERT_STATUS(Buffer, STATUS_INVALID_PARAMETER_2);
  527. ASSERT_STATUS(BufferSize > 0, STATUS_INVALID_BUFFER_SIZE);
  528. //
  529. // initialize
  530. //
  531. CopyChars = 0;
  532. CopySize = 0;
  533. //
  534. // Default: no bytes were read
  535. //
  536. *ByteCount = 0;
  537. //
  538. // If there is nothing to send,
  539. // then return that we read 0 bytes
  540. //
  541. if (Channel->IBufferLength(Channel) == 0) {
  542. ASSERT(ChannelHasNewIBufferData(Channel) == FALSE);
  543. return STATUS_SUCCESS;
  544. }
  545. //
  546. // Caclulate the largest buffer size we can use (and need), and then calculate
  547. // the number of characters this refers to.
  548. //
  549. CopySize = Channel->IBufferLength(Channel) * sizeof(UCHAR);
  550. CopySize = CopySize > BufferSize ? BufferSize : CopySize;
  551. CopyChars = CopySize / sizeof(UCHAR);
  552. //
  553. // We need to recalc the CopySize in case there was a rounding down when
  554. // computing CopyChars
  555. //
  556. CopySize = CopyChars * sizeof(UCHAR);
  557. ASSERT(CopyChars <= Channel->IBufferLength(Channel));
  558. //
  559. // Do a block copy of the ibuffer to the destination buffer
  560. //
  561. RtlCopyMemory(
  562. Buffer,
  563. Channel->IBuffer,
  564. CopySize
  565. );
  566. //
  567. // subtract the # of characters copied from the character counter
  568. //
  569. RawChannelSetIBufferIndex(
  570. Channel,
  571. RawChannelGetIBufferIndex(Channel) - CopyChars
  572. );
  573. //
  574. // If there is remaining data left in the Channel input buffer,
  575. // shift it to the beginning
  576. //
  577. if (Channel->IBufferLength(Channel) > 0) {
  578. RtlMoveMemory(&(Channel->IBuffer[0]),
  579. &(Channel->IBuffer[CopyChars]),
  580. Channel->IBufferLength(Channel) * sizeof(Channel->IBuffer[0])
  581. );
  582. }
  583. //
  584. // Send back the # of bytes read
  585. //
  586. *ByteCount = CopySize;
  587. return STATUS_SUCCESS;
  588. }
  589. NTSTATUS
  590. RawChannelIBufferIsFull(
  591. IN PSAC_CHANNEL Channel,
  592. OUT BOOLEAN* BufferStatus
  593. )
  594. /*++
  595. Routine Description:
  596. Determine if the IBuffer is full
  597. Arguments:
  598. Channel - Previously created channel.
  599. BufferStatus - on exit, TRUE if the buffer is full, otherwise FALSE
  600. Return Value:
  601. Status
  602. --*/
  603. {
  604. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  605. ASSERT_STATUS(BufferStatus, STATUS_INVALID_PARAMETER_2);
  606. *BufferStatus = (BOOLEAN)(RawChannelGetIBufferIndex(Channel) >= (SAC_RAW_IBUFFER_SIZE-1));
  607. return STATUS_SUCCESS;
  608. }
  609. ULONG
  610. RawChannelIBufferLength(
  611. IN PSAC_CHANNEL Channel
  612. )
  613. /*++
  614. Routine Description:
  615. This routine determines the length of the input buffer, treating the input buffer
  616. contents as a string
  617. Arguments:
  618. Channel - Previously created channel.
  619. Return Value:
  620. The length of the current input buffer
  621. --*/
  622. {
  623. ASSERT(Channel);
  624. return (RawChannelGetIBufferIndex(Channel) / sizeof(UCHAR));
  625. }
  626. WCHAR
  627. RawChannelIReadLast(
  628. IN PSAC_CHANNEL Channel
  629. )
  630. /*++
  631. Routine Description:
  632. This routine takes the last character in the input buffer, removes and returns it. If
  633. there is none, it returns 0x0.
  634. Arguments:
  635. Channel - Previously created channel.
  636. Return Value:
  637. Last character in the input buffer.
  638. --*/
  639. {
  640. WCHAR Char;
  641. ASSERT(Channel);
  642. //
  643. // default: no character was read
  644. //
  645. Char = UNICODE_NULL;
  646. if (Channel->IBufferLength(Channel) > 0) {
  647. RawChannelSetIBufferIndex(
  648. Channel,
  649. RawChannelGetIBufferIndex(Channel) - sizeof(UCHAR)
  650. );
  651. Char = Channel->IBuffer[RawChannelGetIBufferIndex(Channel)];
  652. Channel->IBuffer[RawChannelGetIBufferIndex(Channel)] = UNICODE_NULL;
  653. }
  654. return Char;
  655. }
  656. ULONG
  657. RawChannelGetIBufferIndex(
  658. IN PSAC_CHANNEL Channel
  659. )
  660. /*++
  661. Routine Description:
  662. Get teh ibuffer index
  663. Arguments:
  664. Channel - the channel to get the ibuffer index from
  665. Environment:
  666. The ibuffer index
  667. --*/
  668. {
  669. ASSERT(Channel);
  670. //
  671. // Make sure the ibuffer index is atleast aligned to a WCHAR
  672. //
  673. ASSERT((Channel->IBufferIndex % sizeof(UCHAR)) == 0);
  674. //
  675. // Make sure the ibuffer index is in bounds
  676. //
  677. ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
  678. return Channel->IBufferIndex;
  679. }
  680. VOID
  681. RawChannelSetIBufferIndex(
  682. IN PSAC_CHANNEL Channel,
  683. IN ULONG IBufferIndex
  684. )
  685. /*++
  686. Routine Description:
  687. Set the ibuffer index
  688. Arguments:
  689. Channel - the channel to get the ibuffer index from
  690. IBufferIndex - the new inbuffer index
  691. Environment:
  692. None
  693. --*/
  694. {
  695. ASSERT(Channel);
  696. //
  697. // Make sure the ibuffer index is atleast aligned to a WCHAR
  698. //
  699. ASSERT((Channel->IBufferIndex % sizeof(UCHAR)) == 0);
  700. //
  701. // Make sure the ibuffer index is in bounds
  702. //
  703. ASSERT(Channel->IBufferIndex < SAC_RAW_IBUFFER_SIZE);
  704. //
  705. // Set the index
  706. //
  707. Channel->IBufferIndex = IBufferIndex;
  708. //
  709. // Set the has new data flag accordingly
  710. //
  711. ChannelSetIBufferHasNewData(
  712. Channel,
  713. Channel->IBufferIndex == 0 ? FALSE : TRUE
  714. );
  715. //
  716. // Additional checking if the index == 0
  717. //
  718. if (Channel->IBufferIndex == 0) {
  719. //
  720. // Clear the Has New Data event if specified
  721. //
  722. if (Channel->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) {
  723. ASSERT(Channel->HasNewDataEvent);
  724. ASSERT(Channel->HasNewDataEventObjectBody);
  725. ASSERT(Channel->HasNewDataEventWaitObjectBody);
  726. KeClearEvent(Channel->HasNewDataEventWaitObjectBody);
  727. }
  728. }
  729. }