You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.5 KiB

  1. // Copyright 2012 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build windows
  5. package svc
  6. import (
  7. "unsafe"
  8. "golang.org/x/sys/windows"
  9. )
  10. func allocSid(subAuth0 uint32) (*windows.SID, error) {
  11. var sid *windows.SID
  12. err := windows.AllocateAndInitializeSid(&windows.SECURITY_NT_AUTHORITY,
  13. 1, subAuth0, 0, 0, 0, 0, 0, 0, 0, &sid)
  14. if err != nil {
  15. return nil, err
  16. }
  17. return sid, nil
  18. }
  19. // IsAnInteractiveSession determines if calling process is running interactively.
  20. // It queries the process token for membership in the Interactive group.
  21. // http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s
  22. func IsAnInteractiveSession() (bool, error) {
  23. interSid, err := allocSid(windows.SECURITY_INTERACTIVE_RID)
  24. if err != nil {
  25. return false, err
  26. }
  27. defer windows.FreeSid(interSid)
  28. serviceSid, err := allocSid(windows.SECURITY_SERVICE_RID)
  29. if err != nil {
  30. return false, err
  31. }
  32. defer windows.FreeSid(serviceSid)
  33. t, err := windows.OpenCurrentProcessToken()
  34. if err != nil {
  35. return false, err
  36. }
  37. defer t.Close()
  38. gs, err := t.GetTokenGroups()
  39. if err != nil {
  40. return false, err
  41. }
  42. p := unsafe.Pointer(&gs.Groups[0])
  43. groups := (*[2 << 20]windows.SIDAndAttributes)(p)[:gs.GroupCount]
  44. for _, g := range groups {
  45. if windows.EqualSid(g.Sid, interSid) {
  46. return true, nil
  47. }
  48. if windows.EqualSid(g.Sid, serviceSid) {
  49. return false, nil
  50. }
  51. }
  52. return false, nil
  53. }