Reputation: 371
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
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
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
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