first commit
This commit is contained in:
78
internal/kernel32/kernel32.go
Normal file
78
internal/kernel32/kernel32.go
Normal file
@ -0,0 +1,78 @@
|
||||
//go:build windows
|
||||
|
||||
package kernel32
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type (
|
||||
heapHandle = uintptr
|
||||
win32Error uint32
|
||||
heapFlags uint32
|
||||
)
|
||||
|
||||
const (
|
||||
heapNone heapFlags = 0
|
||||
heapZeroMemory heapFlags = 8 // The allocated memory will be initialized to zero.
|
||||
)
|
||||
|
||||
var (
|
||||
libKernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
pHeapFree uintptr
|
||||
pHeapAlloc uintptr
|
||||
pGetProcessHeap uintptr
|
||||
|
||||
hHeap heapHandle
|
||||
)
|
||||
|
||||
func init() {
|
||||
hHeap, _ = getProcessHeap()
|
||||
}
|
||||
|
||||
// Malloc allocates the given amount of bytes in the heap
|
||||
func Malloc(size uintptr) unsafe.Pointer {
|
||||
return heapAlloc(hHeap, heapZeroMemory, size)
|
||||
}
|
||||
|
||||
// Free releases the given unsafe pointer from the heap
|
||||
func Free(inst unsafe.Pointer) {
|
||||
_, _ = heapFree(hHeap, heapNone, inst)
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc
|
||||
func heapAlloc(hHeap heapHandle, dwFlags heapFlags, dwBytes uintptr) unsafe.Pointer {
|
||||
addr := getProcAddr(&pHeapAlloc, libKernel32, "HeapAlloc")
|
||||
allocatedPtr, _, _ := syscall.SyscallN(addr, hHeap, uintptr(dwFlags), dwBytes)
|
||||
// Since this pointer is allocated in the heap by Windows, it will never be
|
||||
// GCd by Go, so this is a safe operation.
|
||||
// But linter thinks it is not (probably because we are not using CGO) and fails.
|
||||
return unsafe.Pointer(allocatedPtr) //nolint:gosec,govet
|
||||
}
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapfree
|
||||
func heapFree(hHeap heapHandle, dwFlags heapFlags, lpMem unsafe.Pointer) (bool, win32Error) {
|
||||
addr := getProcAddr(&pHeapFree, libKernel32, "HeapFree")
|
||||
ret, _, err := syscall.SyscallN(addr, hHeap, uintptr(dwFlags), uintptr(lpMem))
|
||||
return ret == 0, win32Error(err)
|
||||
}
|
||||
|
||||
func getProcessHeap() (heapHandle, win32Error) {
|
||||
addr := getProcAddr(&pGetProcessHeap, libKernel32, "GetProcessHeap")
|
||||
ret, _, err := syscall.SyscallN(addr)
|
||||
return ret, win32Error(err)
|
||||
}
|
||||
|
||||
func getProcAddr(pAddr *uintptr, lib *windows.LazyDLL, procName string) uintptr {
|
||||
addr := atomic.LoadUintptr(pAddr)
|
||||
if addr == 0 {
|
||||
addr = lib.NewProc(procName).Addr()
|
||||
atomic.StoreUintptr(pAddr, addr)
|
||||
}
|
||||
return addr
|
||||
}
|
Reference in New Issue
Block a user