为了账号安全,请及时绑定邮箱和手机立即绑定

golang,调用GetVolumeInformation winapi函数

golang,调用GetVolumeInformation winapi函数

Go
www说 2021-12-07 18:53:58
尝试从 golang 调用 GetVolumeInformation 函数。想要获取卷名。使用 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);使用代码:// testpackage mainimport (    "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 0xfffffffffffffffffatal error: fault[signal 0xc0000005 code=0x0 addr=0xffffffffffffffff pc=0x456b11]不明白,谷歌无法帮助调用 winapi 函数并返回字符串作为结果。
查看完整描述

2 回答

?
繁星淼淼

TA贡献1775条经验 获得超11个赞

包裹不安全

包 unsafe 包含绕过 Go 程序类型安全的操作。

类型指针

type Pointer *ArbitraryType

指针表示指向任意类型的指针。有四种特殊操作可用于类型 Pointer,其他类型不可用。

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

}


查看完整回答
反对 回复 2021-12-07
?
白衣非少年

TA贡献1155条经验 获得超0个赞

我不知道您遇到的确切问题,但我认为这可能是因为您没有使用https://github.com/golang/go/blob/master/src/syscall/syscall_windows.go 中与从内核产生的格式转换为 Go 需要的格式。查看 UTF16ToString 的其他调用者,例如在 env_windows.go 中,以了解它们是如何使用的。

查看完整回答
反对 回复 2021-12-07
  • 2 回答
  • 0 关注
  • 267 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信