ClientConnection.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // ClientConnection.cpp - 用户态连接管理实现
  2. #include <ntddk.h>
  3. #include <wdf.h>
  4. #include "ClientConnection.h"
  5. #include "EventRingBuffer.h"
  6. #include "../common/CommKitIoctl.h"
  7. #include "../common/CommKitEvents.h"
  8. namespace commkit_driver {
  9. // 全局实例
  10. ClientConnection g_ClientConnection;
  11. void ClientConnection::Initialize() {
  12. ports_count_ = 0;
  13. control_device_ = nullptr;
  14. callback_registered_ = FALSE;
  15. KeInitializeSpinLock(&ports_lock_);
  16. RtlZeroMemory(ports_table_, sizeof(ports_table_));
  17. }
  18. void ClientConnection::Cleanup() {
  19. // 释放所有端口的环形缓冲
  20. KIRQL old_irql;
  21. KeAcquireSpinLock(&ports_lock_, &old_irql);
  22. for (ULONG i = 0; i < ports_count_; ++i) {
  23. PDEVICE_CONTEXT ctx = ports_table_[i].Context;
  24. if (ctx && ctx->RingBuffer) {
  25. EventRingBuffer* ring = (EventRingBuffer*)ctx->RingBuffer;
  26. ring->Cleanup();
  27. ExFreePoolWithTag(ring, 'RBCK');
  28. ctx->RingBuffer = nullptr;
  29. }
  30. }
  31. ports_count_ = 0;
  32. KeReleaseSpinLock(&ports_lock_, old_irql);
  33. }
  34. void ClientConnection::RegisterFilterDevice(ULONG com_number, WDFDEVICE device) {
  35. KIRQL old_irql;
  36. KeAcquireSpinLock(&ports_lock_, &old_irql);
  37. if (ports_count_ < 256) {
  38. PDEVICE_CONTEXT ctx = DeviceGetContext(device);
  39. ports_table_[ports_count_].ComNumber = com_number;
  40. ports_table_[ports_count_].Context = ctx;
  41. ports_count_++;
  42. ctx->ComNumber = com_number;
  43. ctx->MonitoringEnabled = FALSE;
  44. ctx->WdfDevice = device;
  45. }
  46. KeReleaseSpinLock(&ports_lock_, old_irql);
  47. }
  48. void ClientConnection::UnregisterFilterDevice(ULONG com_number) {
  49. KIRQL old_irql;
  50. KeAcquireSpinLock(&ports_lock_, &old_irql);
  51. for (ULONG i = 0; i < ports_count_; ++i) {
  52. if (ports_table_[i].ComNumber == com_number) {
  53. // 移动最后一个元素到当前位置
  54. PDEVICE_CONTEXT ctx = ports_table_[i].Context;
  55. if (ctx && ctx->RingBuffer) {
  56. EventRingBuffer* ring = (EventRingBuffer*)ctx->RingBuffer;
  57. ring->Cleanup();
  58. ExFreePoolWithTag(ring, 'RBCK');
  59. ctx->RingBuffer = nullptr;
  60. }
  61. ports_table_[i] = ports_table_[ports_count_ - 1];
  62. ports_count_--;
  63. break;
  64. }
  65. }
  66. KeReleaseSpinLock(&ports_lock_, old_irql);
  67. }
  68. PDEVICE_CONTEXT ClientConnection::FindPortContext(ULONG com_number) {
  69. PDEVICE_CONTEXT result = nullptr;
  70. KIRQL old_irql;
  71. KeAcquireSpinLock(&ports_lock_, &old_irql);
  72. for (ULONG i = 0; i < ports_count_; ++i) {
  73. if (ports_table_[i].ComNumber == com_number) {
  74. result = ports_table_[i].Context;
  75. break;
  76. }
  77. }
  78. KeReleaseSpinLock(&ports_lock_, old_irql);
  79. return result;
  80. }
  81. NTSTATUS ClientConnection::HandleRegisterCallback() {
  82. callback_registered_ = TRUE;
  83. return STATUS_SUCCESS;
  84. }
  85. NTSTATUS ClientConnection::HandleAttachPort(ULONG com_number) {
  86. PDEVICE_CONTEXT ctx = FindPortContext(com_number);
  87. if (!ctx) {
  88. return STATUS_DEVICE_DOES_NOT_EXIST;
  89. }
  90. // 如果未分配环形缓冲,先分配
  91. if (!ctx->RingBuffer) {
  92. EventRingBuffer* ring = (EventRingBuffer*)ExAllocatePool2(
  93. POOL_FLAG_NON_PAGED, sizeof(EventRingBuffer), 'RBCK');
  94. if (!ring) {
  95. return STATUS_INSUFFICIENT_RESOURCES;
  96. }
  97. // placement new 等价:手动调用构造
  98. RtlZeroMemory(ring, sizeof(EventRingBuffer));
  99. NTSTATUS status = ring->Initialize();
  100. if (!NT_SUCCESS(status)) {
  101. ring->Cleanup();
  102. ExFreePoolWithTag(ring, 'RBCK');
  103. return status;
  104. }
  105. ctx->RingBuffer = ring;
  106. }
  107. // 推入 OP_OPEN 事件(序列号由全局计数器递增)
  108. EventRingBuffer* ring = (EventRingBuffer*)ctx->RingBuffer;
  109. static LONG seq = 0;
  110. LONG cur = InterlockedIncrement(&seq);
  111. UINT64 timestamp = KeQueryInterruptTime(); // 100ns 单位
  112. ring->Push((ULONG)cur, timestamp, com_number, COMMKIT_OP_OPEN, 0, nullptr);
  113. ctx->MonitoringEnabled = TRUE;
  114. return STATUS_SUCCESS;
  115. }
  116. NTSTATUS ClientConnection::HandleDetachPort(ULONG com_number) {
  117. PDEVICE_CONTEXT ctx = FindPortContext(com_number);
  118. if (!ctx) {
  119. return STATUS_DEVICE_DOES_NOT_EXIST;
  120. }
  121. ctx->MonitoringEnabled = FALSE;
  122. // 推入 OP_CLOSE 事件
  123. if (ctx->RingBuffer) {
  124. EventRingBuffer* ring = (EventRingBuffer*)ctx->RingBuffer;
  125. static LONG seq2 = 0;
  126. LONG cur = InterlockedIncrement(&seq2);
  127. UINT64 timestamp = KeQueryInterruptTime();
  128. ring->Push((ULONG)cur, timestamp, com_number, COMMKIT_OP_CLOSE, 0, nullptr);
  129. }
  130. return STATUS_SUCCESS;
  131. }
  132. NTSTATUS ClientConnection::HandleWritePort(ULONG com_number, PVOID data, ULONG len) {
  133. UNREFERENCED_PARAMETER(data);
  134. UNREFERENCED_PARAMETER(len);
  135. // 简化实现:直接调用下层串口的 Write IRP
  136. // 完整实现需要查找端口上下文,构造 IRP 发送给下层设备
  137. PDEVICE_CONTEXT ctx = FindPortContext(com_number);
  138. if (!ctx) {
  139. return STATUS_DEVICE_DOES_NOT_EXIST;
  140. }
  141. // 注:完整的写数据流通过过滤驱动 IRP_MJ_WRITE 派遣完成
  142. // 这里仅返回成功;实际数据发送由用户态通过 CreateFile(COMx) 直接写入
  143. return STATUS_SUCCESS;
  144. }
  145. NTSTATUS ClientConnection::HandleReadPort(ULONG com_number, PVOID data, ULONG len) {
  146. UNREFERENCED_PARAMETER(data);
  147. UNREFERENCED_PARAMETER(len);
  148. PDEVICE_CONTEXT ctx = FindPortContext(com_number);
  149. if (!ctx) {
  150. return STATUS_DEVICE_DOES_NOT_EXIST;
  151. }
  152. return STATUS_SUCCESS;
  153. }
  154. NTSTATUS ClientConnection::HandleReadEvents(PVOID out_buf, ULONG out_size, PULONG returned) {
  155. *returned = 0;
  156. if (!callback_registered_) {
  157. return STATUS_DEVICE_NOT_READY;
  158. }
  159. PCOMMKIT_EVENT events = (PCOMMKIT_EVENT)out_buf;
  160. ULONG max_count = out_size / sizeof(COMMKIT_EVENT);
  161. if (max_count == 0) {
  162. return STATUS_BUFFER_TOO_SMALL;
  163. }
  164. ULONG total_popped = 0;
  165. KIRQL old_irql;
  166. KeAcquireSpinLock(&ports_lock_, &old_irql);
  167. for (ULONG i = 0; i < ports_count_ && total_popped < max_count; ++i) {
  168. PDEVICE_CONTEXT ctx = ports_table_[i].Context;
  169. if (!ctx || !ctx->RingBuffer || !ctx->MonitoringEnabled) {
  170. continue;
  171. }
  172. EventRingBuffer* ring = (EventRingBuffer*)ctx->RingBuffer;
  173. LONG popped = ring->PopBatch(events + total_popped, max_count - total_popped);
  174. total_popped += (ULONG)popped;
  175. }
  176. KeReleaseSpinLock(&ports_lock_, old_irql);
  177. *returned = total_popped * sizeof(COMMKIT_EVENT);
  178. return STATUS_SUCCESS;
  179. }
  180. NTSTATUS ClientConnection::HandleFreeAll() {
  181. KIRQL old_irql;
  182. KeAcquireSpinLock(&ports_lock_, &old_irql);
  183. for (ULONG i = 0; i < ports_count_; ++i) {
  184. PDEVICE_CONTEXT ctx = ports_table_[i].Context;
  185. if (ctx) {
  186. ctx->MonitoringEnabled = FALSE;
  187. if (ctx->RingBuffer) {
  188. ((EventRingBuffer*)ctx->RingBuffer)->Clear();
  189. }
  190. }
  191. }
  192. KeReleaseSpinLock(&ports_lock_, old_irql);
  193. callback_registered_ = FALSE;
  194. return STATUS_SUCCESS;
  195. }
  196. } // namespace commkit_driver