Closed
[WIP] Fix serial port listening functionality bug#219
Conversation
Open
2 tasks
- Implement complete Rust replacement for closed-source Delphi DLL - Add support for both x86 and x64 architectures - Use retour crate for safe API hooking (ReadFile, WriteFile, CreateFileW) - Implement DLL injection using CreateRemoteThread - Add comprehensive documentation (README, MIGRATION guide) - Create build scripts and GitHub Actions workflow - Update C# code with detailed comments - Maintain 100% API compatibility with original DLL This resolves crashes in XCOM, LLCOM and other serial applications that previously failed with the x86-only closed-source implementation. Agent-Logs-Url: https://github.com/chenxuuu/llcom/sessions/eeef4b56-4f39-4cd4-88aa-0ec307817285 Co-authored-by: chenxuuu <10357394+chenxuuu@users.noreply.github.com>
Co-authored-by: chenxuuu <10357394+chenxuuu@users.noreply.github.com>
The `retour` crate requires nightly Rust features which caused CI build failures. Switched to `ilhook` which works on stable Rust and supports both x86 and x64. Changes: - Replace retour dependency with ilhook in Cargo.toml - Rewrite hooking implementation using ilhook API - Update documentation to reflect the change - Maintain all functionality and API compatibility This resolves the GitHub Actions build errors. Agent-Logs-Url: https://github.com/chenxuuu/llcom/sessions/ad2d08e7-9cd1-459b-9a97-bb933b621f21 Co-authored-by: chenxuuu <10357394+chenxuuu@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a Rust-based rewrite of serial_monitor.dll intended to replace the previous closed-source serial monitor implementation and add x64 support, along with build tooling, CI, and updated C# integration documentation.
Changes:
- Add a new Rust
cdylibproject (serial_monitor_rust/) implementing DLL injection + API hooking for serial monitoring. - Add build/CI infrastructure to produce x86 and x64 DLLs (
build.bat, GitHub Actions workflow). - Update llcom’s serial monitor page comments/error handling and add multiple documentation files describing the migration and implementation.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
serial_monitor_rust/src/lib.rs |
New Rust DLL implementation (injection, hooks, callback path). |
serial_monitor_rust/Cargo.toml |
Rust crate definition and dependencies (incl. windows, ilhook). |
serial_monitor_rust/Cargo.lock |
Locked dependency graph for the Rust crate. |
serial_monitor_rust/README.md |
Build/install/API documentation for the Rust DLL. |
serial_monitor_rust/MIGRATION.md |
Migration guide and testing checklist for replacing the old DLL. |
serial_monitor_rust/build.bat |
Windows build script for x86/x64 and copy into costura folders. |
serial_monitor_rust/.gitignore |
Ignore rules for Rust build artifacts and IDE files. |
SERIAL_MONITOR_REWRITE.md |
Repo-level overview of the rewrite and developer workflow. |
IMPLEMENTATION_SUMMARY.md |
Summary of the implementation and next steps/testing plan. |
llcom/Pages/SerialMonitorPage.xaml.cs |
Updated comments/error message around serial monitor plugin usage. |
.github/workflows/build-serial-monitor.yml |
CI job to build and publish x86/x64 DLL artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const STATE_SEND: u8 = 4; | ||
|
|
||
| /// Callback function type | ||
| type CallbackFn = unsafe extern "C" fn(*const Udata) -> i32; |
Comment on lines
+422
to
+427
| #[no_mangle] | ||
| pub unsafe extern "C" fn MonitorComm(pid: u32, com_index: u32, callback: CallbackFn) -> bool { | ||
| let mut state = MONITOR_STATE.lock(); | ||
|
|
||
| if state.is_monitoring { | ||
| return false; |
Comment on lines
+58
to
+61
| // Shared memory for inter-process communication | ||
| static SHARED_CALLBACK: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut()); | ||
| static SHARED_COM_PORT: Mutex<u32> = Mutex::new(0); | ||
|
|
Comment on lines
+192
to
+216
| /// Invoke the callback function with captured data | ||
| unsafe fn invoke_callback(state: u8, com_port: u32, handle: HANDLE, data: *const u8, size: usize) { | ||
| let callback_ptr = SHARED_CALLBACK.load(Ordering::SeqCst); | ||
| if callback_ptr.is_null() { | ||
| return; | ||
| } | ||
|
|
||
| let callback: CallbackFn = std::mem::transmute(callback_ptr); | ||
|
|
||
| let mut udata = Udata { | ||
| com_port: com_port as u8, | ||
| comm_state: state, | ||
| file_handle: handle.0 as i32, | ||
| data_size: size.min(8192) as i32, | ||
| data: [0u8; 8192], | ||
| }; | ||
|
|
||
| // Copy data | ||
| if !data.is_null() && size > 0 { | ||
| let copy_size = size.min(8192); | ||
| std::ptr::copy_nonoverlapping(data, udata.data.as_mut_ptr(), copy_size); | ||
| } | ||
|
|
||
| callback(&udata); | ||
| } |
Comment on lines
+310
to
+314
| // Get original function | ||
| let kernel32 = GetModuleHandleW(w!("kernel32.dll")).unwrap(); | ||
| let original: ReadFileFn = std::mem::transmute(GetProcAddress(kernel32, s!("ReadFile")).unwrap()); | ||
| ReadFile_Hook(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped, original) | ||
| } |
|
|
||
| The implementation uses: | ||
| - **Rust** for memory safety and modern tooling | ||
| - **retour** crate for safe API hooking |
Comment on lines
+55
to
+56
| copy serial_monitor_rust\target\i686-pc-windows-msvc\release\serial_monitor.dll llcom\costura32\serial_monitor.dll | ||
| copy serial_monitor_rust\target\x86_64-pc-windows-msvc\release\serial_monitor.dll llcom\costura64\serial_monitor.dll |
Comment on lines
+38
to
60
| /// <summary> | ||
| /// 回调函数委托,当监听到串口数据时被调用 | ||
| /// </summary> | ||
| public delegate int CallbackDelegate(IntPtr param); | ||
|
|
||
| /// <summary> | ||
| /// 停止监听串口通信 | ||
| /// 由serial_monitor.dll导出 (Rust实现) | ||
| /// </summary> | ||
| [DllImport("serial_monitor.dll")] | ||
| static extern bool UnMonitorComm(); | ||
|
|
||
| /// <summary> | ||
| /// 开始监听指定进程的串口通信 | ||
| /// 由serial_monitor.dll导出 (Rust实现) | ||
| /// </summary> | ||
| /// <param name="Pid">目标进程ID</param> | ||
| /// <param name="ComIndex">串口号 (例如: 1 表示 COM1)</param> | ||
| /// <param name="lpCallFunc">回调函数指针</param> | ||
| /// <returns>成功返回true,失败返回false</returns> | ||
| [DllImport("serial_monitor.dll")] | ||
| static extern bool MonitorComm(uint Pid, uint ComIndex, CallbackDelegate lpCallFunc); | ||
|
|
Comment on lines
+74
to
+76
| Stops monitoring and removes hooks. | ||
|
|
||
| **Returns:** `true` on success, `false` on failure |
Comment on lines
+392
to
+413
| /// DLL entry point | ||
| #[no_mangle] | ||
| #[allow(non_snake_case)] | ||
| unsafe extern "system" fn DllMain( | ||
| _hinst_dll: HINSTANCE, | ||
| fdw_reason: u32, | ||
| _lpv_reserved: *mut c_void, | ||
| ) -> BOOL { | ||
| match fdw_reason { | ||
| DLL_PROCESS_ATTACH => { | ||
| // When injected into target process, install hooks | ||
| if let Ok(()) = install_hooks() { | ||
| TRUE | ||
| } else { | ||
| FALSE | ||
| } | ||
| } | ||
| DLL_PROCESS_DETACH => { | ||
| // Clean up hooks | ||
| remove_hooks(); | ||
| TRUE | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.