public static Win32HardwareBreakpoint TrySet(SafeObjectHandle threadHandle, HardwareBreakpointType type, HardwareBreakpointSize size, IntPtr address) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || IntPtr.Size != 8) { throw new PlatformNotSupportedException("Only 64 bit Windows is supported"); } var breakpoint = new Win32HardwareBreakpoint { Address = address, Size = size, Type = type, ThreadHandle = threadHandle }; bool self = threadHandle.DangerousGetHandle() == Win32Thread.GetCurrentThread().DangerousGetHandle(); if (self) { int threadID = GetCurrentThreadId(); breakpoint.ThreadHandle = Win32Thread.OpenThread(ThreadAccess.All, inheritHandle: false, threadID: threadID); if (breakpoint.ThreadHandle.IsInvalid) { throw new Win32Exception(); } } breakpoint.CompletionEvent = Win32Event.CreateEvent(IntPtr.Zero, manualReset: false, initialState: false, name: null); breakpoint.Op = Operation.Set; Win32Thread.ThreadProc threadProc = Win32HardwareBreakpoint.th; var th = Marshal.GetFunctionPointerForDelegate(threadProc); var h = GCHandle.Alloc(breakpoint); if (Win32Thread.CreateThread(IntPtr.Zero, UIntPtr.Zero, th, parameter: (IntPtr)h, creationFlags: 0, out int _).IsInvalid) { throw new Win32Exception(); } WaitForSingleObject(breakpoint.CompletionEvent, dwMilliseconds: Constants.INFINITE); breakpoint.CompletionEvent.Dispose(); if (self) { breakpoint.ThreadHandle.Dispose(); } breakpoint.ThreadHandle = threadHandle; if (!breakpoint.SUCC) { h.Free(); return(null); } breakpoint.gcHandle = h; GC.KeepAlive(threadProc); return(breakpoint); }
static void Remove(GCHandle handle) { if (!handle.IsAllocated) { throw new ArgumentNullException(nameof(handle)); } var breakpoint = (Win32HardwareBreakpoint)handle.Target; bool isSelf = false; if (breakpoint.ThreadHandle.DangerousGetHandle() == Win32Thread.GetCurrentThread().DangerousGetHandle()) { int threadID = GetCurrentThreadId(); breakpoint.ThreadHandle = Win32Thread.OpenThread(ThreadAccess.All, inheritHandle: false, threadID); if (breakpoint.ThreadHandle.IsInvalid) { throw new Win32Exception(); } isSelf = true; } breakpoint.CompletionEvent = Win32Event.CreateEvent(IntPtr.Zero, manualReset: false, initialState: false, name: null); breakpoint.Op = Operation.Remove; Win32Thread.ThreadProc threadProc = Win32HardwareBreakpoint.th; var th = Marshal.GetFunctionPointerForDelegate(threadProc); if (Win32Thread.CreateThread(IntPtr.Zero, UIntPtr.Zero, th, (IntPtr)handle, 0, out int _).IsInvalid) { throw new Win32Exception(); } WaitForSingleObject(breakpoint.CompletionEvent, Constants.INFINITE); breakpoint.CompletionEvent.Dispose(); if (isSelf) { breakpoint.ThreadHandle.Dispose(); } handle.Free(); }