golang, вызов функции GetVolumeInformation winapi



Пытается вызвать функцию GetVolumeInformation из golang. Хотите получить имя Тома.



Используйте спецификации api:



BOOL WINAPI GetVolumeInformation(
_In_opt_ LPCTSTR lpRootPathName,
_Out_opt_ LPTSTR lpVolumeNameBuffer,
_In_ DWORD nVolumeNameSize,
_Out_opt_ LPDWORD lpVolumeSerialNumber,
_Out_opt_ LPDWORD lpMaximumComponentLength,
_Out_opt_ LPDWORD lpFileSystemFlags,
_Out_opt_ LPTSTR lpFileSystemNameBuffer,
_In_ DWORD nFileSystemNameSize
);


Используйте код:



// test
package main

import (
"fmt"
"syscall"
"unsafe"
)

func main() {
var lpRootPathName = "C:\"
var lpVolumeNameBuffer string
var nVolumeNameSize uint64
var lpVolumeSerialNumber uint64
var lpMaximumComponentLength uint64
var lpFileSystemFlags uint64
var lpFileSystemNameBuffer string
var nFileSystemNameSize uint32

kernel32, _ := syscall.LoadLibrary("kernel32.dll")
getVolume, _ := syscall.GetProcAddress(kernel32, "GetVolumeInformationW")

var nargs uintptr = 8
ret, _, callErr := syscall.Syscall9(uintptr(getVolume),
nargs,
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpRootPathName))),
uintptr(unsafe.Pointer(&lpVolumeNameBuffer)),
uintptr(unsafe.Pointer(&nVolumeNameSize)),
uintptr(unsafe.Pointer(&lpVolumeSerialNumber)),
uintptr(unsafe.Pointer(&lpMaximumComponentLength)),
uintptr(unsafe.Pointer(&lpFileSystemFlags)),
uintptr(unsafe.Pointer(&lpFileSystemNameBuffer)),
uintptr(unsafe.Pointer(&nFileSystemNameSize)),
0)
fmt.Println(ret, callErr, lpVolumeNameBuffer)
}


... и, наконец, есть ошибка : (



unexpected fault address 0xffffffffffffffff
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0xffffffffffffffff pc=0x456b11]


Не понимаю, и google не может помочь с вызовом функций winapi и возвращением строки в результате.



Спасибо.

707   2  

2 ответов:

Пакет небезопасный

Пакет unsafe содержит операции, которые обходят безопасность типа Идут программы.

Указатель Типа

type Pointer *ArbitraryType

Указатель представляет собой указатель на произвольный тип. Их четыре. специальные операции, доступные для указателя типа, которые недоступны для других типов.

1) значение указателя любого типа может быть преобразовано в указатель.

2) указатель может быть преобразован в значение указателя любого типа.

3) uintptr можно преобразовать в указатель.

4) указатель может быть преобразован в uintptr.

Указатель, таким образом, позволяет программе победить систему типов и прочитать и запишите произвольную память. Его следует использовать с особой осторожностью.

Вы не обратили внимания на предупреждение о том, что unsafe.Pointer "следует использовать с особой осторожностью."

Попробуйте вот что:

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func main() {
    var RootPathName = `C:\`
    var VolumeNameBuffer = make([]uint16, syscall.MAX_PATH+1)
    var nVolumeNameSize = uint32(len(VolumeNameBuffer))
    var VolumeSerialNumber uint32
    var MaximumComponentLength uint32
    var FileSystemFlags uint32
    var FileSystemNameBuffer = make([]uint16, 255)
    var nFileSystemNameSize uint32 = syscall.MAX_PATH + 1

    kernel32, _ := syscall.LoadLibrary("kernel32.dll")
    getVolume, _ := syscall.GetProcAddress(kernel32, "GetVolumeInformationW")

    var nargs uintptr = 8
    ret, _, callErr := syscall.Syscall9(uintptr(getVolume),
        nargs,
        uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(RootPathName))),
        uintptr(unsafe.Pointer(&VolumeNameBuffer[0])),
        uintptr(nVolumeNameSize),
        uintptr(unsafe.Pointer(&VolumeSerialNumber)),
        uintptr(unsafe.Pointer(&MaximumComponentLength)),
        uintptr(unsafe.Pointer(&FileSystemFlags)),
        uintptr(unsafe.Pointer(&FileSystemNameBuffer[0])),
        uintptr(nFileSystemNameSize),
        0)
    fmt.Println(ret, callErr, syscall.UTF16ToString(VolumeNameBuffer))
}

Я не знаю точной проблемы, которая у вас есть, но я думаю, что это вероятно, потому что вы не используете функции в https://github.com/golang/go/blob/master/src/syscall/syscall_windows.go связано с преобразованием из формата, который выходит из ядра, в то, что нужно Go. Посмотрите на других абонентов UTF16ToString, как в env_windows.идите, посмотрите, как они используются.

Comments

    Ничего не найдено.