SickGear/lib/hachoir/parser/common/win32.py

182 lines
6.1 KiB
Python

from hachoir.field import (FieldSet,
UInt16, UInt32, Enum, String, Bytes, Bits, TimestampUUID60)
from hachoir.parser.video.fourcc import video_fourcc_name
from hachoir.core.bits import str2hex
from hachoir.core.text_handler import textHandler, hexadecimal
from hachoir.parser.network.common import MAC48_Address
# Dictionary: Windows codepage => Python charset name
CODEPAGE_CHARSET = {
874: "CP874",
# 932: Japanese Shift-JIS
# 936: Simplified Chinese GBK
# 949: Korean
# 950: Traditional Chinese Big5
1250: "WINDOWS-1250",
1251: "WINDOWS-1251",
1252: "WINDOWS-1252",
1253: "WINDOWS-1253",
1254: "WINDOWS-1254",
1255: "WINDOWS-1255",
1256: "WINDOWS-1256",
1257: "WINDOWS-1257",
1258: "WINDOWS-1258",
10000: "MacRoman",
65001: "UTF-8",
}
class PascalStringWin16(FieldSet):
def __init__(self, parent, name, description=None, strip=None, charset="UTF-16-LE"):
FieldSet.__init__(self, parent, name, description)
length = self["length"].value
self._size = 16 + length * 16
self.strip = strip
self.charset = charset
def createFields(self):
yield UInt16(self, "length", "Length in widechar characters")
size = self["length"].value
if size:
yield String(self, "text", size * 2, charset=self.charset, strip=self.strip)
def createValue(self):
if "text" in self:
return self["text"].value
else:
return None
class PascalStringWin32(FieldSet):
def __init__(self, parent, name, description=None, strip=None, charset="UTF-16-LE"):
FieldSet.__init__(self, parent, name, description)
length = self["length"].value
self._size = 32 + length * 16
self.strip = strip
self.charset = charset
def createFields(self):
yield UInt32(self, "length", "Length in widechar characters")
size = self["length"].value
if size:
yield String(self, "text", size * 2, charset=self.charset, strip=self.strip)
def createValue(self):
if "text" in self:
return self["text"].value
else:
return None
class GUID(FieldSet):
"""
Windows 128 bits Globally Unique Identifier (GUID)
See RFC 4122
"""
static_size = 128
NULL = "00000000-0000-0000-0000-000000000000"
FIELD_NAMES = {
3: ("sha1_high", "sha1_low"),
4: ("random_high", "random_low"),
5: ("md5_high", "md5_low"),
}
VERSION_NAME = {
1: "Timestamp & MAC-48",
2: "DCE Security version",
3: "Name SHA-1 hash",
4: "Randomly generated",
5: "Name MD5 hash",
}
VARIANT_NAME = {
0: "NCS",
2: "Leach-Salz",
# 5: Microsoft Corporation?
6: "Microsoft Corporation",
7: "Reserved Future",
}
def __init__(self, *args):
FieldSet.__init__(self, *args)
self.version = self.stream.readBits(
self.absolute_address + 32 + 16 + 12, 4, self.endian)
def createFields(self):
if self.version == 1:
yield TimestampUUID60(self, "time")
yield Enum(Bits(self, "version", 4), self.VERSION_NAME)
yield Enum(Bits(self, "variant", 3), self.VARIANT_NAME)
yield textHandler(Bits(self, "clock", 13), hexadecimal)
# yield textHandler(Bits(self, "clock", 16), hexadecimal)
if self.version == 1:
yield MAC48_Address(self, "mac", "IEEE 802 MAC address")
else:
yield Bytes(self, "node", 6)
else:
namea, nameb = self.FIELD_NAMES.get(
self.version, ("data_a", "data_b"))
yield textHandler(Bits(self, namea, 60), hexadecimal)
yield Enum(Bits(self, "version", 4), self.VERSION_NAME)
yield Enum(Bits(self, "variant", 3), self.VARIANT_NAME)
yield textHandler(Bits(self, nameb, 61), hexadecimal)
def createValue(self):
addr = self.absolute_address
a = self.stream.readBits(addr, 32, self.endian)
b = self.stream.readBits(addr + 32, 16, self.endian)
c = self.stream.readBits(addr + 48, 16, self.endian)
d = self.stream.readBytes(addr + 64, 2)
e = self.stream.readBytes(addr + 80, 6)
return "%08X-%04X-%04X-%s-%s" % (a, b, c, str2hex(d), str2hex(e))
def createDisplay(self):
value = self.value
if value == self.NULL:
name = "Null GUID: "
else:
name = "GUID v%u (%s): " % (self.version, self["version"].display)
return name + value
def createRawDisplay(self):
value = self.stream.readBytes(self.absolute_address, 16)
return str2hex(value, format=r"\x%02x")
class BitmapInfoHeader(FieldSet):
""" Win32 BITMAPINFOHEADER structure from GDI """
static_size = 40 * 8
COMPRESSION_NAME = {
0: "Uncompressed (RGB)",
1: "RLE (8 bits)",
2: "RLE (4 bits)",
3: "Bitfields",
4: "JPEG",
5: "PNG"
}
def __init__(self, parent, name, use_fourcc=False):
FieldSet.__init__(self, parent, name)
self._use_fourcc = use_fourcc
def createFields(self):
yield UInt32(self, "hdr_size", "Header size (in bytes) (=40)")
yield UInt32(self, "width", "Width")
yield UInt32(self, "height", "Height")
yield UInt16(self, "nb_planes", "Color planes")
yield UInt16(self, "bpp", "Bits/pixel")
if self._use_fourcc:
yield Enum(String(self, "codec", 4, charset="ASCII"), video_fourcc_name)
else:
yield Enum(UInt32(self, "codec", "Compression"), self.COMPRESSION_NAME)
yield UInt32(self, "size", "Image size (in bytes)")
yield UInt32(self, "xres", "X pixels per meter")
yield UInt32(self, "yres", "Y pixels per meter")
yield UInt32(self, "color_used", "Number of used colors")
yield UInt32(self, "color_important", "Number of important colors")
def createDescription(self):
return "Bitmap info header: %ux%u pixels, %u bits/pixel" % \
(self["width"].value, self["height"].value, self["bpp"].value)