filetime.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // Package mstypes implements representations of Microsoft types for PAC processing.
  2. package mstypes
  3. import (
  4. "encoding/binary"
  5. "gopkg.in/jcmturner/gokrb5.v2/ndr"
  6. "time"
  7. )
  8. /*
  9. FILETIME is a windows data structure.
  10. Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx
  11. It contains two parts that are 32bit integers:
  12. dwLowDateTime
  13. dwHighDateTime
  14. We need to combine these two into one 64bit integer.
  15. This gives the number of 100 nano second period from January 1, 1601, Coordinated Universal Time (UTC)
  16. */
  17. const unixEpochDiff = 116444736000000000
  18. // FileTime implements the Microsoft FILETIME type https://msdn.microsoft.com/en-us/library/cc230324.aspx
  19. type FileTime struct {
  20. LowDateTime uint32
  21. HighDateTime uint32
  22. }
  23. // Time return a golang Time type from the FileTime
  24. func (ft FileTime) Time() time.Time {
  25. ns := (ft.MSEpoch() - unixEpochDiff) * 100
  26. return time.Unix(0, int64(ns)).UTC()
  27. }
  28. // MSEpoch returns the FileTime as a Microsoft epoch, the number of 100 nano second periods elapsed from January 1, 1601 UTC.
  29. func (ft FileTime) MSEpoch() int64 {
  30. return (int64(ft.HighDateTime) << 32) + int64(ft.LowDateTime)
  31. }
  32. // Unix returns the FileTime as a Unix time, the number of seconds elapsed since January 1, 1970 UTC.
  33. func (ft FileTime) Unix() int64 {
  34. return (ft.MSEpoch() - unixEpochDiff) / 10000000
  35. }
  36. // GetFileTime returns a FileTime type from the provided Golang Time type.
  37. func GetFileTime(t time.Time) FileTime {
  38. ns := t.UnixNano()
  39. fp := (ns / 100) + unixEpochDiff
  40. hd := fp >> 32
  41. ld := fp - (hd << 32)
  42. return FileTime{
  43. LowDateTime: uint32(ld),
  44. HighDateTime: uint32(hd),
  45. }
  46. }
  47. // ReadFileTime reads a FileTime from the bytes slice.
  48. func ReadFileTime(b *[]byte, p *int, e *binary.ByteOrder) FileTime {
  49. l := ndr.ReadUint32(b, p, e)
  50. h := ndr.ReadUint32(b, p, e)
  51. return FileTime{
  52. LowDateTime: l,
  53. HighDateTime: h,
  54. }
  55. }