Skip to content

Commit

Permalink
Closes #89
Browse files Browse the repository at this point in the history
Retain Kind value for DateTime resource type.
  • Loading branch information
malwarefrank committed Feb 1, 2025
1 parent 703c9c3 commit 5680236
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 24 deletions.
41 changes: 31 additions & 10 deletions src/dnfile/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -985,28 +985,49 @@ def parse(self):

class DateTimeStruct(Structure):
Ticks: int
Kind: enums.DateTimeKind
Kind: int


class DateTime(object):
def __init__(self, rva: int, raw_bytes: bytes):
struct: Optional[DateTimeStruct]
kind: Optional[enums.DateTimeKind]
value: Optional[datetime.datetime]
seconds: Optional[int]
__data__: bytes

def __init__(self, raw_bytes: bytes, rva: Optional[int] = None):
self.struct: Optional[DateTimeStruct] = None
self.raw: bytes = raw_bytes
self.kind: Optional[enums.DateTimeKind] = None
self.value: Optional[datetime.datetime] = None
self.seconds: Optional[int] = None
self.__data__: bytes = raw_bytes
self.rva: Optional[int] = rva

def parse(self):
if not self.raw:
if not self.__data__:
# TODO: warn/error
return
# Should be 64 bites
if len(self.raw) != 8:
# Should be 64 bits
if len(self.__data__) != 8:
# TODO: warn/error
return
x = _struct.unpack("<q", self.raw)[0]
x = _struct.unpack("<q", self.__data__)[0]
self.struct = DateTimeStruct()
self.struct.Ticks = x & 0x3FFFFFFFFFFFFFFF
# Value is stored in lower 62-bits
# https://github.com/dotnet/runtime/blob/17c55f1/src/libraries/System.Private.CoreLib/src/System/DateTime.cs#L130-L138
self.struct.Kind = x >> 62
# https://stackoverflow.com/questions/3169517/python-c-sharp-binary-datetime-encoding
secs = self.struct.Ticks / 10.0 ** 7
delta = datetime.timedelta(seconds=secs)
self.value = datetime.datetime(1, 1, 1) + delta
self.Seconds = self.struct.Ticks / 10.0 ** 7
self.Kind = enums.DateTimeKind(self.struct.Kind)
delta = datetime.timedelta(seconds=self.Seconds)
if self.Kind == enums.DateTimeKind.Utc:
self.value = datetime.datetime(1, 1, 1, 0, 0, 0, 0, datetime.timezone.utc) + delta
else:
self.value = datetime.datetime(1, 1, 1, 0, 0, 0, 0) + delta

def __str__(self) -> str:
return str(self.value)

def to_datetime(self) -> Optional[datetime.datetime]:
return self.value
2 changes: 1 addition & 1 deletion src/dnfile/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,4 +874,4 @@ class DateTimeKind(_enum.IntEnum):
Unspecified = 0
Utc = 1
Local = 2
LocalAmbiguousDst = 3
LocalAmbiguousDst = 3
16 changes: 3 additions & 13 deletions src/dnfile/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,19 +224,9 @@ def type_str_to_type(self, type_name: str, data: bytes, offset: int) -> Tuple[Op
elif type_name == "System.DateTime":
tsize = 8
final_bytes = data[offset:offset + tsize]
x = struct.unpack("<q", final_bytes)[0]
# Value is stored in lower 62-bits
# https://github.com/dotnet/runtime/blob/17c55f1/src/libraries/System.Private.CoreLib/src/System/DateTime.cs#L130-L138
x = x & ((1 << 62) - 1)
# https://stackoverflow.com/questions/3169517/python-c-sharp-binary-datetime-encoding
secs = x / 10.0 ** 7
delta = datetime.timedelta(seconds=secs)
try:
dt = datetime.datetime(1, 1, 1) + delta
final_value = dt
except OverflowError:
# TODO warn/error
pass
dt = base.DateTime(final_bytes)
dt.parse()
final_value = dt
elif type_name == "System.TimeSpan":
# TODO return resourceDataFactory.Create(new TimeSpan(reader.ReadInt64()));
tsize = 8
Expand Down

0 comments on commit 5680236

Please sign in to comment.