windowsdllgo32bit-64bitwow64

Determining if current process runs in WOW64 or not in Go


With Windows, the official way of guessing if the current 32-bit process is running on a 32 or 64-bit architecture (so on WOW64 or not) is to call the IsWow64Process function from kernel32.dll, and see if it is present (as I understand the doc).

In Go we can call functions exported in dll files with the syscall package, so here is my attempt:

package main

import (
    "fmt"
    "os"
    "syscall"
)

func main() {
    dll, err := syscall.LoadDLL("kernel32.dll")
    if err != nil {
        fmt.Println(err)
    }
    defer dll.Release()
    proc, err := dll.FindProc("IsWow64Process")
    if err != nil {
        fmt.Println("Proc not found") // not a WOW64 so a 32 bit system?
        fmt.Println(err)
    }
    fmt.Printf("%v\n", proc)

    var handle uintptr = uintptr(os.Getpid())

    var result uintptr
    v, x, y := proc.Call(handle, result)

    fmt.Printf("%v %v %v\n", v, x, y)
    fmt.Printf("%v\n", result)
}

Unfortunately, testing with or without a WOW64 system displays the same in stdout:

&{0x10ada110 IsWow64Process 2088961457}
0 7 The handle is invalid.
0

What do I do wrong? How to achieve a test to determine if our 32-bit Go program runs on an emulated 32-bit on a 64-bit CPU (WOW64) or on a real 32-bit Windows?


Solution

  • I believe the issue is the handle parameter on your proc.Call. The expected parameter for IsWow64Process is a HANDLE which is not the same as a pid. Which is why it is indicating that the handle is invalid.

    The following SO question How to get process handle from process id indicates that you need to call OpenProcess passsing in the pid and it returns the handle.

    EDIT: GetCurrentProcess is defined in syscall. So I think you can replace the Getpid call with the following:

    handle, err := syscall.GetCurrentProcess()