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.

1633 lines
36 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. channel.c
  5. Abstract:
  6. Routines for managing channels in the sac.
  7. Author:
  8. Brian Guarraci (briangu) March, 2001.
  9. Sean Selitrennikoff (v-seans) Sept, 2000.
  10. Revision History:
  11. --*/
  12. #include "sac.h"
  13. BOOLEAN
  14. ChannelIsValidType(
  15. SAC_CHANNEL_TYPE ChannelType
  16. )
  17. /*++
  18. Routine Description:
  19. This is a convenience routine to determine if a the given type
  20. is a valid Channel type
  21. Arguments:
  22. ChannelType - the type to be investigated
  23. Return Value:
  24. TRUE - if type is valid
  25. otherwise, FALSE
  26. --*/
  27. {
  28. BOOLEAN isValid;
  29. switch(ChannelType) {
  30. case ChannelTypeVTUTF8:
  31. case ChannelTypeRaw:
  32. case ChannelTypeCmd:
  33. isValid = TRUE;
  34. break;
  35. default:
  36. isValid = FALSE;
  37. break;
  38. }
  39. return isValid;
  40. }
  41. BOOLEAN
  42. ChannelIsActive(
  43. IN PSAC_CHANNEL Channel
  44. )
  45. /*++
  46. Routine Description:
  47. Determine if a channel is active.
  48. Arguments:
  49. Channel - Channel to see if has new data
  50. Return Value:
  51. TRUE - if the channel is active
  52. otherwise, FALSE
  53. --*/
  54. {
  55. SAC_CHANNEL_STATUS Status;
  56. ChannelGetStatus(
  57. Channel,
  58. &Status
  59. );
  60. return (BOOLEAN)(Status == ChannelStatusActive);
  61. }
  62. BOOLEAN
  63. ChannelIsEqual(
  64. IN PSAC_CHANNEL Channel,
  65. IN PSAC_CHANNEL_HANDLE Handle
  66. )
  67. /*++
  68. Routine Description:
  69. Determine if a channel is the same as the one in question
  70. Note: this is to encapsulate the GUID implementation of
  71. channel handles
  72. Arguments:
  73. Channel - Channel to see if has new data
  74. ChannelHandle - The channel handle in question
  75. Return Value:
  76. TRUE - if the channel is active
  77. otherwise, FALSE
  78. --*/
  79. {
  80. return (BOOLEAN)IsEqualGUID(
  81. &(ChannelGetHandle(Channel).ChannelHandle),
  82. &(Handle->ChannelHandle)
  83. );
  84. }
  85. BOOLEAN
  86. ChannelIsClosed(
  87. IN PSAC_CHANNEL Channel
  88. )
  89. /*++
  90. Routine Description:
  91. Determine if a channel is available for reuse. The criterion
  92. for reuse are:
  93. 1. The channel must be inactive
  94. 2. If the preserve bit is FALSE, then HasNewData must == FALSE
  95. Arguments:
  96. Channel - Channel to see if has new data
  97. Return Value:
  98. TRUE - if the channel has unsent data
  99. otherwise, FALSE
  100. --*/
  101. {
  102. SAC_CHANNEL_STATUS Status;
  103. ChannelGetStatus(
  104. Channel,
  105. &Status
  106. );
  107. return (BOOLEAN)(
  108. (Status == ChannelStatusInactive) &&
  109. (ChannelHasNewOBufferData(Channel) == FALSE)
  110. );
  111. }
  112. NTSTATUS
  113. ChannelInitializeVTable(
  114. IN PSAC_CHANNEL Channel
  115. )
  116. /*++
  117. Routine Description:
  118. This routine assigns channel type specific functions.
  119. Arguments:
  120. Channel - The channel to assign the functions to.
  121. Return Value:
  122. STATUS_SUCCESS if successful, else the appropriate error code.
  123. --*/
  124. {
  125. //
  126. // Fill out the channel's vtable according to channel type
  127. //
  128. switch(ChannelGetType(Channel)){
  129. case ChannelTypeVTUTF8:
  130. Channel->Create = VTUTF8ChannelCreate;
  131. Channel->Destroy = VTUTF8ChannelDestroy;
  132. Channel->OFlush = VTUTF8ChannelOFlush;
  133. Channel->OEcho = VTUTF8ChannelOEcho;
  134. Channel->OWrite = VTUTF8ChannelOWrite;
  135. Channel->ORead = VTUTF8ChannelORead;
  136. Channel->IWrite = VTUTF8ChannelIWrite;
  137. Channel->IRead = VTUTF8ChannelIRead;
  138. Channel->IReadLast = VTUTF8ChannelIReadLast;
  139. Channel->IBufferIsFull = VTUTF8ChannelIBufferIsFull;
  140. Channel->IBufferLength = VTUTF8ChannelIBufferLength;
  141. break;
  142. case ChannelTypeRaw:
  143. Channel->Create = RawChannelCreate;
  144. Channel->Destroy = RawChannelDestroy;
  145. Channel->OFlush = RawChannelOFlush;
  146. Channel->OEcho = RawChannelOEcho;
  147. Channel->OWrite = RawChannelOWrite;
  148. Channel->ORead = RawChannelORead;
  149. Channel->IWrite = RawChannelIWrite;
  150. Channel->IRead = RawChannelIRead;
  151. Channel->IReadLast = RawChannelIReadLast;
  152. Channel->IBufferIsFull = RawChannelIBufferIsFull;
  153. Channel->IBufferLength = RawChannelIBufferLength;
  154. break;
  155. case ChannelTypeCmd:
  156. Channel->Create = CmdChannelCreate;
  157. Channel->Destroy = CmdChannelDestroy;
  158. Channel->OFlush = CmdChannelOFlush;
  159. Channel->OEcho = VTUTF8ChannelOEcho;
  160. Channel->OWrite = CmdChannelOWrite;
  161. Channel->ORead = CmdChannelORead;
  162. Channel->IWrite = VTUTF8ChannelIWrite;
  163. Channel->IRead = VTUTF8ChannelIRead;
  164. Channel->IReadLast = VTUTF8ChannelIReadLast;
  165. Channel->IBufferIsFull = VTUTF8ChannelIBufferIsFull;
  166. Channel->IBufferLength = VTUTF8ChannelIBufferLength;
  167. break;
  168. default:
  169. return STATUS_INVALID_PARAMETER;
  170. break;
  171. }
  172. return STATUS_SUCCESS;
  173. }
  174. NTSTATUS
  175. ChannelCreate(
  176. OUT PSAC_CHANNEL Channel,
  177. IN PSAC_CHANNEL_OPEN_ATTRIBUTES Attributes,
  178. IN SAC_CHANNEL_HANDLE Handle
  179. )
  180. /*++
  181. Routine Description:
  182. This routine allocates a channel and returns a pointer to it.
  183. Arguments:
  184. Channel - The resulting channel.
  185. Attributes - All the parameters for the new channel
  186. Handle - The new channel's handle
  187. Return Value:
  188. STATUS_SUCCESS if successful, else the appropriate error code.
  189. --*/
  190. {
  191. NTSTATUS Status;
  192. BOOLEAN b;
  193. PVOID EventObjectBody;
  194. PVOID EventWaitObjectBody;
  195. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  196. ASSERT_STATUS(Attributes, STATUS_INVALID_PARAMETER_2);
  197. //
  198. // Verify that if the user wants to use the CLOSE_EVENT, we received on to use
  199. //
  200. if (Attributes->Flags & SAC_CHANNEL_FLAG_CLOSE_EVENT) {
  201. ASSERT_STATUS(Attributes->CloseEvent != NULL, STATUS_INVALID_PARAMETER);
  202. } else {
  203. ASSERT_STATUS(Attributes->CloseEvent == NULL, STATUS_INVALID_PARAMETER);
  204. }
  205. //
  206. // Verify that if the user wants to use the HAS_NEW_DATA_EVENT, we received one to use
  207. //
  208. if (Attributes->Flags & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT) {
  209. ASSERT_STATUS(Attributes->HasNewDataEvent != NULL, STATUS_INVALID_PARAMETER);
  210. } else {
  211. ASSERT_STATUS(Attributes->HasNewDataEvent == NULL, STATUS_INVALID_PARAMETER);
  212. }
  213. #if ENABLE_CHANNEL_LOCKING
  214. //
  215. // Verify that if the user wants to use the LOCK_EVENT, we received one to use
  216. //
  217. if (Attributes->Flags & SAC_CHANNEL_FLAG_LOCK_EVENT) {
  218. ASSERT_STATUS(Attributes->LockEvent != NULL, STATUS_INVALID_PARAMETER);
  219. } else {
  220. ASSERT_STATUS(Attributes->LockEvent == NULL, STATUS_INVALID_PARAMETER);
  221. }
  222. #endif
  223. //
  224. // Verify that if the user wants to use the LOCK_EVENT, we received one to use
  225. //
  226. if (Attributes->Flags & SAC_CHANNEL_FLAG_REDRAW_EVENT) {
  227. ASSERT_STATUS(Attributes->RedrawEvent != NULL, STATUS_INVALID_PARAMETER);
  228. } else {
  229. ASSERT_STATUS(Attributes->RedrawEvent == NULL, STATUS_INVALID_PARAMETER);
  230. }
  231. //
  232. // Initialize the channel structure
  233. //
  234. do {
  235. //
  236. // Initialize the channel structure
  237. //
  238. RtlZeroMemory(Channel, sizeof(SAC_CHANNEL));
  239. //
  240. // Initialize the channel access locks
  241. //
  242. INIT_CHANNEL_LOCKS(Channel);
  243. //
  244. // copy the name and force NULL termination at the end of the buffer
  245. //
  246. ChannelSetName(
  247. Channel,
  248. Attributes->Name
  249. );
  250. //
  251. // copy the description and force NULL termination at the end of the buffer
  252. //
  253. ChannelSetDescription(
  254. Channel,
  255. Attributes->Description
  256. );
  257. //
  258. // Attempt to get the wait object from the event
  259. //
  260. if (Attributes->CloseEvent) {
  261. b = VerifyEventWaitable(
  262. Attributes->CloseEvent,
  263. &EventObjectBody,
  264. &EventWaitObjectBody
  265. );
  266. if(!b) {
  267. Status = STATUS_INVALID_HANDLE;
  268. break;
  269. }
  270. //
  271. // We successfully got the wait object, so keep it.
  272. //
  273. Channel->CloseEvent = Attributes->CloseEvent;
  274. Channel->CloseEventObjectBody = EventObjectBody;
  275. Channel->CloseEventWaitObjectBody = EventWaitObjectBody;
  276. }
  277. //
  278. // Attempt to get the wait object from the event
  279. //
  280. if (Attributes->HasNewDataEvent) {
  281. b = VerifyEventWaitable(
  282. Attributes->HasNewDataEvent,
  283. &EventObjectBody,
  284. &EventWaitObjectBody
  285. );
  286. if(!b) {
  287. Status = STATUS_INVALID_HANDLE;
  288. break;
  289. }
  290. //
  291. // We successfully got the wait object, so keep it.
  292. //
  293. Channel->HasNewDataEvent = Attributes->HasNewDataEvent;
  294. Channel->HasNewDataEventObjectBody = EventObjectBody;
  295. Channel->HasNewDataEventWaitObjectBody = EventWaitObjectBody;
  296. }
  297. #if ENABLE_CHANNEL_LOCKING
  298. //
  299. // Attempt to get the wait object from the event
  300. //
  301. if (Attributes->LockEvent) {
  302. b = VerifyEventWaitable(
  303. Attributes->LockEvent,
  304. &EventObjectBody,
  305. &EventWaitObjectBody
  306. );
  307. if(!b) {
  308. Status = STATUS_INVALID_HANDLE;
  309. break;
  310. }
  311. //
  312. // We successfully got the wait object, so keep it.
  313. //
  314. Channel->LockEvent = Attributes->LockEvent;
  315. Channel->LockEventObjectBody = EventObjectBody;
  316. Channel->LockEventWaitObjectBody = EventWaitObjectBody;
  317. }
  318. #endif
  319. //
  320. // Attempt to get the wait object from the event
  321. //
  322. if (Attributes->RedrawEvent) {
  323. b = VerifyEventWaitable(
  324. Attributes->RedrawEvent,
  325. &EventObjectBody,
  326. &EventWaitObjectBody
  327. );
  328. if(!b) {
  329. Status = STATUS_INVALID_HANDLE;
  330. break;
  331. }
  332. //
  333. // We successfully got the wait object, so keep it.
  334. //
  335. Channel->RedrawEvent = Attributes->RedrawEvent;
  336. Channel->RedrawEventObjectBody = EventObjectBody;
  337. Channel->RedrawEventWaitObjectBody = EventWaitObjectBody;
  338. }
  339. //
  340. // Copy the remaining attributes
  341. //
  342. // Note: use the channel handle sent to use by the channel manager
  343. //
  344. Channel->Handle = Handle;
  345. Channel->Type = Attributes->Type;
  346. Channel->Flags = Attributes->Flags;
  347. //
  348. // If we have the ApplicationType,
  349. // then save it
  350. //
  351. if (Attributes->Flags & SAC_CHANNEL_FLAG_APPLICATION_TYPE) {
  352. Channel->ApplicationType = Attributes->ApplicationType;
  353. }
  354. //
  355. // Assign the appropriate channel functions base on type
  356. //
  357. Status = ChannelInitializeVTable(Channel);
  358. if (! NT_SUCCESS(Status)) {
  359. IF_SAC_DEBUG(
  360. SAC_DEBUG_FAILS,
  361. KdPrint(("SAC Create Channel :: Failed to initialize vtable\n"))
  362. );
  363. break;
  364. }
  365. //
  366. // Do Channel type specific initialization
  367. //
  368. Status = Channel->Create(Channel);
  369. if (! NT_SUCCESS(Status)) {
  370. IF_SAC_DEBUG(
  371. SAC_DEBUG_FAILS,
  372. KdPrint(("SAC Create Channel :: Failed channel specific initialization\n"))
  373. );
  374. break;
  375. }
  376. //
  377. // The channel is now Active
  378. //
  379. ChannelSetStatus(Channel, ChannelStatusActive);
  380. } while (FALSE);
  381. //
  382. // If the creation failed, destroy the channel object
  383. //
  384. if (! NT_SUCCESS(Status)) {
  385. Channel->Destroy(Channel);
  386. }
  387. return Status;
  388. }
  389. NTSTATUS
  390. ChannelDereferenceHandles(
  391. PSAC_CHANNEL Channel
  392. )
  393. /*++
  394. Routine Description:
  395. This routine dereferences and NULLs the channel's event handles,
  396. if appropriate.
  397. Note: caller must hold channel mutex
  398. Arguments:
  399. Channel - the channel to close
  400. Return Value:
  401. STATUS_SUCCESS - if the mapping was successful
  402. otherwise, error status
  403. --*/
  404. {
  405. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER);
  406. //
  407. // Release the has new data event if we have it
  408. //
  409. if (Channel->HasNewDataEvent) {
  410. //
  411. // validate that the channel's attributes for this event
  412. // are properly set
  413. //
  414. ASSERT(ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT);
  415. ASSERT(Channel->HasNewDataEventObjectBody);
  416. ASSERT(Channel->HasNewDataEventWaitObjectBody);
  417. if (Channel->HasNewDataEventObjectBody) {
  418. ObDereferenceObject(Channel->HasNewDataEventObjectBody);
  419. //
  420. // NULL the event pointers
  421. //
  422. ChannelSetFlags(
  423. Channel,
  424. ChannelGetFlags(Channel) & ~SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT
  425. );
  426. Channel->HasNewDataEvent = NULL;
  427. Channel->HasNewDataEventObjectBody = NULL;
  428. Channel->HasNewDataEventWaitObjectBody = NULL;
  429. }
  430. }
  431. //
  432. // do we have the Close Channel Event?
  433. //
  434. if (Channel->CloseEvent) {
  435. //
  436. // validate that the channel's attributes for this event
  437. // are properly set
  438. //
  439. ASSERT(ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_CLOSE_EVENT);
  440. ASSERT(Channel->CloseEventObjectBody);
  441. ASSERT(Channel->CloseEventWaitObjectBody);
  442. if (Channel->CloseEventObjectBody) {
  443. //
  444. // release the events
  445. //
  446. ObDereferenceObject(Channel->CloseEventObjectBody);
  447. //
  448. // NULL the event pointers
  449. //
  450. ChannelSetFlags(
  451. Channel,
  452. ChannelGetFlags(Channel) & ~SAC_CHANNEL_FLAG_CLOSE_EVENT
  453. );
  454. Channel->CloseEvent = NULL;
  455. Channel->CloseEventObjectBody = NULL;
  456. Channel->CloseEventWaitObjectBody = NULL;
  457. }
  458. }
  459. #if ENABLE_CHANNEL_LOCKING
  460. //
  461. // do we have the Lock Channel Event?
  462. //
  463. if (Channel->LockEvent) {
  464. //
  465. // validate that the channel's attributes for this event
  466. // are properly set
  467. //
  468. ASSERT(ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_LOCK_EVENT);
  469. ASSERT(Channel->LockEventObjectBody);
  470. ASSERT(Channel->LockEventWaitObjectBody);
  471. if (Channel->LockEventObjectBody) {
  472. //
  473. // release the events
  474. //
  475. ObDereferenceObject(Channel->LockEventObjectBody);
  476. //
  477. // NULL the event pointers
  478. //
  479. ChannelSetFlags(
  480. Channel,
  481. ChannelGetFlags(Channel) & ~SAC_CHANNEL_FLAG_LOCK_EVENT
  482. );
  483. Channel->LockEvent = NULL;
  484. Channel->LockEventObjectBody = NULL;
  485. Channel->LockEventWaitObjectBody = NULL;
  486. }
  487. }
  488. #endif
  489. //
  490. // do we have the Redraw Channel Event?
  491. //
  492. if (Channel->RedrawEvent) {
  493. //
  494. // validate that the channel's attributes for this event
  495. // are properly set
  496. //
  497. ASSERT(ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_REDRAW_EVENT);
  498. ASSERT(Channel->RedrawEventObjectBody);
  499. ASSERT(Channel->RedrawEventWaitObjectBody);
  500. if (Channel->RedrawEventObjectBody) {
  501. //
  502. // release the events
  503. //
  504. ObDereferenceObject(Channel->RedrawEventObjectBody);
  505. //
  506. // NULL the event pointers
  507. //
  508. ChannelSetFlags(
  509. Channel,
  510. ChannelGetFlags(Channel) & ~SAC_CHANNEL_FLAG_REDRAW_EVENT
  511. );
  512. Channel->RedrawEvent = NULL;
  513. Channel->RedrawEventObjectBody = NULL;
  514. Channel->RedrawEventWaitObjectBody = NULL;
  515. }
  516. }
  517. return STATUS_SUCCESS;
  518. }
  519. NTSTATUS
  520. ChannelClose(
  521. PSAC_CHANNEL Channel
  522. )
  523. /*++
  524. Routine Description:
  525. This routine closes the given channel and
  526. fires the CloseEvent if specified
  527. Note: caller must hold channel mutex
  528. Arguments:
  529. Channel - the channel to close
  530. Return Value:
  531. STATUS_SUCCESS - if the mapping was successful
  532. otherwise, error status
  533. --*/
  534. {
  535. NTSTATUS Status;
  536. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER);
  537. //
  538. // Set the channel's state to inactive
  539. //
  540. ChannelSetStatus(Channel, ChannelStatusInactive);
  541. //
  542. // do we need to fire the Close Channel Event?
  543. //
  544. if (ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_CLOSE_EVENT) {
  545. ASSERT(Channel->CloseEvent);
  546. ASSERT(Channel->CloseEventObjectBody);
  547. ASSERT(Channel->CloseEventWaitObjectBody);
  548. if (Channel->CloseEventWaitObjectBody) {
  549. //
  550. // Yes, fire the event
  551. //
  552. KeSetEvent(
  553. Channel->CloseEventWaitObjectBody,
  554. EVENT_INCREMENT,
  555. FALSE
  556. );
  557. }
  558. }
  559. //
  560. // Let go of any handles this channel may own
  561. //
  562. Status = ChannelDereferenceHandles(Channel);
  563. return Status;
  564. }
  565. NTSTATUS
  566. ChannelDestroy(
  567. IN PSAC_CHANNEL Channel
  568. )
  569. /*++
  570. Routine Description:
  571. This routine does the final steps of channel destruction.
  572. Arguments:
  573. Channel - The channel to be closed
  574. Return Value:
  575. STATUS_SUCCESS if successful, else the appropriate error code.
  576. --*/
  577. {
  578. NTSTATUS Status;
  579. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER);
  580. //
  581. // Let go of any handles this channel may own
  582. //
  583. Status = ChannelDereferenceHandles(Channel);
  584. return Status;
  585. }
  586. NTSTATUS
  587. ChannelOWrite(
  588. IN PSAC_CHANNEL Channel,
  589. IN PCUCHAR Buffer,
  590. IN ULONG BufferSize
  591. )
  592. /*++
  593. Routine Description:
  594. This is the common entry point for all channel owrite methods.
  595. The purpose of this entry point is to provide a uniform locking
  596. scheme for the obuffer. Channel apps should not call the owrite method
  597. directly, but should use this instead.
  598. Arguments:
  599. Channel - Previously created channel.
  600. Buffer - The buffer to write
  601. BufferSize - The size of the buffer to write
  602. Return Value:
  603. Status
  604. --*/
  605. {
  606. NTSTATUS Status;
  607. //
  608. // Make sure the caller isn't sending an unacceptably
  609. // large sized buffer. This prevents an app from blocking
  610. // the console manager from being blocked while a channel
  611. // dumps it's buffer.
  612. //
  613. ASSERT_STATUS(
  614. BufferSize < CHANNEL_MAX_OWRITE_BUFFER_SIZE,
  615. STATUS_INVALID_PARAMETER_3
  616. );
  617. LOCK_CHANNEL_OBUFFER(Channel);
  618. Status = Channel->OWrite(
  619. Channel,
  620. Buffer,
  621. BufferSize
  622. );
  623. UNLOCK_CHANNEL_OBUFFER(Channel);
  624. return Status;
  625. }
  626. NTSTATUS
  627. ChannelOFlush(
  628. IN PSAC_CHANNEL Channel
  629. )
  630. /*++
  631. Routine Description:
  632. This is the common entry point for all channel OFlush methods.
  633. The purpose of this entry point is to provide a uniform locking
  634. scheme for the obuffer. Channel apps should not call the OFlush method
  635. directly, but should use this instead.
  636. Arguments:
  637. Channel - Previously created channel.
  638. Return Value:
  639. Status
  640. --*/
  641. {
  642. NTSTATUS Status;
  643. LOCK_CHANNEL_OBUFFER(Channel);
  644. Status = Channel->OFlush(Channel);
  645. UNLOCK_CHANNEL_OBUFFER(Channel);
  646. return Status;
  647. }
  648. NTSTATUS
  649. ChannelOEcho(
  650. IN PSAC_CHANNEL Channel,
  651. IN PCUCHAR Buffer,
  652. IN ULONG BufferSize
  653. )
  654. /*++
  655. Routine Description:
  656. This is the common entry point for all channel OEcho methods.
  657. The purpose of this entry point is to provide a uniform locking
  658. scheme for the obuffer. Channel apps should not call the OEcho method
  659. directly, but should use this instead.
  660. Arguments:
  661. Channel - Previously created channel.
  662. Buffer - The buffer to write
  663. BufferSize - The size of the buffer to write
  664. Return Value:
  665. Status
  666. --*/
  667. {
  668. NTSTATUS Status;
  669. LOCK_CHANNEL_OBUFFER(Channel);
  670. Status = Channel->OEcho(
  671. Channel,
  672. Buffer,
  673. BufferSize
  674. );
  675. UNLOCK_CHANNEL_OBUFFER(Channel);
  676. return Status;
  677. }
  678. NTSTATUS
  679. ChannelORead(
  680. IN PSAC_CHANNEL Channel,
  681. IN PUCHAR Buffer,
  682. IN ULONG BufferSize,
  683. OUT PULONG ByteCount
  684. )
  685. /*++
  686. Routine Description:
  687. This is the common entry point for all channel ORead methods.
  688. The purpose of this entry point is to provide a uniform locking
  689. scheme for the obuffer. Channel apps should not call the ORead method
  690. directly, but should use this instead.
  691. Arguments:
  692. Channel - Previously created channel.
  693. Buffer - The buffer to write
  694. BufferSize - The size of the buffer to write
  695. ByteCount - The number bytes read
  696. Return Value:
  697. Status
  698. --*/
  699. {
  700. NTSTATUS Status;
  701. LOCK_CHANNEL_OBUFFER(Channel);
  702. Status = Channel->ORead(
  703. Channel,
  704. Buffer,
  705. BufferSize,
  706. ByteCount
  707. );
  708. UNLOCK_CHANNEL_OBUFFER(Channel);
  709. return Status;
  710. }
  711. NTSTATUS
  712. ChannelIWrite(
  713. IN PSAC_CHANNEL Channel,
  714. IN PCUCHAR Buffer,
  715. IN ULONG BufferSize
  716. )
  717. /*++
  718. Routine Description:
  719. This is the common entry point for all channel iwrite methods.
  720. The purpose of this entry point is to provide a uniform locking
  721. scheme for the ibuffer. Channel apps should not call the iwrite method
  722. directly, but should use this instead.
  723. Arguments:
  724. Channel - Previously created channel.
  725. Buffer - The buffer to write
  726. BufferSize - The size of the buffer to write
  727. Return Value:
  728. Status
  729. --*/
  730. {
  731. NTSTATUS Status;
  732. LOCK_CHANNEL_IBUFFER(Channel);
  733. Status = Channel->IWrite(
  734. Channel,
  735. Buffer,
  736. BufferSize
  737. );
  738. UNLOCK_CHANNEL_IBUFFER(Channel);
  739. return Status;
  740. }
  741. NTSTATUS
  742. ChannelIRead(
  743. IN PSAC_CHANNEL Channel,
  744. IN PUCHAR Buffer,
  745. IN ULONG BufferSize,
  746. OUT PULONG ByteCount
  747. )
  748. /*++
  749. Routine Description:
  750. This is the common entry point for all channel iread methods.
  751. The purpose of this entry point is to provide a uniform locking
  752. scheme for the ibuffer. Channel apps should not call the iread method
  753. directly, but should use this instead.
  754. Arguments:
  755. Channel - Previously created channel.
  756. Buffer - The buffer to read into
  757. BufferSize - The size of the buffer
  758. ByteCount - The # of bytes read
  759. Return Value:
  760. Status
  761. --*/
  762. {
  763. NTSTATUS Status;
  764. LOCK_CHANNEL_IBUFFER(Channel);
  765. Status = Channel->IRead(
  766. Channel,
  767. Buffer,
  768. BufferSize,
  769. ByteCount
  770. );
  771. UNLOCK_CHANNEL_IBUFFER(Channel);
  772. return Status;
  773. }
  774. WCHAR
  775. ChannelIReadLast(
  776. IN PSAC_CHANNEL Channel
  777. )
  778. /*++
  779. Routine Description:
  780. This is the common entry point for all channel ireadlast methods.
  781. The purpose of this entry point is to provide a uniform locking
  782. scheme for the ibuffer. Channel apps should not call the ireadlast method
  783. directly, but should use this instead.
  784. Arguments:
  785. Channel - Previously created channel.
  786. Return Value:
  787. The last character, otherwise UNICODE_NULL
  788. --*/
  789. {
  790. WCHAR wch;
  791. LOCK_CHANNEL_IBUFFER(Channel);
  792. wch = Channel->IReadLast(Channel);
  793. UNLOCK_CHANNEL_IBUFFER(Channel);
  794. return wch;
  795. }
  796. NTSTATUS
  797. ChannelIBufferIsFull(
  798. IN PSAC_CHANNEL Channel,
  799. OUT BOOLEAN* BufferStatus
  800. )
  801. /*++
  802. Routine Description:
  803. This is the common entry point for all channel IBufferIsFull methods.
  804. The purpose of this entry point is to provide a uniform locking
  805. scheme for the ibuffer. Channel apps should not call the IBufferIsFull method
  806. directly, but should use this instead.
  807. Arguments:
  808. Channel - Previously created channel.
  809. BufferStatus - The query result
  810. Return Value:
  811. Status
  812. --*/
  813. {
  814. NTSTATUS Status;
  815. LOCK_CHANNEL_IBUFFER(Channel);
  816. Status = Channel->IBufferIsFull(
  817. Channel,
  818. BufferStatus
  819. );
  820. UNLOCK_CHANNEL_IBUFFER(Channel);
  821. return Status;
  822. }
  823. ULONG
  824. ChannelIBufferLength(
  825. IN PSAC_CHANNEL Channel
  826. )
  827. /*++
  828. Routine Description:
  829. This is the common entry point for all channel IBufferLength methods.
  830. The purpose of this entry point is to provide a uniform locking
  831. scheme for the ibuffer. Channel apps should not call the IBufferLength method
  832. directly, but should use this instead.
  833. Arguments:
  834. Channel - Previously created channel.
  835. Return Value:
  836. The last character, otherwise UNICODE_NULL
  837. --*/
  838. {
  839. ULONG Length;
  840. LOCK_CHANNEL_IBUFFER(Channel);
  841. Length = Channel->IBufferLength(Channel);
  842. UNLOCK_CHANNEL_IBUFFER(Channel);
  843. return Length;
  844. }
  845. NTSTATUS
  846. ChannelGetName(
  847. IN PSAC_CHANNEL Channel,
  848. OUT PWSTR* Name
  849. )
  850. /*++
  851. Routine Description:
  852. This routine retrieves the channel's description and stores it
  853. in a newly allocated buffer
  854. Note: the caller is responsible for releasing the memory holding
  855. the description
  856. Arguments:
  857. Channel - Previously created channel.
  858. Name - the retrieved name
  859. Return Value:
  860. Status
  861. --*/
  862. {
  863. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  864. ASSERT_STATUS(Name, STATUS_INVALID_PARAMETER_2);
  865. *Name = ALLOCATE_POOL(SAC_MAX_CHANNEL_NAME_SIZE, GENERAL_POOL_TAG);
  866. ASSERT_STATUS(*Name, STATUS_NO_MEMORY);
  867. LOCK_CHANNEL_ATTRIBUTES(Channel);
  868. SAFE_WCSCPY(
  869. SAC_MAX_CHANNEL_NAME_SIZE,
  870. *Name,
  871. Channel->Name
  872. );
  873. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  874. return STATUS_SUCCESS;
  875. }
  876. NTSTATUS
  877. ChannelSetName(
  878. IN PSAC_CHANNEL Channel,
  879. IN PCWSTR Name
  880. )
  881. /*++
  882. Routine Description:
  883. This routine sets the channel's name.
  884. Arguments:
  885. Channel - Previously created channel.
  886. Name - The new channel name
  887. Note: this routine does not check to see if the name is unique
  888. Return Value:
  889. Status
  890. --*/
  891. {
  892. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  893. ASSERT_STATUS(Name, STATUS_INVALID_PARAMETER_2);
  894. LOCK_CHANNEL_ATTRIBUTES(Channel);
  895. SAFE_WCSCPY(
  896. SAC_MAX_CHANNEL_NAME_SIZE,
  897. Channel->Name,
  898. Name
  899. );
  900. Channel->Name[SAC_MAX_CHANNEL_NAME_LENGTH] = UNICODE_NULL;
  901. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  902. return STATUS_SUCCESS;
  903. }
  904. NTSTATUS
  905. ChannelGetDescription(
  906. IN PSAC_CHANNEL Channel,
  907. OUT PWSTR* Description
  908. )
  909. /*++
  910. Routine Description:
  911. This routine retrieves the channel's description and stores it
  912. in a newly allocated buffer
  913. Note: the caller is responsible for releasing the memory holding
  914. the description
  915. Arguments:
  916. Channel - Previously created channel.
  917. Description - the retrieved description
  918. Return Value:
  919. Status
  920. --*/
  921. {
  922. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  923. ASSERT_STATUS(Description, STATUS_INVALID_PARAMETER_2);
  924. *Description = ALLOCATE_POOL(SAC_MAX_CHANNEL_DESCRIPTION_SIZE, GENERAL_POOL_TAG);
  925. ASSERT_STATUS(*Description, STATUS_NO_MEMORY);
  926. LOCK_CHANNEL_ATTRIBUTES(Channel);
  927. SAFE_WCSCPY(
  928. SAC_MAX_CHANNEL_DESCRIPTION_SIZE,
  929. *Description,
  930. Channel->Description
  931. );
  932. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  933. return STATUS_SUCCESS;
  934. }
  935. NTSTATUS
  936. ChannelSetDescription(
  937. IN PSAC_CHANNEL Channel,
  938. IN PCWSTR Description
  939. )
  940. /*++
  941. Routine Description:
  942. This routine sets the channels description.
  943. Arguments:
  944. Channel - Previously created channel.
  945. Description - The new description
  946. Return Value:
  947. Status
  948. --*/
  949. {
  950. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  951. LOCK_CHANNEL_ATTRIBUTES(Channel);
  952. if (Description != NULL) {
  953. SAFE_WCSCPY(
  954. SAC_MAX_CHANNEL_DESCRIPTION_SIZE,
  955. Channel->Description,
  956. Description
  957. );
  958. //
  959. // Force a null termination at the end of the description
  960. //
  961. Channel->Description[SAC_MAX_CHANNEL_DESCRIPTION_LENGTH] = UNICODE_NULL;
  962. } else {
  963. //
  964. // make the description 0 length
  965. //
  966. Channel->Description[0] = UNICODE_NULL;
  967. }
  968. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  969. return STATUS_SUCCESS;
  970. }
  971. NTSTATUS
  972. ChannelSetStatus(
  973. IN PSAC_CHANNEL Channel,
  974. IN SAC_CHANNEL_STATUS Status
  975. )
  976. /*++
  977. Routine Description:
  978. This routine sets the channels status.
  979. Arguments:
  980. Channel - Previously created channel.
  981. Status - The channel's new status
  982. Return Value:
  983. NTStatus
  984. --*/
  985. {
  986. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  987. LOCK_CHANNEL_ATTRIBUTES(Channel);
  988. Channel->Status = Status;
  989. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  990. return STATUS_SUCCESS;
  991. }
  992. NTSTATUS
  993. ChannelGetStatus(
  994. IN PSAC_CHANNEL Channel,
  995. OUT SAC_CHANNEL_STATUS* Status
  996. )
  997. /*++
  998. Routine Description:
  999. This routine Gets the channels status.
  1000. Arguments:
  1001. Channel - Previously created channel.
  1002. Status - The channel's new status
  1003. Return Value:
  1004. NTStatus
  1005. --*/
  1006. {
  1007. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  1008. LOCK_CHANNEL_ATTRIBUTES(Channel);
  1009. *Status = Channel->Status;
  1010. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  1011. return STATUS_SUCCESS;
  1012. }
  1013. NTSTATUS
  1014. ChannelSetApplicationType(
  1015. IN PSAC_CHANNEL Channel,
  1016. IN GUID ApplicationType
  1017. )
  1018. /*++
  1019. Routine Description:
  1020. This routine sets the channel's application type.
  1021. Arguments:
  1022. Channel - Previously created channel.
  1023. ApplicationType - Application type
  1024. Return Value:
  1025. NTStatus
  1026. --*/
  1027. {
  1028. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  1029. LOCK_CHANNEL_ATTRIBUTES(Channel);
  1030. Channel->ApplicationType = ApplicationType;
  1031. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  1032. return STATUS_SUCCESS;
  1033. }
  1034. NTSTATUS
  1035. ChannelGetApplicationType(
  1036. IN PSAC_CHANNEL Channel,
  1037. OUT GUID* ApplicationType
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine gets the channel's application type.
  1042. Arguments:
  1043. Channel - Previously created channel.
  1044. ApplicationType - Application type
  1045. Return Value:
  1046. NTStatus
  1047. --*/
  1048. {
  1049. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  1050. LOCK_CHANNEL_ATTRIBUTES(Channel);
  1051. *ApplicationType = Channel->ApplicationType;
  1052. UNLOCK_CHANNEL_ATTRIBUTES(Channel);
  1053. return STATUS_SUCCESS;
  1054. }
  1055. #if ENABLE_CHANNEL_LOCKING
  1056. NTSTATUS
  1057. ChannelSetLockEvent(
  1058. IN PSAC_CHANNEL Channel
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. Set the channel lock event
  1063. Arguments:
  1064. Channel - The channel to fire the event for
  1065. Return Value:
  1066. NTStatus
  1067. --*/
  1068. {
  1069. ASSERT_STATUS(Channel->LockEvent, STATUS_UNSUCCESSFUL);
  1070. ASSERT_STATUS(Channel->LockEventObjectBody, STATUS_UNSUCCESSFUL);
  1071. ASSERT_STATUS(Channel->LockEventWaitObjectBody, STATUS_UNSUCCESSFUL);
  1072. if (Channel->LockEventWaitObjectBody) {
  1073. //
  1074. // fire the event
  1075. //
  1076. KeSetEvent(
  1077. Channel->LockEventWaitObjectBody,
  1078. EVENT_INCREMENT,
  1079. FALSE
  1080. );
  1081. }
  1082. return STATUS_SUCCESS;
  1083. }
  1084. #endif
  1085. NTSTATUS
  1086. ChannelSetRedrawEvent(
  1087. IN PSAC_CHANNEL Channel
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. Set the channel redraw event
  1092. Arguments:
  1093. Channel - The channel to fire the event for
  1094. Return Value:
  1095. NTStatus
  1096. --*/
  1097. {
  1098. ASSERT_STATUS(Channel->RedrawEvent, STATUS_UNSUCCESSFUL);
  1099. ASSERT_STATUS(Channel->RedrawEventObjectBody, STATUS_UNSUCCESSFUL);
  1100. ASSERT_STATUS(Channel->RedrawEventWaitObjectBody, STATUS_UNSUCCESSFUL);
  1101. if (Channel->RedrawEventWaitObjectBody) {
  1102. //
  1103. // fire the event
  1104. //
  1105. KeSetEvent(
  1106. Channel->RedrawEventWaitObjectBody,
  1107. EVENT_INCREMENT,
  1108. FALSE
  1109. );
  1110. }
  1111. return STATUS_SUCCESS;
  1112. }
  1113. NTSTATUS
  1114. ChannelClearRedrawEvent(
  1115. IN PSAC_CHANNEL Channel
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. Clear the channel redraw event
  1120. Arguments:
  1121. Channel - The channel to fire the event for
  1122. Return Value:
  1123. NTStatus
  1124. --*/
  1125. {
  1126. ASSERT_STATUS(Channel->RedrawEvent, STATUS_UNSUCCESSFUL);
  1127. ASSERT_STATUS(Channel->RedrawEventObjectBody, STATUS_UNSUCCESSFUL);
  1128. ASSERT_STATUS(Channel->RedrawEventWaitObjectBody, STATUS_UNSUCCESSFUL);
  1129. if (Channel->RedrawEventWaitObjectBody) {
  1130. //
  1131. // clear the event
  1132. //
  1133. KeClearEvent( Channel->RedrawEventWaitObjectBody );
  1134. }
  1135. return STATUS_SUCCESS;
  1136. }
  1137. NTSTATUS
  1138. ChannelHasRedrawEvent(
  1139. IN PSAC_CHANNEL Channel,
  1140. OUT PBOOLEAN Present
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. This routine determines if the channel has the Redraw event present.
  1145. Arguments:
  1146. Channel - the channel to query
  1147. Return Value:
  1148. TRUE - the channel has the event
  1149. FALSE - Otherwise
  1150. --*/
  1151. {
  1152. ASSERT_STATUS(Channel, STATUS_INVALID_PARAMETER_1);
  1153. ASSERT_STATUS(Present, STATUS_INVALID_PARAMETER_2);
  1154. *Present = (ChannelGetFlags(Channel) & SAC_CHANNEL_FLAG_REDRAW_EVENT) ? TRUE : FALSE;
  1155. return STATUS_SUCCESS;
  1156. }