Use CsWin32 for (most) native win32 bindings#41
Conversation
|
Working with the code generators has had an impact for my development experience for this, as I had to Also, the single remaining |
There was a problem hiding this comment.
Pull request overview
This PR replaces hand-rolled Win32 P/Invoke bindings (the Kernal32NativeMethods class and other scattered DllImport declarations) with CsWin32-generated bindings, as requested in issue #24. A new STROOP.Win32 project is introduced to host the CsWin32 source generator and provide wrapper methods for APIs that need additional marshalling logic.
Changes:
- Added a new
STROOP.Win32project with CsWin32 package,NativeMethods.txtdeclarations, and wrapper methods for complex APIs (ReadProcessMemory,WriteProcessMemory,QueryWorkingSetEx,GetSymbolAddress). - Removed
Kernal32NativeMethods.csandCarretlessTextBox.cs, migrating all consumers (WindowsProcessIO,DolphinProcessIO,SigScanSharp,ProcessHelper,RichTextBoxEx,MouseUtility) to use CsWin32-generated types and wrappers. - Added a manual
VirtualQueryExbinding (in a separate static class) due to a CsWin32 limitation with platform-dependent struct sizes.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
STROOP.Win32/STROOP.Win32.csproj |
New project hosting CsWin32 package |
STROOP.Win32/NativeMethods.txt |
CsWin32 API declarations |
STROOP.Win32/NativeMethods.json |
CsWin32 configuration (public visibility) |
STROOP.Win32/NativeMethodWrappers.cs |
Wrapper methods for complex P/Invoke calls |
STROOP.Win32/VirtualQueryEx.cs |
Manual VirtualQueryEx binding (CsWin32 can't generate it) |
STROOP.sln |
Added STROOP.Win32 project to solution |
STROOP.Core/STROOP.Core.csproj |
Added project reference to STROOP.Win32 |
STROOP.Core/ProcessHelper.cs |
New helper extracted from Kernal32NativeMethods |
STROOP.Core/Kernal32NativeMethods.cs |
Deleted old hand-rolled bindings |
STROOP.Core/GameMemoryAccess/WindowsProcessIO.cs |
Updated to use CsWin32 types and wrappers |
STROOP.Core/GameMemoryAccess/SigScanSharp.cs |
Updated to use NativeMethodWrappers |
STROOP.Core/GameMemoryAccess/DolphinProcessIO.cs |
Updated to use VirtualQueryEx wrapper |
STROOP/STROOP.csproj |
Removed CarretlessTextBox compile entry |
STROOP/Controls/CarretlessTextBox.cs |
Deleted (unused caret functionality) |
STROOP/Controls/VariablePanel/VariablePanelValueEditBox.cs |
Changed base class from CarretlessTextBox to TextBox |
STROOP/Controls/RichTextBoxEx.cs |
Updated to use CsWin32 types for rich edit |
STROOP/Utilities/MouseUtility.cs |
Updated to use CsWin32 for input/metrics |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| MaxNameLen = 2000, | ||
| SizeOfStruct = 88, | ||
| }; | ||
| var result = PInvoke.SymFromName(hProcess, "CORE_RDRAM", &symbol); |
There was a problem hiding this comment.
The name parameter is accepted but never used — "CORE_RDRAM" is hardcoded on line 67 instead of using the name argument. This makes the API misleading and will silently ignore any other symbol name passed by callers. The call to PInvoke.SymFromName should use name instead of "CORE_RDRAM".
| var result = PInvoke.SymFromName(hProcess, "CORE_RDRAM", &symbol); | |
| var result = PInvoke.SymFromName(hProcess, name, &symbol); |
| public static unsafe bool QueryWorkingSetEx(IntPtr hProcess, UIntPtr lpBaseAddress, out PSAPI_WORKING_SET_EX_INFORMATION wsInfo) | ||
| { | ||
| PSAPI_WORKING_SET_EX_INFORMATION tmp; | ||
| wsInfo.VirtualAddress = (HANDLE)lpBaseAddress; |
There was a problem hiding this comment.
VirtualAddress is set on wsInfo (line 53), but tmp is the variable actually passed to PInvoke.QueryWorkingSetEx (line 55). Then on line 56, wsInfo = tmp overwrites the VirtualAddress you set on line 53. The VirtualAddress should be set on tmp instead of wsInfo so that the API receives the correct input address.
| wsInfo.VirtualAddress = (HANDLE)lpBaseAddress; | |
| tmp.VirtualAddress = (HANDLE)lpBaseAddress; |
| public MemoryType Type; | ||
| } | ||
|
|
||
| [DllImport("kernel32.dll")] |
There was a problem hiding this comment.
The DllImport will attempt to find an export named Invoke in kernel32.dll (since no EntryPoint is specified, the marshaller uses the C# method name). This will fail at runtime with an EntryPointNotFoundException. You need to either rename the method to VirtualQueryEx or add EntryPoint = "VirtualQueryEx" to the DllImport attribute.
| [DllImport("kernel32.dll")] | |
| [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] |
931a0d6 to
f2ab57e
Compare
closes #24