/// <summary> /// This is a generic wndproc. It is the callback for all hooked /// windows. If we get into this function, we look up the hwnd in the /// global list of all hooked windows to get its message map. If the /// message received is present in the message map, its callback is /// invoked with the parameters listed here. /// </summary> /// <param name="hwnd">The handle to the window that received the /// message</param> /// <param name="msg">The message</param> /// <param name="wParam">The message's parameters (part 1)</param> /// <param name="lParam">The messages's parameters (part 2)</param> /// <returns>If the callback handled the message, the callback's return /// value is returned form this function. If the callback didn't handle /// the message, the message is forwarded on to the previous wndproc. /// </returns> private static int WindowProc( IntPtr hwnd, uint msg, uint wParam, int lParam) { if (hwndDict.ContainsKey(hwnd)) { HookedProcInformation hpi = hwndDict[hwnd]; if (hpi.messageMap.ContainsKey(msg)) { WndProcCallback callback = hpi.messageMap[msg]; bool handled = false; int retval = callback(hwnd, msg, wParam, lParam, ref handled); if (handled) { return(retval); } } // if we didn't hook the message passed or we did, but the // callback didn't set the handled property to true, call // the original window procedure return(hpi.CallOldWindowProc(hwnd, msg, wParam, lParam)); } System.Diagnostics.Debug.Assert( false, "WindowProc called for hwnd we don't know about"); return(Win32.DefWindowProc(hwnd, msg, wParam, lParam)); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Initializes a new instance of the Oceanside.Win32.Native.HookedWindow class. </summary> /// /// <param name="handle"> The handle. </param> /// <param name="callback"> The callback. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// internal HookedWindow(IntPtr handle, WndProcCallback callback) { lock (_callbacksLocker) { RegisteredWndProcCallbacks.Add(callback); _isDeActivated = false; } WindowHandle = handle; //Get a native pointer to the delegate _delegateOfCustomWndProc = CustomWndProc; //Grab a pointer to the delegate that will be called when we sub-class W _hookedWndProcPtr = Marshal.GetFunctionPointerForDelegate(_delegateOfCustomWndProc); //I am not entirely sure if this call is absolutely necessary because _hookedWndProcPtr is // scoped to this class rather than local. The idea here is to prevent the GC from cleaning // up the Thunk that is returned by asking for a pointer to the delegate. Worst case // scenario (I believe) is that I am calling this line when it is not needed and since the call // only protects it from the point it is called until the first time it is used below, this // should be a non-issue. Yet I never like feeling absolutely certain about calling into // NativeCode. Don't worry as much as I do, but keep it in mind. GC.KeepAlive(_hookedWndProcPtr); //Install the hook. Note that SetWindowLongPtr is compatible with both 32-bit and 64-bit // calling code. _originalWndProc = SetWindowLongPtr(WindowHandle, WindowLongIndexFlags.GWL_WNDPROC, _hookedWndProcPtr); }
public static void HookWndProc(Control ctl, WndProcCallback callback, uint msg) { HookedProcInformation information = null; if (ctlDict.ContainsKey(ctl)) { information = ctlDict[ctl]; } else if (hwndDict.ContainsKey(ctl.Handle)) { information = hwndDict[ctl.Handle]; } if (information == null) { information = new HookedProcInformation(ctl, new Win32.WndProc(WndProcHooker.WindowProc)); ctl.HandleCreated += new EventHandler(WndProcHooker.ctl_HandleCreated); ctl.HandleDestroyed += new EventHandler(WndProcHooker.ctl_HandleDestroyed); ctl.Disposed += new EventHandler(WndProcHooker.ctl_Disposed); if (ctl.Handle != IntPtr.Zero) { information.SetHook(); } } if (ctl.Handle == IntPtr.Zero) { ctlDict[ctl] = information; } else { hwndDict[ctl.Handle] = information; } information.messageMap[msg] = callback; }
private IntPtr CreateMessageOnlyWindow() { wndClass = new WNDCLASSEX(); wndClass.cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)); callbackDelegate = WndProc; wndClass.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(callbackDelegate); wndClass.lpszClassName = "isclass"; wndClass.cbWndExtra = 0; wndClass.hIcon = IntPtr.Zero; wndClass.hCursor = IntPtr.Zero; wndClass.hIconSm = IntPtr.Zero; wndClass.hbrBackground = IntPtr.Zero; wndClass.hInstance = Process.GetCurrentProcess().Handle; wndClass.lpszMenuName = null; ushort ret = RegisterClassEx(ref wndClass); if (ret == 0) { ISLogger.Write("Failed to create window class: win32 error " + Marshal.GetLastWin32Error()); return(IntPtr.Zero); } IntPtr window = CreateWindowEx(0, wndClass.lpszClassName, "ismsg", 0, 0, 0, 0, 0, HWND_MESSAGE, IntPtr.Zero, Process.GetCurrentProcess().Handle, IntPtr.Zero); if (window == IntPtr.Zero) { ISLogger.Write("Failed to create message only window - " + Marshal.GetLastWin32Error()); return(IntPtr.Zero); } return(window); }
/// <summary> /// /// </summary> /// <param name="handle"></param> /// <param name="callback"></param> public static void UnSubclass(IntPtr handle, WndProcCallback callback) { MessageHook messageHook; if (Hooks.TryGetValue(handle, out messageHook)) { messageHook.RemoveHook(callback); } }
/// <summary> /// /// </summary> /// <param name="callback"></param> private void RemoveHook(WndProcCallback callback) { callbacks.Remove(callback); if (callbacks.Count == 0) { Release(); } }
/// <summary> /// /// </summary> /// <param name="callback"></param> private void AddHook(WndProcCallback callback) { if (callbacks.Count == 0) { Subclass(); } callbacks.Add(callback); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Removes the window procedure callback. </summary> /// /// <param name="windowHandle"> Handle of the window. </param> /// <param name="callback"> The callback. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// public static void RemoveWndProcCallback(IntPtr windowHandle, WndProcCallback callback) { if (ApplicationsHookedWindows.TryGetValue(windowHandle, out var hookedWindow)) { hookedWindow.DetachCallback(callback); if (hookedWindow.RegisteredWndProcCallbacks.Count == 0) { hookedWindow.ClearAllCallbacks(); } } }
/// <summary> /// Makes a connection between a specified window handle /// and the callback to be called when that message is received. /// </summary> private WindowHook(IntPtr handle, WndProcCallback callback) { Debug.Assert(handle != IntPtr.Zero, "Window handle cannot be null"); Debug.Assert(callback != null, "Callback method should be specified"); _handle = handle; _mainWndProc = WindowProc; _callback = callback; // Subclassing window _originalWndProc = User32.SetWindowLong(_handle, User32.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(_mainWndProc)); }
/// <summary> /// /// </summary> /// <param name="handle"></param> /// <param name="callback"></param> public static void Subclass(IntPtr handle, WndProcCallback callback) { MessageHook messageHook; if (Hooks.TryGetValue(handle, out messageHook)) { messageHook.AddHook(callback); } else { messageHook = new MessageHook(handle); Hooks[handle] = messageHook; messageHook.AddHook(callback); } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Adds a window procedure callback to 'callback'. </summary> /// /// <param name="windowHandle"> Handle of the window. </param> /// <param name="callback"> The callback. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// public static void AddWndProcCallback(IntPtr windowHandle, WndProcCallback callback) { //If we already have hooks associated with this windowHandle then just // add the callback if (ApplicationsHookedWindows.TryGetValue(windowHandle, out var hookedWindow)) { hookedWindow.AttachCallback(callback); hookedWindow.OnClosed += HookedWindow_OnDestroyed; } else { hookedWindow = new HookedWindow(windowHandle, callback); ApplicationsHookedWindows[windowHandle] = hookedWindow; } }
// Makes a connection between a message on a specified window handle // and the callback to be called when that message is received. If the // window was not previously hooked it is added to the global list of // all the window procedures hooked. // Parameters: // ctl - The control whose wndproc we are hooking. // callback - The method to call when the specified. // message is received for the specified window. // msg - The message being hooked. public static void HookWndProc( Control ctl, WndProcCallback callback, uint msg) { HookedProcInformation hpi = null; if (CtlDict.ContainsKey(ctl)) { hpi = CtlDict[ctl]; } else if (HwndDict.ContainsKey(ctl.Handle)) { hpi = HwndDict[ctl.Handle]; } if (hpi == null) { // If new control, create a new // HookedProcInformation for it. hpi = new HookedProcInformation( ctl, WindowProc); ctl.HandleCreated += ctl_HandleCreated; ctl.HandleDestroyed += ctl_HandleDestroyed; ctl.Disposed += ctl_Disposed; // If the handle has already been created set the hook. If it // hasn't been created yet, the hook will get set in the // ctl_HandleCreated event handler. if (ctl.Handle != IntPtr.Zero) { hpi.SetHook(); } } // Stick hpi into the correct dictionary. if (ctl.Handle == IntPtr.Zero) { CtlDict[ctl] = hpi; } else { HwndDict[ctl.Handle] = hpi; } // Add the message/callback into the message map. hpi.MessageMap[msg] = callback; }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Callback, called when the detach. </summary> /// /// <param name="callback"> The callback. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// internal void DetachCallback(WndProcCallback callback) { //Not throwing an exception if _isDeActivated is true if (_isDeActivated) { return; } lock (_callbacksLocker) { if (RegisteredWndProcCallbacks.Contains(callback)) { _ = RegisteredWndProcCallbacks.Remove(callback); _isDeActivated = !RegisteredWndProcCallbacks.Any(); return; } } }
/// <summary> /// Makes a connection between a message on a specified window handle /// and the callback to be called when that message is received. If the /// window was not previously hooked it is added to the global list of /// all the window procedures hooked. /// </summary> /// <param name="ctl">The control whose wndproc we are hooking</param> /// <param name="callback">The method to call when the specified /// message is received for the specified window</param> /// <param name="msg">The message we are hooking.</param> public static void HookWndProc( Control ctl, WndProcCallback callback, uint msg) { HookedProcInformation hpi = null; if (ctlDict.ContainsKey(ctl)) { hpi = ctlDict[ctl]; } else if (hwndDict.ContainsKey(ctl.Handle)) { hpi = hwndDict[ctl.Handle]; } if (hpi == null) { // We havne't seen this control before. Create a new // HookedProcInformation for it hpi = new HookedProcInformation(ctl, new Win32.WndProc(WndProcHooker.WindowProc)); ctl.HandleCreated += new EventHandler(ctl_HandleCreated); ctl.HandleDestroyed += new EventHandler(ctl_HandleDestroyed); ctl.Disposed += new EventHandler(ctl_Disposed); // If the handle has already been created set the hook. If it // hasn't been created yet, the hook will get set in the // ctl_HandleCreated event handler if (ctl.Handle != IntPtr.Zero) { hpi.SetHook(); } } // stick hpi into the correct dictionary if (ctl.Handle == IntPtr.Zero) { ctlDict[ctl] = hpi; } else { hwndDict[ctl.Handle] = hpi; } // add the message/callback into the message map hpi.messageMap[msg] = callback; }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Callback, called when the attach. </summary> /// /// <exception cref="InvalidOperationException"> Thrown when the requested operation is /// invalid. </exception> /// /// <param name="callback"> The callback. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// internal void AttachCallback(WndProcCallback callback) { if (_isDestroyed) { throw new InvalidOperationException($"{nameof(AttachCallback)} called on a hook where {nameof(_isDestroyed)} is true."); } lock (_callbacksLocker) { if (!RegisteredWndProcCallbacks.Contains(callback)) { RegisteredWndProcCallbacks.Add(callback); _isDeActivated = false; return; } } Debug.WriteLine( $"An attempt was made to add a duplicate {nameof(WndProcCallback)} to a Window with the handle = {WindowHandle}. Duplicate was skipped."); }
private static int WindowProc(IntPtr hwnd, uint msg, uint wParam, int lParam) { if (!hwndDict.ContainsKey(hwnd)) { return(Win32.DefWindowProc(hwnd, msg, wParam, lParam)); } HookedProcInformation information = hwndDict[hwnd]; if (information.messageMap.ContainsKey(msg)) { WndProcCallback callback = information.messageMap[msg]; bool handled = false; int num = callback(hwnd, msg, wParam, lParam, ref handled); if (handled) { return(num); } } return(information.CallOldWindowProc(hwnd, msg, wParam, lParam)); }
public void ProcessEvent(IWaveDevice waveDevice, int uMsg, WaveBuffer wbuf) { if (waveDevice == _waveInput) { switch (uMsg) { case WaveConstants.MM_WIM_OPEN: DumpDebugMessage("Wave Opened"); break; case WaveConstants.MM_WIM_DATA: { GCHandle gch = GCHandle.Alloc(wbuf); // Create message if (this.IsHandleCreated) { Message m = Message.Create(_CopyWindowHandle, WM_AUDIO_DONE, IntPtr.Zero, (IntPtr)gch); WndProcCallback wndCallback = new WndProcCallback(WndProc); // Ensure all calls will be thread-safe this.BeginInvoke(wndCallback, m); } } break; case WaveConstants.MM_WIM_CLOSE: DumpDebugMessage("Wave Closed"); break; } } }
public void SetWndProcCallback(WndProcCallback callback) { State.WndProcFunction = callback; }
public static extern IntPtr SetWindowsHookEx(int idHook, WndProcCallback lpfn, IntPtr hMod, uint dwThreadId);
/// <summary> /// Installs hook on the existing control. /// This operation should be done before creation of the window handle /// </summary> public static WindowHook Install(IntPtr handle, WndProcCallback callback) { return(new WindowHook(handle, callback)); }
// Makes a connection between a message on a specified window handle // and the callback to be called when that message is received. If the // window was not previously hooked it is added to the global list of // all the window procedures hooked. // Parameters: // ctl - The control whose wndproc we are hooking. // callback - The method to call when the specified. // message is received for the specified window. // msg - The message being hooked. public static void HookWndProc( Control ctl, WndProcCallback callback, uint msg) { HookedProcInformation hpi = null; if (ctlDict.ContainsKey(ctl)) hpi = ctlDict[ctl]; else if (hwndDict.ContainsKey(ctl.Handle)) hpi = hwndDict[ctl.Handle]; if (hpi == null) { // If new control, create a new // HookedProcInformation for it. hpi = new HookedProcInformation(ctl, new Win32.WndProc(WndProcHooker.WindowProc)); ctl.HandleCreated += new EventHandler(ctl_HandleCreated); ctl.HandleDestroyed += new EventHandler(ctl_HandleDestroyed); ctl.Disposed += new EventHandler(ctl_Disposed); // If the handle has already been created set the hook. If it // hasn't been created yet, the hook will get set in the // ctl_HandleCreated event handler. if (ctl.Handle != IntPtr.Zero) hpi.SetHook(); } // Stick hpi into the correct dictionary. if (ctl.Handle == IntPtr.Zero) ctlDict[ctl] = hpi; else hwndDict[ctl.Handle] = hpi; // Add the message/callback into the message map. hpi.messageMap[msg] = callback; }
/// <summary> /// Installs hook on the existing control. /// This operation should be done before creation of the window handle /// </summary> public static WindowHook Install(IntPtr handle, WndProcCallback callback) { return new WindowHook(handle, callback); }