golang,调用WinVolumeInformation winapi函数 [英] golang, call GetVolumeInformation winapi function

查看:62
本文介绍了golang,调用WinVolumeInformation winapi函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试从golang调用GetVolumeInformation函数.要获取卷名.

Tries to call GetVolumeInformation function from golang. Want to get volume name.

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

...最后出现错误:(

... and finally have error :(

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

不理解,谷歌无法帮助调用winapi函数和返回字符串作为结果.

Don't understand and google cant'd help with calling winapi functions and returng string as result.

谢谢.

推荐答案

包装不安全

不安全包装中包含的操作会绕过以下类型的安全性:进入程序.

Package unsafe contains operations that step around the type safety of Go programs.

类型指针

type Pointer *ArbitraryType

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

Pointer represents a pointer to an arbitrary type. There are four special operations available for type Pointer that are not available for other types.

1)任何类型的指针值都可以转换为Pointer.

1) A pointer value of any type can be converted to a Pointer.

2)指针可以转换为任何类型的指针值.

2) A Pointer can be converted to a pointer value of any type.

3)可以将uintptr转换为Pointer.

3) A uintptr can be converted to a Pointer.

4)指针可以转换为uintptr.

4) A Pointer can be converted to a uintptr.

因此,指针允许程序破坏类型系统并读取并写入任意内存.使用时应格外小心.

Pointer therefore allows a program to defeat the type system and read and write arbitrary memory. It should be used with extreme care.

您没有注意 unsafe.Pointer 应格外小心使用"的警告.

You failed to heed the warning that unsafe.Pointer "should be used with extreme care."

尝试一下:

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

这篇关于golang,调用WinVolumeInformation winapi函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆