mirror of
https://github.com/golang/sys.git
synced 2026-02-09 04:06:04 +03:00
windows: add various functions for shutting down and logging out
There are a few functions to control the behavior of shutdown and logout, both for what the current process does during shutdown, and also whether or not the current process is running in an interactive session. The below code is a port of the MSDN example code to Go using one of the added new functions: https://docs.microsoft.com/en-us/windows/win32/shutdown/how-to-shut-down-the-system func shutdownLikeMSDNDoes() error { seShutdownName, err := windows.UTF16PtrFromString("SeShutdownPrivilege") if err != nil { return err } var shutdownPriv windows.Tokenprivileges err = windows.LookupPrivilegeValue(nil, seShutdownName, &shutdownPriv.Privileges[0].Luid) if err != nil { return err } shutdownPriv.Privileges[0].Attributes = windows.SE_PRIVILEGE_ENABLED shutdownPriv.PrivilegeCount = 1 process, err := windows.GetCurrentProcess() if err != nil { return err } var token windows.Token err = windows.OpenProcessToken(process, windows.TOKEN_ADJUST_PRIVILEGES | windows.TOKEN_QUERY, &token) if err != nil { return err } defer token.Close() err = windows.AdjustTokenPrivileges(token, false, &shutdownPriv, 0, nil, nil) if err != nil { return err } err = windows.ExitWindowsEx(windows.EWX_SHUTDOWN | windows.EWX_FORCE, windows.SHTDN_REASON_MAJOR_OPERATINGSYSTEM | windows.SHTDN_REASON_MINOR_UPGRADE | windows.SHTDN_REASON_FLAG_PLANNED) if err != nil { return err } return nil } Note, though, that this function doesn't set the token privs back to how they were before, which isn't good. A more robust method than the MSDN one above would be to duplicate&impersonate. Fixes: golang/go#34271 Change-Id: Ibe55ddd35b709d9ab793cb9af47c39901c5e5c69 Reviewed-on: https://go-review.googlesource.com/c/sys/+/195497 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bruce Downs <bruceadowns@gmail.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
@@ -296,6 +296,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW
|
||||
//sys SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW
|
||||
//sys MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW
|
||||
//sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx
|
||||
//sys InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) = advapi32.InitiateSystemShutdownExW
|
||||
//sys SetProcessShutdownParameters(level uint32, flags uint32) (err error) = kernel32.SetProcessShutdownParameters
|
||||
//sys GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) = kernel32.GetProcessShutdownParameters
|
||||
//sys clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) = ole32.CLSIDFromString
|
||||
//sys stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) = ole32.StringFromGUID2
|
||||
//sys coCreateGuid(pguid *GUID) (ret error) = ole32.CoCreateGuid
|
||||
|
||||
@@ -1688,3 +1688,68 @@ type OsVersionInfoEx struct {
|
||||
ProductType byte
|
||||
_ byte
|
||||
}
|
||||
|
||||
const (
|
||||
EWX_LOGOFF = 0x00000000
|
||||
EWX_SHUTDOWN = 0x00000001
|
||||
EWX_REBOOT = 0x00000002
|
||||
EWX_FORCE = 0x00000004
|
||||
EWX_POWEROFF = 0x00000008
|
||||
EWX_FORCEIFHUNG = 0x00000010
|
||||
EWX_QUICKRESOLVE = 0x00000020
|
||||
EWX_RESTARTAPPS = 0x00000040
|
||||
EWX_HYBRID_SHUTDOWN = 0x00400000
|
||||
EWX_BOOTOPTIONS = 0x01000000
|
||||
|
||||
SHTDN_REASON_FLAG_COMMENT_REQUIRED = 0x01000000
|
||||
SHTDN_REASON_FLAG_DIRTY_PROBLEM_ID_REQUIRED = 0x02000000
|
||||
SHTDN_REASON_FLAG_CLEAN_UI = 0x04000000
|
||||
SHTDN_REASON_FLAG_DIRTY_UI = 0x08000000
|
||||
SHTDN_REASON_FLAG_USER_DEFINED = 0x40000000
|
||||
SHTDN_REASON_FLAG_PLANNED = 0x80000000
|
||||
SHTDN_REASON_MAJOR_OTHER = 0x00000000
|
||||
SHTDN_REASON_MAJOR_NONE = 0x00000000
|
||||
SHTDN_REASON_MAJOR_HARDWARE = 0x00010000
|
||||
SHTDN_REASON_MAJOR_OPERATINGSYSTEM = 0x00020000
|
||||
SHTDN_REASON_MAJOR_SOFTWARE = 0x00030000
|
||||
SHTDN_REASON_MAJOR_APPLICATION = 0x00040000
|
||||
SHTDN_REASON_MAJOR_SYSTEM = 0x00050000
|
||||
SHTDN_REASON_MAJOR_POWER = 0x00060000
|
||||
SHTDN_REASON_MAJOR_LEGACY_API = 0x00070000
|
||||
SHTDN_REASON_MINOR_OTHER = 0x00000000
|
||||
SHTDN_REASON_MINOR_NONE = 0x000000ff
|
||||
SHTDN_REASON_MINOR_MAINTENANCE = 0x00000001
|
||||
SHTDN_REASON_MINOR_INSTALLATION = 0x00000002
|
||||
SHTDN_REASON_MINOR_UPGRADE = 0x00000003
|
||||
SHTDN_REASON_MINOR_RECONFIG = 0x00000004
|
||||
SHTDN_REASON_MINOR_HUNG = 0x00000005
|
||||
SHTDN_REASON_MINOR_UNSTABLE = 0x00000006
|
||||
SHTDN_REASON_MINOR_DISK = 0x00000007
|
||||
SHTDN_REASON_MINOR_PROCESSOR = 0x00000008
|
||||
SHTDN_REASON_MINOR_NETWORKCARD = 0x00000009
|
||||
SHTDN_REASON_MINOR_POWER_SUPPLY = 0x0000000a
|
||||
SHTDN_REASON_MINOR_CORDUNPLUGGED = 0x0000000b
|
||||
SHTDN_REASON_MINOR_ENVIRONMENT = 0x0000000c
|
||||
SHTDN_REASON_MINOR_HARDWARE_DRIVER = 0x0000000d
|
||||
SHTDN_REASON_MINOR_OTHERDRIVER = 0x0000000e
|
||||
SHTDN_REASON_MINOR_BLUESCREEN = 0x0000000F
|
||||
SHTDN_REASON_MINOR_SERVICEPACK = 0x00000010
|
||||
SHTDN_REASON_MINOR_HOTFIX = 0x00000011
|
||||
SHTDN_REASON_MINOR_SECURITYFIX = 0x00000012
|
||||
SHTDN_REASON_MINOR_SECURITY = 0x00000013
|
||||
SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY = 0x00000014
|
||||
SHTDN_REASON_MINOR_WMI = 0x00000015
|
||||
SHTDN_REASON_MINOR_SERVICEPACK_UNINSTALL = 0x00000016
|
||||
SHTDN_REASON_MINOR_HOTFIX_UNINSTALL = 0x00000017
|
||||
SHTDN_REASON_MINOR_SECURITYFIX_UNINSTALL = 0x00000018
|
||||
SHTDN_REASON_MINOR_MMC = 0x00000019
|
||||
SHTDN_REASON_MINOR_SYSTEMRESTORE = 0x0000001a
|
||||
SHTDN_REASON_MINOR_TERMSRV = 0x00000020
|
||||
SHTDN_REASON_MINOR_DC_PROMOTION = 0x00000021
|
||||
SHTDN_REASON_MINOR_DC_DEMOTION = 0x00000022
|
||||
SHTDN_REASON_UNKNOWN = SHTDN_REASON_MINOR_NONE
|
||||
SHTDN_REASON_LEGACY_API = SHTDN_REASON_MAJOR_LEGACY_API | SHTDN_REASON_FLAG_PLANNED
|
||||
SHTDN_REASON_VALID_BIT_MASK = 0xc0ffffff
|
||||
|
||||
SHUTDOWN_NORETRY = 0x1
|
||||
)
|
||||
|
||||
@@ -234,6 +234,10 @@ var (
|
||||
procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW")
|
||||
procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW")
|
||||
procMessageBoxW = moduser32.NewProc("MessageBoxW")
|
||||
procExitWindowsEx = moduser32.NewProc("ExitWindowsEx")
|
||||
procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW")
|
||||
procSetProcessShutdownParameters = modkernel32.NewProc("SetProcessShutdownParameters")
|
||||
procGetProcessShutdownParameters = modkernel32.NewProc("GetProcessShutdownParameters")
|
||||
procCLSIDFromString = modole32.NewProc("CLSIDFromString")
|
||||
procStringFromGUID2 = modole32.NewProc("StringFromGUID2")
|
||||
procCoCreateGuid = modole32.NewProc("CoCreateGuid")
|
||||
@@ -2584,6 +2588,66 @@ func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret
|
||||
return
|
||||
}
|
||||
|
||||
func ExitWindowsEx(flags uint32, reason uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if forceAppsClosed {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
var _p1 uint32
|
||||
if rebootAfterShutdown {
|
||||
_p1 = 1
|
||||
} else {
|
||||
_p1 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason))
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func SetProcessShutdownParameters(level uint32, flags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) {
|
||||
r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0)
|
||||
if r0 != 0 {
|
||||
|
||||
Reference in New Issue
Block a user