2019-03-07 11:39:54 +08:00
|
|
|
package win32api
|
|
|
|
|
|
|
|
|
|
import (
|
2026-06-06 17:46:02 +08:00
|
|
|
"fmt"
|
2019-03-07 11:39:54 +08:00
|
|
|
"syscall"
|
2019-03-11 14:54:38 +08:00
|
|
|
"unsafe"
|
2019-03-07 11:39:54 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func WTSGetActiveConsoleSessionId() (DWORD, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
WTGet, err := getProcAddr("kernel32.dll", "WTSGetActiveConsoleSessionId")
|
2019-03-07 11:39:54 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
res, _, _ := syscall.Syscall(WTGet, 0, 0, 0, 0)
|
|
|
|
|
return DWORD(res), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CloseHandle(hObject HANDLE) error {
|
|
|
|
|
CH, err := getProcAddr("kernel32.dll", "CloseHandle")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if r, _, errno := syscall.Syscall(CH, 1, uintptr(hObject), 0, 0); r == 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetLastError() DWORD {
|
|
|
|
|
last := syscall.GetLastError()
|
|
|
|
|
if last == nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
if errno, ok := last.(syscall.Errno); ok {
|
|
|
|
|
return DWORD(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetLastError(dwErrCode DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "SetLastError")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
syscall.Syscall(proc, 1, uintptr(dwErrCode), 0, 0)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func FormatMessage(dwMessageId DWORD) (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "FormatMessageW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf := make([]uint16, 2048)
|
|
|
|
|
flags := FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
|
|
|
|
|
r, _, errno := syscall.Syscall9(proc, 7,
|
|
|
|
|
uintptr(flags),
|
|
|
|
|
0,
|
|
|
|
|
uintptr(dwMessageId),
|
|
|
|
|
0,
|
|
|
|
|
uintptr(unsafe.Pointer(&buf[0])),
|
|
|
|
|
uintptr(len(buf)),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return syscall.UTF16ToString(buf[:r]), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CreateToolhelp32Snapshot(dwFlags, th32ProcessID DWORD) (HANDLE, error) {
|
|
|
|
|
CTS, err := getProcAddr("kernel32.dll", "CreateToolhelp32Snapshot")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(CTS, 2, uintptr(dwFlags), uintptr(th32ProcessID), 0)
|
|
|
|
|
if int(r) == -1 {
|
|
|
|
|
return HANDLE(r), error(errno)
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Process32First(hSnapshot HANDLE, lppe *PROCESSENTRY32) error {
|
|
|
|
|
PN, err := getProcAddr("kernel32.dll", "Process32First")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(PN, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lppe)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Process32Next(hSnapshot HANDLE, lppe *PROCESSENTRY32) error {
|
|
|
|
|
PN, err := getProcAddr("kernel32.dll", "Process32Next")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(PN, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lppe)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Thread32First(hSnapshot HANDLE, lpte *THREADENTRY32) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "Thread32First")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lpte)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Thread32Next(hSnapshot HANDLE, lpte *THREADENTRY32) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "Thread32Next")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lpte)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Module32First(hSnapshot HANDLE, lpme *MODULEENTRY32W) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "Module32FirstW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lpme)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Module32Next(hSnapshot HANDLE, lpme *MODULEENTRY32W) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "Module32NextW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lpme)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func OpenThread(dwDesiredAccess DWORD, bInheritHandle bool, dwThreadID DWORD) (HANDLE, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "OpenThread")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inherit := uintptr(0)
|
|
|
|
|
if bInheritHandle {
|
|
|
|
|
inherit = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 3, uintptr(dwDesiredAccess), inherit, uintptr(dwThreadID))
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SuspendThread(hThread HANDLE) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "SuspendThread")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(hThread), 0, 0)
|
|
|
|
|
result := DWORD(r)
|
|
|
|
|
if result == 0xFFFFFFFF {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return result, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return result, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ResumeThread(hThread HANDLE) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "ResumeThread")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(hThread), 0, 0)
|
|
|
|
|
result := DWORD(r)
|
|
|
|
|
if result == 0xFFFFFFFF {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return result, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return result, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetThreadContext(hThread HANDLE, lpContext unsafe.Pointer) error {
|
|
|
|
|
if lpContext == nil {
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetThreadContext")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hThread), uintptr(lpContext), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SetThreadContext(hThread HANDLE, lpContext unsafe.Pointer) error {
|
|
|
|
|
if lpContext == nil {
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "SetThreadContext")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hThread), uintptr(lpContext), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DebugActiveProcess(dwProcessId DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "DebugActiveProcess")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(dwProcessId), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DebugActiveProcessStop(dwProcessId DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "DebugActiveProcessStop")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(dwProcessId), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func WaitForDebugEvent(lpDebugEvent unsafe.Pointer, dwMilliseconds DWORD) error {
|
|
|
|
|
if lpDebugEvent == nil {
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "WaitForDebugEvent")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(lpDebugEvent), uintptr(dwMilliseconds), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ContinueDebugEvent(dwProcessId, dwThreadId, dwContinueStatus DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "ContinueDebugEvent")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 3, uintptr(dwProcessId), uintptr(dwThreadId), uintptr(dwContinueStatus))
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DebugEventCodeName(code DWORD) string {
|
|
|
|
|
switch code {
|
|
|
|
|
case EXCEPTION_DEBUG_EVENT:
|
|
|
|
|
return "EXCEPTION_DEBUG_EVENT"
|
|
|
|
|
case CREATE_THREAD_DEBUG_EVENT:
|
|
|
|
|
return "CREATE_THREAD_DEBUG_EVENT"
|
|
|
|
|
case CREATE_PROCESS_DEBUG_EVENT:
|
|
|
|
|
return "CREATE_PROCESS_DEBUG_EVENT"
|
|
|
|
|
case EXIT_THREAD_DEBUG_EVENT:
|
|
|
|
|
return "EXIT_THREAD_DEBUG_EVENT"
|
|
|
|
|
case EXIT_PROCESS_DEBUG_EVENT:
|
|
|
|
|
return "EXIT_PROCESS_DEBUG_EVENT"
|
|
|
|
|
case LOAD_DLL_DEBUG_EVENT:
|
|
|
|
|
return "LOAD_DLL_DEBUG_EVENT"
|
|
|
|
|
case UNLOAD_DLL_DEBUG_EVENT:
|
|
|
|
|
return "UNLOAD_DLL_DEBUG_EVENT"
|
|
|
|
|
case OUTPUT_DEBUG_STRING_EVENT:
|
|
|
|
|
return "OUTPUT_DEBUG_STRING_EVENT"
|
|
|
|
|
case RIP_EVENT:
|
|
|
|
|
return "RIP_EVENT"
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Sprintf("UNKNOWN_DEBUG_EVENT(%d)", code)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DecodeDebugEvent(raw []byte) (DebugEventInfo, error) {
|
|
|
|
|
if len(raw) < int(unsafe.Sizeof(DEBUG_EVENT_HEADER{})) {
|
|
|
|
|
return DebugEventInfo{}, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
header := *(*DEBUG_EVENT_HEADER)(unsafe.Pointer(&raw[0]))
|
|
|
|
|
return DebugEventInfo{
|
|
|
|
|
Header: header,
|
|
|
|
|
CodeName: DebugEventCodeName(header.DwDebugEventCode),
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func WaitForDebugEventInfo(raw []byte, dwMilliseconds DWORD) (DebugEventInfo, error) {
|
|
|
|
|
if len(raw) == 0 {
|
|
|
|
|
return DebugEventInfo{}, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
if err := WaitForDebugEvent(unsafe.Pointer(&raw[0]), dwMilliseconds); err != nil {
|
|
|
|
|
return DebugEventInfo{}, err
|
|
|
|
|
}
|
|
|
|
|
return DecodeDebugEvent(raw)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CreateRemoteThread(hProcess HANDLE, lpThreadAttributes *syscall.SecurityAttributes, dwStackSize uintptr, lpStartAddress uintptr, lpParameter uintptr, dwCreationFlags DWORD, lpThreadID *DWORD) (HANDLE, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "CreateRemoteThread")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall9(
|
|
|
|
|
proc,
|
|
|
|
|
7,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
uintptr(unsafe.Pointer(lpThreadAttributes)),
|
|
|
|
|
dwStackSize,
|
|
|
|
|
lpStartAddress,
|
|
|
|
|
lpParameter,
|
|
|
|
|
uintptr(dwCreationFlags),
|
|
|
|
|
uintptr(unsafe.Pointer(lpThreadID)),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetProcessId(Process HANDLE) uint32 {
|
|
|
|
|
GPI, err := getProcAddr("kernel32.dll", "GetProcessId")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0
|
2019-03-07 11:39:54 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, _ := syscall.Syscall(GPI, 1, uintptr(Process), 0, 0)
|
|
|
|
|
return uint32(r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ProcessIdToSessionId(dwProcessId DWORD) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "ProcessIdToSessionId")
|
2019-03-07 11:39:54 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
var sessionID DWORD
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(dwProcessId), uintptr(unsafe.Pointer(&sessionID)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return sessionID, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ReadProcessMemory(hProcess HANDLE, lpBaseAddress uintptr, lpBuffer []byte, lpNumberOfBytesRead *uintptr) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "ReadProcessMemory")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bufferPtr uintptr
|
|
|
|
|
if len(lpBuffer) > 0 {
|
|
|
|
|
bufferPtr = uintptr(unsafe.Pointer(&lpBuffer[0]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
5,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpBaseAddress,
|
|
|
|
|
bufferPtr,
|
|
|
|
|
uintptr(len(lpBuffer)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpNumberOfBytesRead)),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func WriteProcessMemory(hProcess HANDLE, lpBaseAddress uintptr, lpBuffer []byte, lpNumberOfBytesWritten *uintptr) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "WriteProcessMemory")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bufferPtr uintptr
|
|
|
|
|
if len(lpBuffer) > 0 {
|
|
|
|
|
bufferPtr = uintptr(unsafe.Pointer(&lpBuffer[0]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
5,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpBaseAddress,
|
|
|
|
|
bufferPtr,
|
|
|
|
|
uintptr(len(lpBuffer)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpNumberOfBytesWritten)),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func VirtualQueryEx(hProcess HANDLE, lpAddress uintptr, lpBuffer *MEMORY_BASIC_INFORMATION, dwLength uintptr) (uintptr, error) {
|
|
|
|
|
if lpBuffer == nil {
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "VirtualQueryEx")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
4,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpAddress,
|
|
|
|
|
uintptr(unsafe.Pointer(lpBuffer)),
|
|
|
|
|
dwLength,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return r, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func VirtualProtectEx(hProcess HANDLE, lpAddress uintptr, dwSize uintptr, flNewProtect DWORD, lpflOldProtect *DWORD) error {
|
|
|
|
|
if lpflOldProtect == nil {
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "VirtualProtectEx")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
5,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpAddress,
|
|
|
|
|
dwSize,
|
|
|
|
|
uintptr(flNewProtect),
|
|
|
|
|
uintptr(unsafe.Pointer(lpflOldProtect)),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func VirtualAllocEx(hProcess HANDLE, lpAddress uintptr, dwSize uintptr, flAllocationType, flProtect DWORD) (uintptr, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "VirtualAllocEx")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
5,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpAddress,
|
|
|
|
|
dwSize,
|
|
|
|
|
uintptr(flAllocationType),
|
|
|
|
|
uintptr(flProtect),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return r, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func VirtualFreeEx(hProcess HANDLE, lpAddress uintptr, dwSize uintptr, dwFreeType DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "VirtualFreeEx")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(
|
|
|
|
|
proc,
|
|
|
|
|
4,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
lpAddress,
|
|
|
|
|
dwSize,
|
|
|
|
|
uintptr(dwFreeType),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func OpenProcess(dwDesiredAccess DWORD, bInheritHandle bool, dwProcessId DWORD) (HANDLE, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "OpenProcess")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
inherit := uintptr(0)
|
|
|
|
|
if bInheritHandle {
|
|
|
|
|
inherit = 1
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 3, uintptr(dwDesiredAccess), inherit, uintptr(dwProcessId))
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
2019-03-07 11:39:54 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
return HANDLE(r), nil
|
2019-03-07 11:39:54 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func TerminateProcess(hProcess HANDLE, uExitCode DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "TerminateProcess")
|
2019-03-07 11:39:54 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return err
|
2019-03-07 11:39:54 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hProcess), uintptr(uExitCode), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2019-03-07 11:39:54 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2019-03-11 14:54:38 +08:00
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func CreateProcess(lpApplicationName, lpCommandLine string,
|
|
|
|
|
lpProcessAttributes, lpThreadAttributes *syscall.SecurityAttributes, bInheritHandles bool,
|
|
|
|
|
dwCreationFlags DWORD, lpEnvironment HANDLE, lpCurrentDirectory string,
|
|
|
|
|
lpStartupInfo *StartupInfo, lpProcessInformation *ProcessInformation) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "CreateProcessW")
|
2019-03-11 14:54:38 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return err
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
var applicationName uintptr
|
|
|
|
|
if len(lpApplicationName) > 0 {
|
|
|
|
|
applicationName = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpApplicationName)))
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
var commandLine uintptr
|
|
|
|
|
if len(lpCommandLine) > 0 {
|
|
|
|
|
commandLine = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCommandLine)))
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
var currentDirectory uintptr
|
|
|
|
|
if len(lpCurrentDirectory) > 0 {
|
|
|
|
|
currentDirectory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCurrentDirectory)))
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
inheritHandles := uintptr(0)
|
|
|
|
|
if bInheritHandles {
|
|
|
|
|
inheritHandles = 1
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
r, _, errno := syscall.Syscall12(proc, 10,
|
|
|
|
|
applicationName,
|
|
|
|
|
commandLine,
|
|
|
|
|
uintptr(unsafe.Pointer(lpProcessAttributes)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpThreadAttributes)),
|
|
|
|
|
inheritHandles,
|
|
|
|
|
uintptr(dwCreationFlags),
|
|
|
|
|
uintptr(lpEnvironment),
|
|
|
|
|
currentDirectory,
|
|
|
|
|
uintptr(unsafe.Pointer(lpStartupInfo)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpProcessInformation)),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
2021-09-01 11:03:37 +08:00
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func WaitForSingleObject(hHandle HANDLE, dwMilliseconds DWORD) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "WaitForSingleObject")
|
2019-03-11 14:54:38 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hHandle), uintptr(dwMilliseconds), 0)
|
|
|
|
|
result := DWORD(r)
|
|
|
|
|
if result == WAIT_FAILED {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return result, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return result, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func WaitForMultipleObjects(handles []HANDLE, bWaitAll bool, dwMilliseconds DWORD) (DWORD, error) {
|
|
|
|
|
if len(handles) == 0 {
|
|
|
|
|
return WAIT_FAILED, fmt.Errorf("handles must not be empty")
|
|
|
|
|
}
|
|
|
|
|
if len(handles) > int(MAXIMUM_WAIT_OBJECTS) {
|
|
|
|
|
return WAIT_FAILED, fmt.Errorf("too many handles: %d > %d", len(handles), MAXIMUM_WAIT_OBJECTS)
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "WaitForMultipleObjects")
|
2019-03-11 14:54:38 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return 0, err
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
waitAll := uintptr(0)
|
|
|
|
|
if bWaitAll {
|
|
|
|
|
waitAll = 1
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(proc, 4,
|
|
|
|
|
uintptr(len(handles)),
|
|
|
|
|
uintptr(unsafe.Pointer(&handles[0])),
|
|
|
|
|
waitAll,
|
|
|
|
|
uintptr(dwMilliseconds),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
result := DWORD(r)
|
|
|
|
|
if result == WAIT_FAILED {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return result, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return result, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return result, nil
|
2019-03-11 14:54:38 +08:00
|
|
|
}
|
2020-10-19 21:14:49 +08:00
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func GetExitCodeProcess(hProcess HANDLE) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetExitCodeProcess")
|
2020-10-19 21:14:49 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
var code DWORD
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(hProcess), uintptr(unsafe.Pointer(&code)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return code, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetTickCount() (uint32, error) {
|
|
|
|
|
GTC, err := getProcAddr("kernel32.dll", "GetTickCount")
|
2020-10-19 21:14:49 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, _ := syscall.Syscall(GTC, 0, 0, 0, 0)
|
2020-10-19 21:14:49 +08:00
|
|
|
return uint32(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GlobalMemoryStatusEx(data *MEMORYSTATUSEX) (bool, error) {
|
|
|
|
|
(*data).DwLength = DWORD(unsafe.Sizeof(*data))
|
2026-06-06 17:46:02 +08:00
|
|
|
GMS, err := getProcAddr("kernel32.dll", "GlobalMemoryStatusEx")
|
2020-10-19 21:14:49 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(GMS, 1, uintptr(unsafe.Pointer(data)), 0, 0)
|
2020-10-19 21:14:49 +08:00
|
|
|
if r == 0 {
|
2021-09-01 11:03:37 +08:00
|
|
|
if errno != 0 {
|
|
|
|
|
return false, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return false, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func LockFileEx(hFile HANDLE, dwFlags DWORD, dwReserved DWORD, nNumberOfBytesToLockLow DWORD,
|
|
|
|
|
nNumberOfBytesToLockHigh DWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
Lck, err := getProcAddr("kernel32.dll", "LockFileEx")
|
2021-09-01 11:03:37 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall6(Lck, 6, uintptr(hFile), uintptr(dwFlags), uintptr(dwReserved),
|
2021-09-01 11:03:37 +08:00
|
|
|
uintptr(nNumberOfBytesToLockLow), uintptr(nNumberOfBytesToLockHigh), uintptr(unsafe.Pointer(lpOverlapped)))
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return false, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return false, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-15 17:25:42 +08:00
|
|
|
func OpenFileById(hVolumeHint HANDLE, lpFileId *FILE_ID_DESCRIPTOR, dwDesiredAccess DWORD, dwShareMode DWORD,
|
|
|
|
|
lpSecurityAttributes *syscall.SecurityAttributes, dwFlagsAndAttributes DWORD) (HANDLE, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
ofb, err := getProcAddr("kernel32.dll", "OpenFileById")
|
2021-11-15 17:25:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(ofb, 6, uintptr(hVolumeHint),
|
|
|
|
|
uintptr(unsafe.Pointer(lpFileId)), uintptr(dwDesiredAccess), uintptr(dwShareMode),
|
|
|
|
|
uintptr(unsafe.Pointer(lpSecurityAttributes)), uintptr(dwFlagsAndAttributes))
|
2026-06-06 17:46:02 +08:00
|
|
|
if HANDLE(r) == HANDLE(syscall.InvalidHandle) {
|
2021-11-15 17:25:42 +08:00
|
|
|
if errno != 0 {
|
|
|
|
|
return HANDLE(r), error(errno)
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-01 11:03:37 +08:00
|
|
|
func CreateEventW(lpEventAttributes *syscall.SecurityAttributes, bManualReset bool,
|
|
|
|
|
bInitialState bool, lpName LPCWSTR) (HANDLE, error) {
|
|
|
|
|
var intBManualReset, intBInitialState int
|
|
|
|
|
if bManualReset {
|
|
|
|
|
intBManualReset = 1
|
|
|
|
|
}
|
|
|
|
|
if bInitialState {
|
|
|
|
|
intBInitialState = 1
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
Lck, err := getProcAddr("kernel32.dll", "CreateEventW")
|
2021-09-01 11:03:37 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall6(Lck, 4, uintptr(unsafe.Pointer(lpEventAttributes)),
|
2021-09-01 11:03:37 +08:00
|
|
|
uintptr(intBManualReset), uintptr(intBInitialState), uintptr(unsafe.Pointer(lpName)), 0, 0)
|
|
|
|
|
if HANDLE(r) == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return HANDLE(r), error(errno)
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return HANDLE(r), nil
|
2020-10-19 21:14:49 +08:00
|
|
|
}
|
2021-11-15 17:25:42 +08:00
|
|
|
|
|
|
|
|
func GetLogicalDriveStringsW(nBufferLength DWORD, lpBuffer LPWSTR) error {
|
2026-06-06 17:46:02 +08:00
|
|
|
glds, err := getProcAddr("kernel32.dll", "GetLogicalDriveStringsW")
|
2021-11-15 17:25:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(glds, 2, uintptr(nBufferLength), uintptr(unsafe.Pointer(lpBuffer)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2021-11-15 17:25:42 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetVolumeInformationW(lpRootPathName LPCWSTR, lpVolumeNameBuffer LPWSTR, nVolumeNameSize DWORD,
|
|
|
|
|
lpVolumeSerialNumber LPDWORD, lpMaximumComponentLength LPDWORD, lpFileSystemFlags LPDWORD,
|
|
|
|
|
lpFileSystemNameBuffer LPWSTR, nFileSystemNameSize DWORD) error {
|
2026-06-06 17:46:02 +08:00
|
|
|
glds, err := getProcAddr("kernel32.dll", "GetVolumeInformationW")
|
2021-11-15 17:25:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall9(glds, 8, uintptr(unsafe.Pointer(lpRootPathName)),
|
2021-11-15 17:25:42 +08:00
|
|
|
uintptr(unsafe.Pointer(lpVolumeNameBuffer)), uintptr(nVolumeNameSize), uintptr(unsafe.Pointer(lpVolumeSerialNumber)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpMaximumComponentLength)), uintptr(unsafe.Pointer(lpFileSystemFlags)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpFileSystemNameBuffer)), uintptr(nFileSystemNameSize), 0)
|
2026-06-06 17:46:02 +08:00
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2021-11-15 17:25:42 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DeviceIoControl(hDevice HANDLE, dwIoControlCode DWORD, lpInBuffer LPVOID, nInBufferSize DWORD, lpOutBuffer LPVOID,
|
|
|
|
|
nOutBufferSize DWORD, lpBytesReturned LPDWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
dic, err := getProcAddr("kernel32.dll", "DeviceIoControl")
|
2021-11-15 17:25:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall9(dic, 8, uintptr(hDevice), uintptr(dwIoControlCode),
|
2021-11-15 17:25:42 +08:00
|
|
|
uintptr(unsafe.Pointer(lpInBuffer)), uintptr(nInBufferSize), uintptr(unsafe.Pointer(lpOutBuffer)), uintptr(nOutBufferSize),
|
|
|
|
|
uintptr(unsafe.Pointer(lpBytesReturned)), uintptr(unsafe.Pointer(lpOverlapped)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return false, error(errno)
|
|
|
|
|
} else {
|
|
|
|
|
return false, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DeviceIoControlPtr(hDevice HANDLE, dwIoControlCode DWORD, lpInBuffer uintptr, nInBufferSize DWORD, lpOutBuffer uintptr,
|
|
|
|
|
nOutBufferSize DWORD, lpBytesReturned LPDWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
dic, err := getProcAddr("kernel32.dll", "DeviceIoControl")
|
2021-11-15 17:25:42 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return false, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall9(dic, 8, uintptr(hDevice), uintptr(dwIoControlCode),
|
2021-11-15 17:25:42 +08:00
|
|
|
lpInBuffer, uintptr(nInBufferSize), lpOutBuffer, uintptr(nOutBufferSize),
|
|
|
|
|
uintptr(unsafe.Pointer(lpBytesReturned)), uintptr(unsafe.Pointer(lpOverlapped)), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return false, error(errno)
|
|
|
|
|
} else {
|
|
|
|
|
return false, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
2024-03-26 11:10:26 +08:00
|
|
|
|
|
|
|
|
func GlobalLock(hMem HGLOBAL) (unsafe.Pointer, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
gl, err := getProcAddr("kernel32.dll", "GlobalLock")
|
2024-03-26 11:10:26 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(gl, 1, uintptr(hMem), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return nil, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return nil, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return unsafe.Pointer(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GlobalUnlock(hMem HGLOBAL) error {
|
2026-06-06 17:46:02 +08:00
|
|
|
gu, err := getProcAddr("kernel32.dll", "GlobalUnlock")
|
2024-03-26 11:10:26 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
if err := SetLastError(0); err != nil {
|
2024-03-26 11:10:26 +08:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(gu, 1, uintptr(hMem), 0, 0)
|
|
|
|
|
if r == 0 {
|
2026-06-06 17:46:02 +08:00
|
|
|
if errno == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2024-03-26 11:10:26 +08:00
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GlobalSize(hMem HGLOBAL) (DWORD, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
gs, err := getProcAddr("kernel32.dll", "GlobalSize")
|
2024-03-26 11:10:26 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(gs, 1, uintptr(hMem), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return DWORD(r), nil
|
|
|
|
|
}
|
2024-03-30 15:06:00 +08:00
|
|
|
|
|
|
|
|
func GlobalAlloc(uFlags DWORD, dwBytes uintptr) (HGLOBAL, error) {
|
2026-06-06 17:46:02 +08:00
|
|
|
ga, err := getProcAddr("kernel32.dll", "GlobalAlloc")
|
2024-03-30 15:06:00 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(ga, 2, uintptr(uFlags), dwBytes, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return 0, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return 0, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return HGLOBAL(r), nil
|
|
|
|
|
}
|
2024-04-02 10:16:13 +08:00
|
|
|
|
|
|
|
|
func GlobalFree(hMem HGLOBAL) error {
|
2026-06-06 17:46:02 +08:00
|
|
|
gf, err := getProcAddr("kernel32.dll", "GlobalFree")
|
2024-04-02 10:16:13 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(gf, 1, uintptr(hMem), 0, 0)
|
|
|
|
|
if r != 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func RtlMoveMemory(Destination, Source unsafe.Pointer, Length uintptr) error {
|
|
|
|
|
rmv, err := getProcAddr("kernel32.dll", "RtlMoveMemory")
|
2024-04-02 10:16:13 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
syscall.Syscall(rmv, 3, uintptr(unsafe.Pointer(Destination)), uintptr(unsafe.Pointer(Source)), Length)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetModuleHandle(lpModuleName *uint16) (HINSTANCE, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetModuleHandleW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, err := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(lpModuleName)), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return HINSTANCE(r), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetCurrentProcessId() DWORD {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetCurrentProcessId")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
r, _, _ := syscall.Syscall(proc, 0, 0, 0, 0)
|
|
|
|
|
return DWORD(r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetCurrentThreadId() DWORD {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetCurrentThreadId")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
r, _, _ := syscall.Syscall(proc, 0, 0, 0, 0)
|
|
|
|
|
return DWORD(r)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetComputerName() (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetComputerNameW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(64)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
n := uint32(len(buf))
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0)
|
|
|
|
|
if r != 0 {
|
|
|
|
|
return syscall.UTF16ToString(buf), nil
|
|
|
|
|
}
|
|
|
|
|
if errno == syscall.ERROR_MORE_DATA || errno == syscall.ERROR_INSUFFICIENT_BUFFER {
|
|
|
|
|
if n > size {
|
|
|
|
|
size = n
|
|
|
|
|
} else {
|
|
|
|
|
size *= 2
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetTempPath() (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetTempPathW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(syscall.MAX_PATH + 1)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(size), uintptr(unsafe.Pointer(&buf[0])), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
needed := uint32(r)
|
|
|
|
|
if needed < size {
|
|
|
|
|
return syscall.UTF16ToString(buf[:needed]), nil
|
|
|
|
|
}
|
|
|
|
|
size = needed + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetSystemDirectory() (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetSystemDirectoryW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(syscall.MAX_PATH + 1)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
needed := uint32(r)
|
|
|
|
|
if needed < size {
|
|
|
|
|
return syscall.UTF16ToString(buf[:needed]), nil
|
|
|
|
|
}
|
|
|
|
|
size = needed + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetWindowsDirectory() (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetWindowsDirectoryW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(syscall.MAX_PATH + 1)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
needed := uint32(r)
|
|
|
|
|
if needed < size {
|
|
|
|
|
return syscall.UTF16ToString(buf[:needed]), nil
|
|
|
|
|
}
|
|
|
|
|
size = needed + 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func QueryFullProcessImageName(hProcess HANDLE, dwFlags DWORD) (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "QueryFullProcessImageNameW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(syscall.MAX_PATH + 1)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
n := size
|
|
|
|
|
r, _, errno := syscall.Syscall6(proc, 4,
|
|
|
|
|
uintptr(hProcess),
|
|
|
|
|
uintptr(dwFlags),
|
|
|
|
|
uintptr(unsafe.Pointer(&buf[0])),
|
|
|
|
|
uintptr(unsafe.Pointer(&n)),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r != 0 {
|
|
|
|
|
return syscall.UTF16ToString(buf[:n]), nil
|
|
|
|
|
}
|
|
|
|
|
if errno == syscall.ERROR_INSUFFICIENT_BUFFER {
|
|
|
|
|
size *= 2
|
|
|
|
|
if size > 32768 {
|
|
|
|
|
return "", fmt.Errorf("query full process image name buffer overflow")
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CreateFile(lpFileName string, dwDesiredAccess, dwShareMode DWORD,
|
|
|
|
|
lpSecurityAttributes *syscall.SecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes DWORD,
|
|
|
|
|
hTemplateFile HANDLE) (HANDLE, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "CreateFileW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall9(proc, 7,
|
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFileName))),
|
|
|
|
|
uintptr(dwDesiredAccess),
|
|
|
|
|
uintptr(dwShareMode),
|
|
|
|
|
uintptr(unsafe.Pointer(lpSecurityAttributes)),
|
|
|
|
|
uintptr(dwCreationDisposition),
|
|
|
|
|
uintptr(dwFlagsAndAttributes),
|
|
|
|
|
uintptr(hTemplateFile),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
handle := HANDLE(r)
|
|
|
|
|
if handle == HANDLE(syscall.InvalidHandle) {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return handle, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return handle, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return handle, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ReadFile(hFile HANDLE, lpBuffer []byte, lpNumberOfBytesRead *DWORD, lpOverlapped *syscall.Overlapped) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "ReadFile")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bufferPtr uintptr
|
|
|
|
|
if len(lpBuffer) > 0 {
|
|
|
|
|
bufferPtr = uintptr(unsafe.Pointer(&lpBuffer[0]))
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(proc, 5,
|
|
|
|
|
uintptr(hFile),
|
|
|
|
|
bufferPtr,
|
|
|
|
|
uintptr(len(lpBuffer)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpNumberOfBytesRead)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpOverlapped)),
|
|
|
|
|
0,
|
|
|
|
|
)
|
2024-04-02 10:16:13 +08:00
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func WriteFile(hFile HANDLE, lpBuffer []byte, lpNumberOfBytesWritten *DWORD, lpOverlapped *syscall.Overlapped) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "WriteFile")
|
2024-04-02 10:16:13 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
|
|
|
|
|
var bufferPtr uintptr
|
|
|
|
|
if len(lpBuffer) > 0 {
|
|
|
|
|
bufferPtr = uintptr(unsafe.Pointer(&lpBuffer[0]))
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall6(proc, 5,
|
|
|
|
|
uintptr(hFile),
|
|
|
|
|
bufferPtr,
|
|
|
|
|
uintptr(len(lpBuffer)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpNumberOfBytesWritten)),
|
|
|
|
|
uintptr(unsafe.Pointer(lpOverlapped)),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DeleteFile(path string) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "DeleteFileW")
|
2024-04-02 10:16:13 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 0, 0)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2024-04-02 10:16:13 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2025-11-07 22:37:37 +08:00
|
|
|
|
2026-06-06 17:46:02 +08:00
|
|
|
func CopyFile(existingFileName, newFileName string, bFailIfExists bool) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "CopyFileW")
|
2025-11-07 22:37:37 +08:00
|
|
|
if err != nil {
|
2026-06-06 17:46:02 +08:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
failIfExists := uintptr(0)
|
|
|
|
|
if bFailIfExists {
|
|
|
|
|
failIfExists = 1
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 3,
|
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(existingFileName))),
|
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(newFileName))),
|
|
|
|
|
failIfExists,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
2025-11-07 22:37:37 +08:00
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetFileAttributes(path string) (DWORD, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetFileAttributesW")
|
2025-11-07 22:37:37 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
2026-06-06 17:46:02 +08:00
|
|
|
r, _, errno := syscall.Syscall(proc, 1, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))), 0, 0)
|
|
|
|
|
attr := DWORD(r)
|
|
|
|
|
if attr == INVALID_FILE_ATTRIBUTES {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return attr, error(errno)
|
|
|
|
|
}
|
|
|
|
|
return attr, syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return attr, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func MoveFileEx(existingFileName, newFileName string, dwFlags DWORD) error {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "MoveFileExW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var newFilePtr uintptr
|
|
|
|
|
if len(newFileName) > 0 {
|
|
|
|
|
newFilePtr = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(newFileName)))
|
|
|
|
|
}
|
|
|
|
|
r, _, errno := syscall.Syscall(proc, 3,
|
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(existingFileName))),
|
|
|
|
|
newFilePtr,
|
|
|
|
|
uintptr(dwFlags),
|
|
|
|
|
)
|
2025-11-07 22:37:37 +08:00
|
|
|
if r == 0 {
|
2026-06-06 17:46:02 +08:00
|
|
|
if errno != 0 {
|
|
|
|
|
return error(errno)
|
|
|
|
|
}
|
|
|
|
|
return syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GetFullPathName(path string) (string, error) {
|
|
|
|
|
proc, err := getProcAddr("kernel32.dll", "GetFullPathNameW")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size := uint32(syscall.MAX_PATH + 1)
|
|
|
|
|
for {
|
|
|
|
|
buf := make([]uint16, size)
|
|
|
|
|
r, _, errno := syscall.Syscall6(proc, 4,
|
|
|
|
|
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(path))),
|
|
|
|
|
uintptr(size),
|
|
|
|
|
uintptr(unsafe.Pointer(&buf[0])),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
if r == 0 {
|
|
|
|
|
if errno != 0 {
|
|
|
|
|
return "", error(errno)
|
|
|
|
|
}
|
|
|
|
|
return "", syscall.EINVAL
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
needed := uint32(r)
|
|
|
|
|
if needed < size {
|
|
|
|
|
return syscall.UTF16ToString(buf[:needed]), nil
|
|
|
|
|
}
|
|
|
|
|
size = needed + 1
|
2025-11-07 22:37:37 +08:00
|
|
|
}
|
|
|
|
|
}
|