//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 }