2015-11-18 9 views
2

В Windows официальный способ угадать, работает ли текущий 32-разрядный процесс в 32-разрядной или 64-разрядной архитектуре (например, WOW64 или нет), - это вызов IsWow64Process функция из kernel32.dll, и посмотреть, присутствует ли она (как я понимаю, документ).Определение, выполняется ли текущий процесс в WOW64 или нет.

В Go мы можем назвать функции, экспортируемые в DLL файлы с syscall пакета, так вот моя попытка:

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

К сожалению, тестирование с или без системы WOW64 показывает то же самое в стандартный вывод:

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

Что делать неправильно? Как достичь теста, чтобы определить, работает ли наша 32-разрядная программа Go на эмулированном 32-битном процессоре 64-разрядного процессора (WOW64) или на реальной 32-разрядной Windows?

+1

Вы полностью осведомлены о том, что ваш код в основном проверяет, работает ли ваш код Go на эмуляции WOW64 или нет, а не является ли ОС 32-разрядной дугой или нет? Чтобы ответить на вопрос *, как указано, * вы должны называть ['kernel32! GetNativeSystemInfo()'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724340) и проверять возвращаемую им архитектуру , Значение будет таким же, независимо от того, выполняете ли вы 32-битный процесс Go в 32-битном осевом или 64-битном процессе Go в 64-битной ОС или 32-битном процессе Go в 64-разрядной ОС. – kostix

+0

Спасибо за ваши комментарии и уточнения @kostix. Действительно, вы правы, я был предвзятым из-за того, что я предположил, что это 32-битный скомпилированный исполняемый файл Go. Должен ли я изменить свой вопрос, чтобы отразить то, что я хотел угадать, если мы запускаем WOW64 или нет, а затем снова задаем новый вопрос с функцией GetNativeSystemInfo в Go? [Похоже, что это метод stackoverflow для обработки такой ситуации] (http://meta.stackoverflow.com/q/283408/2583075). – Lomanic

+0

Вопрос отредактирован, чтобы отразить то, что было наконец спрошено и ответили, после комментария @kostix. – Lomanic

ответ

4

Я считаю, что проблема заключается в параметре дескриптора на вашем proc.Call. Ожидаемый параметр для IsWow64Process - это РУЧКА, которая не совпадает с pid. Вот почему это указывает на то, что дескриптор недействителен.

Следующий вопрос SO How to get process handle from process id указывает, что вам нужно позвонить OpenProcess, пропуская в pid, и он возвращает дескриптор.

EDIT: GetCurrentProcess определен в syscall. Так что я думаю, что вы можете заменить Getpid вызов со следующим:

handle, err := syscall.GetCurrentProcess() 
+0

Спасибо за ваш ответ. [Здесь] (https://play.golang.org/p/q6YOUS58pf) - мой код. К сожалению, у меня есть исключение во время выполнения ([link] (http://pastebin.aquilenet.fr/?11f1a1d75a631c63#xEoHdDHc6K56GtJOzlOAUrJ7qYpC6DjJI+Vv1DN94eg=)) во время его запуска, который я не могу диагностировать. Это происходит в строке proc.Call(). Похоже, что это не влияет на «результат» var? – Lomanic

2

ОК, так вот рабочий код:

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

result вар будет верно для системы WOW64 и ложным для 32-битная система.