Lomanic
Lomanic

Reputation: 371

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?

Upvotes: 3

Views: 1405

Answers (3)

Erfan Azhdari
Erfan Azhdari

Reputation: 321

You can also use golang.org/x/sys/windows

package main

import (
    "fmt"
    "golang.org/x/sys/windows"
)

func main() {
    handle := windows.CurrentProcess()
    var isWow64 bool
    err := windows.IsWow64Process(handle, &isWow64)
    if err != nil {
        panic(err)
    }
    fmt.Println(isWow64)
}

Upvotes: 1

Lomanic
Lomanic

Reputation: 371

OK, so here is a working code:

package main

import (
    "syscall"
    "fmt"
    "unsafe"
)
func main() {
    dll, err := syscall.LoadDLL("kernel32.dll")
    if err != nil {
        fmt.Println("Can't load kernel32")
        fmt.Println(err)
    }
    defer dll.Release()
    proc, err := dll.FindProc("IsWow64Process")
    if err != nil {
        fmt.Println("Proc not found")
        fmt.Println(err)
    }
    fmt.Printf("%v\n",proc)

    handle, err := syscall.GetCurrentProcess()  
    if err != nil {
        fmt.Println("Handle not found")
        fmt.Println(err)
    }
    fmt.Printf("%v\n",handle)

    var result bool

    v, x, y := proc.Call(uintptr(handle), uintptr(unsafe.Pointer(&result)))

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

The result var will be true for a WOW64 system and false for a 32 bit system.

Upvotes: 3

miltonb
miltonb

Reputation: 7385

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()

Upvotes: 4

Related Questions