97 lines
4.2 KiB
Go
97 lines
4.2 KiB
Go
|
package winloader
|
||
|
|
||
|
import (
|
||
|
"syscall"
|
||
|
|
||
|
"github.com/jchv/go-winloader/internal/loader"
|
||
|
"golang.org/x/sys/windows"
|
||
|
)
|
||
|
|
||
|
// Proc is a Proc implementation using a native procedure.
|
||
|
type Proc uintptr
|
||
|
|
||
|
// Call calls a native procedure.
|
||
|
func (p Proc) Call(a ...uint64) (r1, r2 uint64, lastErr error) {
|
||
|
var n1, n2 uintptr
|
||
|
switch len(a) {
|
||
|
case 0:
|
||
|
n1, n2, lastErr = syscall.Syscall(uintptr(p), 0, 0, 0, 0)
|
||
|
case 1:
|
||
|
n1, n2, lastErr = syscall.Syscall(uintptr(p), 1, uintptr(a[0]), 0, 0)
|
||
|
case 2:
|
||
|
n1, n2, lastErr = syscall.Syscall(uintptr(p), 2, uintptr(a[0]), uintptr(a[1]), 0)
|
||
|
case 3:
|
||
|
n1, n2, lastErr = syscall.Syscall(uintptr(p), 3, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]))
|
||
|
case 4:
|
||
|
n1, n2, lastErr = syscall.Syscall6(uintptr(p), 4, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), 0, 0)
|
||
|
case 5:
|
||
|
n1, n2, lastErr = syscall.Syscall6(uintptr(p), 5, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), 0)
|
||
|
case 6:
|
||
|
n1, n2, lastErr = syscall.Syscall6(uintptr(p), 6, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]))
|
||
|
case 7:
|
||
|
n1, n2, lastErr = syscall.Syscall9(uintptr(p), 7, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), 0, 0)
|
||
|
case 8:
|
||
|
n1, n2, lastErr = syscall.Syscall9(uintptr(p), 8, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), 0)
|
||
|
case 9:
|
||
|
n1, n2, lastErr = syscall.Syscall9(uintptr(p), 9, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]))
|
||
|
case 10:
|
||
|
n1, n2, lastErr = syscall.Syscall12(uintptr(p), 10, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), 0, 0)
|
||
|
case 11:
|
||
|
n1, n2, lastErr = syscall.Syscall12(uintptr(p), 11, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), uintptr(a[10]), 0)
|
||
|
case 12:
|
||
|
n1, n2, lastErr = syscall.Syscall12(uintptr(p), 12, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), uintptr(a[10]), uintptr(a[11]))
|
||
|
case 13:
|
||
|
n1, n2, lastErr = syscall.Syscall15(uintptr(p), 13, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), uintptr(a[10]), uintptr(a[11]), uintptr(a[12]), 0, 0)
|
||
|
case 14:
|
||
|
n1, n2, lastErr = syscall.Syscall15(uintptr(p), 14, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), uintptr(a[10]), uintptr(a[11]), uintptr(a[12]), uintptr(a[13]), 0)
|
||
|
case 15:
|
||
|
n1, n2, lastErr = syscall.Syscall15(uintptr(p), 15, uintptr(a[0]), uintptr(a[1]), uintptr(a[2]), uintptr(a[3]), uintptr(a[4]), uintptr(a[5]), uintptr(a[6]), uintptr(a[7]), uintptr(a[8]), uintptr(a[9]), uintptr(a[10]), uintptr(a[11]), uintptr(a[12]), uintptr(a[13]), uintptr(a[14]))
|
||
|
default:
|
||
|
panic("too many arguments")
|
||
|
}
|
||
|
return uint64(n1), uint64(n2), lastErr
|
||
|
}
|
||
|
|
||
|
// Addr gets the native address of the procedure.
|
||
|
func (p Proc) Addr() uint64 {
|
||
|
return uint64(p)
|
||
|
}
|
||
|
|
||
|
// Library is a module implementation using the native Windows loader.
|
||
|
type Library windows.Handle
|
||
|
|
||
|
// Proc implements loader.Module
|
||
|
func (l Library) Proc(name string) loader.Proc {
|
||
|
proc, _ := windows.GetProcAddress(windows.Handle(l), name)
|
||
|
if proc == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return Proc(proc)
|
||
|
}
|
||
|
|
||
|
// Ordinal implements loader.Module
|
||
|
func (l Library) Ordinal(ordinal uint64) loader.Proc {
|
||
|
proc, _ := windows.GetProcAddressByOrdinal(windows.Handle(l), uintptr(ordinal))
|
||
|
if proc == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return Proc(proc)
|
||
|
}
|
||
|
|
||
|
// Free implements loader.Module
|
||
|
func (l Library) Free() error {
|
||
|
return windows.FreeLibrary(windows.Handle(l))
|
||
|
}
|
||
|
|
||
|
// Loader is a loader that uses the native Windows library loader.
|
||
|
type Loader struct{}
|
||
|
|
||
|
// Load loads a module into memory.
|
||
|
func (Loader) Load(libname string) (loader.Module, error) {
|
||
|
handle, err := windows.LoadLibrary(libname)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return Library(handle), nil
|
||
|
}
|