win32api/kernel32.go
starainrt 0f82ba044b
修正 Win32 封装语义并补齐关键结构体/进程测试覆盖
- 修正 WTS 会话相关类型、枚举与活动会话选择逻辑
- 对齐 FILE_ID_DESCRIPTOR 布局与 FILE_ID_TYPE 语义,修复 OpenFileById 调用前提
- 修正 user32/shell32/kernel32 部分 API 的返回值、参数个数与错误处理
- 完善剪贴板更新格式读取的缓冲区重试逻辑
- 补充常用进程、线程、调试、桌面与会话 helper
- 增加结构体布局、会话查询、剪贴板、CreateProcess 等回归测试
- 将默认 CreateProcess 相关测试切到 helper 进程,并保留显式开启的 cmd.exe 集成覆盖
2026-06-06 17:46:02 +08:00

1351 lines
32 KiB
Go

package win32api
import (
"fmt"
"syscall"
"unsafe"
)
func WTSGetActiveConsoleSessionId() (DWORD, error) {
WTGet, err := getProcAddr("kernel32.dll", "WTSGetActiveConsoleSessionId")
if err != nil {
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
}
r, _, _ := syscall.Syscall(GPI, 1, uintptr(Process), 0, 0)
return uint32(r)
}
func ProcessIdToSessionId(dwProcessId DWORD) (DWORD, error) {
proc, err := getProcAddr("kernel32.dll", "ProcessIdToSessionId")
if err != nil {
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
}
return HANDLE(r), nil
}
func TerminateProcess(hProcess HANDLE, uExitCode DWORD) error {
proc, err := getProcAddr("kernel32.dll", "TerminateProcess")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 2, uintptr(hProcess), uintptr(uExitCode), 0)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
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")
if err != nil {
return err
}
var applicationName uintptr
if len(lpApplicationName) > 0 {
applicationName = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpApplicationName)))
}
var commandLine uintptr
if len(lpCommandLine) > 0 {
commandLine = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCommandLine)))
}
var currentDirectory uintptr
if len(lpCurrentDirectory) > 0 {
currentDirectory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpCurrentDirectory)))
}
inheritHandles := uintptr(0)
if bInheritHandles {
inheritHandles = 1
}
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,
)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func WaitForSingleObject(hHandle HANDLE, dwMilliseconds DWORD) (DWORD, error) {
proc, err := getProcAddr("kernel32.dll", "WaitForSingleObject")
if err != nil {
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)
}
proc, err := getProcAddr("kernel32.dll", "WaitForMultipleObjects")
if err != nil {
return 0, err
}
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
}
func GetExitCodeProcess(hProcess HANDLE) (DWORD, error) {
proc, err := getProcAddr("kernel32.dll", "GetExitCodeProcess")
if err != nil {
return 0, err
}
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")
if err != nil {
return 0, err
}
r, _, _ := syscall.Syscall(GTC, 0, 0, 0, 0)
return uint32(r), nil
}
func GlobalMemoryStatusEx(data *MEMORYSTATUSEX) (bool, error) {
(*data).DwLength = DWORD(unsafe.Sizeof(*data))
GMS, err := getProcAddr("kernel32.dll", "GlobalMemoryStatusEx")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall(GMS, 1, uintptr(unsafe.Pointer(data)), 0, 0)
if r == 0 {
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) {
Lck, err := getProcAddr("kernel32.dll", "LockFileEx")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall6(Lck, 6, uintptr(hFile), uintptr(dwFlags), uintptr(dwReserved),
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
}
func OpenFileById(hVolumeHint HANDLE, lpFileId *FILE_ID_DESCRIPTOR, dwDesiredAccess DWORD, dwShareMode DWORD,
lpSecurityAttributes *syscall.SecurityAttributes, dwFlagsAndAttributes DWORD) (HANDLE, error) {
ofb, err := getProcAddr("kernel32.dll", "OpenFileById")
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))
if HANDLE(r) == HANDLE(syscall.InvalidHandle) {
if errno != 0 {
return HANDLE(r), error(errno)
}
return HANDLE(r), syscall.EINVAL
}
return HANDLE(r), nil
}
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
}
Lck, err := getProcAddr("kernel32.dll", "CreateEventW")
if err != nil {
return 0, err
}
r, _, errno := syscall.Syscall6(Lck, 4, uintptr(unsafe.Pointer(lpEventAttributes)),
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
}
func GetLogicalDriveStringsW(nBufferLength DWORD, lpBuffer LPWSTR) error {
glds, err := getProcAddr("kernel32.dll", "GetLogicalDriveStringsW")
if err != nil {
return err
}
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
}
return nil
}
func GetVolumeInformationW(lpRootPathName LPCWSTR, lpVolumeNameBuffer LPWSTR, nVolumeNameSize DWORD,
lpVolumeSerialNumber LPDWORD, lpMaximumComponentLength LPDWORD, lpFileSystemFlags LPDWORD,
lpFileSystemNameBuffer LPWSTR, nFileSystemNameSize DWORD) error {
glds, err := getProcAddr("kernel32.dll", "GetVolumeInformationW")
if err != nil {
return err
}
r, _, errno := syscall.Syscall9(glds, 8, uintptr(unsafe.Pointer(lpRootPathName)),
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)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func DeviceIoControl(hDevice HANDLE, dwIoControlCode DWORD, lpInBuffer LPVOID, nInBufferSize DWORD, lpOutBuffer LPVOID,
nOutBufferSize DWORD, lpBytesReturned LPDWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
dic, err := getProcAddr("kernel32.dll", "DeviceIoControl")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall9(dic, 8, uintptr(hDevice), uintptr(dwIoControlCode),
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) {
dic, err := getProcAddr("kernel32.dll", "DeviceIoControl")
if err != nil {
return false, err
}
r, _, errno := syscall.Syscall9(dic, 8, uintptr(hDevice), uintptr(dwIoControlCode),
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
}
func GlobalLock(hMem HGLOBAL) (unsafe.Pointer, error) {
gl, err := getProcAddr("kernel32.dll", "GlobalLock")
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 {
gu, err := getProcAddr("kernel32.dll", "GlobalUnlock")
if err != nil {
return err
}
if err := SetLastError(0); err != nil {
return err
}
r, _, errno := syscall.Syscall(gu, 1, uintptr(hMem), 0, 0)
if r == 0 {
if errno == 0 {
return nil
}
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func GlobalSize(hMem HGLOBAL) (DWORD, error) {
gs, err := getProcAddr("kernel32.dll", "GlobalSize")
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
}
func GlobalAlloc(uFlags DWORD, dwBytes uintptr) (HGLOBAL, error) {
ga, err := getProcAddr("kernel32.dll", "GlobalAlloc")
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
}
func GlobalFree(hMem HGLOBAL) error {
gf, err := getProcAddr("kernel32.dll", "GlobalFree")
if err != nil {
return err
}
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")
if err != nil {
return err
}
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,
)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func WriteFile(hFile HANDLE, lpBuffer []byte, lpNumberOfBytesWritten *DWORD, lpOverlapped *syscall.Overlapped) error {
proc, err := getProcAddr("kernel32.dll", "WriteFile")
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(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")
if err != nil {
return err
}
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
}
return nil
}
func CopyFile(existingFileName, newFileName string, bFailIfExists bool) error {
proc, err := getProcAddr("kernel32.dll", "CopyFileW")
if err != nil {
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
}
return nil
}
func GetFileAttributes(path string) (DWORD, error) {
proc, err := getProcAddr("kernel32.dll", "GetFileAttributesW")
if err != nil {
return 0, err
}
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),
)
if r == 0 {
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
}
}