From f34bb9fccc5017bce03e0a0446cc145e8424054b Mon Sep 17 00:00:00 2001 From: JoeyShapiro Date: Sun, 5 May 2024 01:47:56 +0000 Subject: [PATCH] windows: add net user enum In the go windows package, you can get user information by using `NetUserGetInfo` along with a specified level. However, there is no way to get a list of the users. The only options are to 1. know the users, 2. brute force users, or 3. use an external tool or command (`net users`). I suggest adding a function that implements the windows api for `NetUserEnum`. This will allow a built in way to enumerate users and follow the standard. A side note is that I used `buf **byte` because it is how the others are done, but using `buf *byte` works just as well. Change-Id: Ifcc916659eb1d796175cd18acd2e81f2661bfcd2 GitHub-Last-Rev: 3d01bca920d95280311d47b8e6a9b91d472bea98 GitHub-Pull-Request: golang/sys#190 Reviewed-on: https://go-review.googlesource.com/c/sys/+/578475 Reviewed-by: Alex Brainman Auto-Submit: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Cherry Mui --- windows/security_windows.go | 1 + windows/zsyscall_windows.go | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/windows/security_windows.go b/windows/security_windows.go index 26be94a8a..6f7d2ac70 100644 --- a/windows/security_windows.go +++ b/windows/security_windows.go @@ -68,6 +68,7 @@ type UserInfo10 struct { //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree +//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum const ( // do not reorder diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go index 5c6035ddf..9f73df75b 100644 --- a/windows/zsyscall_windows.go +++ b/windows/zsyscall_windows.go @@ -401,6 +401,7 @@ var ( procTransmitFile = modmswsock.NewProc("TransmitFile") procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetUserEnum = modnetapi32.NewProc("NetUserEnum") procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") @@ -3486,6 +3487,14 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete return } +func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) { + r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle)), 0) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 {