| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- //go:build windows
- // ============================================================================
- // timesync_windows.go — 系统时间同步(Windows 平台)
- //
- // 启用 SeSystemtimePrivilege 特权后用 SetLocalTime 校准系统时间;
- // 直接调用 syscall 声明 user32/kernel32 函数,不引入额外依赖。
- // ============================================================================
- package main
- import (
- "fmt"
- "syscall"
- "time"
- "unsafe"
- )
- // systemTime Windows SYSTEMTIME 结构
- type systemTime struct {
- Year, Month, DayOfWeek, Day, Hour, Minute, Second, Milliseconds uint16
- }
- type luid struct {
- LowPart uint32
- HighPart int32
- }
- type luidAndAttributes struct {
- Luid luid
- Attributes uint32
- }
- type tokenPrivileges struct {
- PrivilegeCount uint32
- Privileges [1]luidAndAttributes
- }
- // enablePrivilege 启用当前进程的指定特权(SeSystemtimePrivilege 默认禁用,
- // 必须先 AdjustTokenPrivileges 启用,否则 SetLocalTime 会失败)
- func enablePrivilege(name string) error {
- const (
- tokenQuery = 0x0008
- tokenAdjustPrivileges = 0x0020
- sePrivilegeEnabled = 0x00000002
- errNotAllAssigned = syscall.Errno(1300) // ERROR_NOT_ALL_ASSIGNED
- )
- advapi32 := syscall.NewLazyDLL("advapi32.dll")
- procOpenProcessToken := advapi32.NewProc("OpenProcessToken")
- procLookupPrivilegeValue := advapi32.NewProc("LookupPrivilegeValueW")
- procAdjustTokenPrivileges := advapi32.NewProc("AdjustTokenPrivileges")
- currentProc, _ := syscall.GetCurrentProcess()
- var token syscall.Handle
- ret, _, err := procOpenProcessToken.Call(
- uintptr(currentProc),
- tokenQuery|tokenAdjustPrivileges,
- uintptr(unsafe.Pointer(&token)),
- )
- if ret == 0 {
- return fmt.Errorf("OpenProcessToken: %v", err)
- }
- defer syscall.CloseHandle(token)
- var luidVal luid
- namePtr, _ := syscall.UTF16PtrFromString(name)
- ret, _, err = procLookupPrivilegeValue.Call(
- 0,
- uintptr(unsafe.Pointer(namePtr)),
- uintptr(unsafe.Pointer(&luidVal)),
- )
- if ret == 0 {
- return fmt.Errorf("LookupPrivilegeValue(%s): %v", name, err)
- }
- tp := tokenPrivileges{
- PrivilegeCount: 1,
- Privileges: [1]luidAndAttributes{
- {Luid: luidVal, Attributes: sePrivilegeEnabled},
- },
- }
- ret, _, err = procAdjustTokenPrivileges.Call(
- uintptr(token), 0,
- uintptr(unsafe.Pointer(&tp)), 0, 0, 0,
- )
- if ret == 0 {
- return fmt.Errorf("AdjustTokenPrivileges: %v", err)
- }
- if err == errNotAllAssigned {
- return fmt.Errorf("进程不具备特权 %s(需以管理员身份运行)", name)
- }
- return nil
- }
- // setLocalTime 按系统当前时区设置本地时间(需管理员权限)
- func setLocalTime(t time.Time) error {
- if err := enablePrivilege("SeSystemtimePrivilege"); err != nil {
- return err
- }
- st := systemTime{
- Year: uint16(t.Year()),
- Month: uint16(t.Month()),
- DayOfWeek: uint16(t.Weekday()),
- Day: uint16(t.Day()),
- Hour: uint16(t.Hour()),
- Minute: uint16(t.Minute()),
- Second: uint16(t.Second()),
- Milliseconds: uint16(t.Nanosecond() / 1e6),
- }
- ret, _, err := syscall.NewLazyDLL("kernel32.dll").NewProc("SetLocalTime").
- Call(uintptr(unsafe.Pointer(&st)))
- if ret == 0 {
- return fmt.Errorf("SetLocalTime: %v", err)
- }
- return nil
- }
|