Search code examples
gowinapihookwin32-processsetwindowlong

How can I manage windows of applications opened using Win32 API (Notepad, Word, Outlook, Chrome etc.)


How can we manage the wndproc function of the applications we run using the Win32 api? The software language I use is Go.

I tried more than one method but couldn't do it. Can you help?

I am learning the HANDLE (HWND) value of notepad application with Microsoft Spy ++

Then I watch the changes on Notepad ++ over SPY ++.

Just like with Spy ++, please help me manage the custom WNPROC function I wrote.

func main() {

    hwnd := w32.HWND(3736818)
    go SetWindowLongTest(w32.HWND(hwnd))
    time.Sleep(99999 * time.Second)
}


func SetWindowLongTest(hwnd w32.HWND) {
    result, err := win.SetWindowLongPtr(win.HWND(hwnd), win.GWL_WNDPROC, syscall.NewCallback(MyNewWndProc))
    if err != nil {
        fmt.Println("SetWindowLongPtr", err)
    }
    fmt.Println(result)
}



func MyNewWndProc(hwnd w32.HWND, uMsg uint, wParam w32.WPARAM, lParam w32.LPARAM) uintptr {
    fmt.Println(uMsg)
    fmt.Println("myNewWndProc", hwnd)
    return 0
}

  Result: 
    PS C:\Users\Cingozr\go\src> go run .\main.go
    SetWindowLongPtr Access is denied.
    0

Method 2:

func main() {

    hwnd := w32.HWND(3736818)
    go SetClassLongTest(w32.HWND(hwnd))
    time.Sleep(99999 * time.Second)
}

func SetClassLongTest(hwnd w32.HWND) {
    result, err := w32.SetClassLongPtrW(hwnd, -24, syscall.NewCallback(MyNewWndProc))
    if err != nil {
        fmt.Println("SetClassLongPtrW Err", err)
    }
    fmt.Println("SetClassLongPtrW", result)

}

func MyNewWndProc(hwnd w32.HWND, uMsg uint, wParam w32.WPARAM, lParam w32.LPARAM) uintptr {
    fmt.Println(uMsg)
    fmt.Println("myNewWndProc", hwnd)
    return 0
}

Result:
PS C:\Users\Cingozr\go\src> go run .\main.go
SetClassLongPtrW Err Access is denied.
SetClassLongPtrW 0

Solution

  • The answer is you cannot replace the window procedure cross-process with SetWindowLongPtr and SetClassLongPtr .

    Calling SetWindowLongPtr with the GWLP_WNDPROC index creates a subclass of the window class used to create the window. An application can subclass a system class, but should not subclass a window class created by another process.

    Calling SetClassLongPtr with the GCLP_WNDPROC index creates a subclass of the window class that affects all windows subsequently created with the class. An application can subclass a system class, but should not subclass a window class created by another process.

    In addition, the hwnd parameter of SetWindowLongPtr also has UIPI restrictions:

    The SetWindowLongPtr function fails if the process that owns the window specified by the hWnd parameter is at a higher process privilege in the UIPI hierarchy than the process the calling thread resides in.

    Windows XP/2000: The SetWindowLongPtr function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.

    It is recommended to use SetWindowsHookEx, if you want to monitor window messages. You could read this document: Using Hooks

    You could also create your own window, with the same WNDCLASSEX(GetClassLongPtr from the target window) and style(GetWindowLongPtr from the target window).

    Or you've already known what you are doing, try dll injection.