golang,调用WinVolumeInformation winapi函数 [英] golang, call GetVolumeInformation winapi function
问题描述
尝试从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屋!