Esempio n. 1
0
    def __init__(self, name, value):
        """
        name
          These are str objects in both versions since we cannot use a leading 'u' to force
          them to unicode.  (Python 3.2 does not allow it.)  This is not a problem since it is
          required to be Unicode value when stored, so we can always convert it.

          In Python 2.7, this will be an str object since they are hardcoded in this file and

        value

          Both Unicode values and binary values are stored in the resource, so more care must
          be taken with this parameter.

          In both versions, a ctypes.Structure (used for VS_FIXEDFILEINFO) will be converted to
          a binary format.

          In Python 3, str values are used for Unicode strings and bytes for binary values.  In
          Python 2, unicode values are used for Unicode strings and str objects for binary
          values.
        """
        self.name = name

        # Set wType to string (1) if there is no data to match StringFileInfo.  I'm not sure if it matters.
        self.wType = (value is None or compat.isunicode(value)) and 1 or 0

        if isinstance(value, Structure):
            value = string_at(addressof(value), sizeof(value))
        elif compat.isunicode(value):
            # We need to write the NULL terminator and it needs to be included in the length.
            value = compat.toucs2(value) + UCS2_NULL
        
        self.value     = value
        self.children = []
Esempio n. 2
0
    def tobytes(self):
        """
        Returns this node encoded as an unpadded VERSIONNODE.
        """
        # Not clear in Microsoft's documentation, but if the value is in a String resource
        # block, the length is in *characters*, not bytes.  This is a very bad design.
        #
        # At this time, the only string values supported are in String resource blocks, so
        # anytime wType is 1 we'll set the length to characters.

        if self.value is not None:
            valuelen = len(self.value)
            if self.wType == 1:
                valuelen /= 2
        else:
            valuelen = 0

        parts = [
            '--', # placeholder for cbNode
            struct.pack('HH', valuelen, self.wType),
            compat.toucs2(self.name) + UCS2_NULL
            ]

        cbNode = sum(len(part) for part in parts)

        if self.value is not None:
            cbNode = self.add_aligned(parts, cbNode, self.value)

        for child in self.children:
            cbNode = self.add_aligned(parts, cbNode, child.tobytes())

        parts[0] = struct.pack('H', cbNode)

        return compat.joinbytes(parts)
Esempio n. 3
0
def AddVersionResource(exe, version, version_strings):
    """
    Adds a version resource to the given executable, constructed from `version_strings`.
    """
    # Parse version numbers.  We'll take any integers in the order they were found.
    # We need 4 parts total, so fill with 0s and truncate.

    parts = [ int(n) for n in re.findall('\d+', version) ]
    parts = (parts + [ 0, 0, 0, 0 ])[:4]

    ffi = VS_FIXEDFILEINFO()
    ffi.dwSignature        = 0xFEEF04BD
    ffi.dwStrucVersion     = 0x00010000
    ffi.dwFileVersionMS    = (parts[0] << 16) | parts[1]
    ffi.dwFileVersionLS    = (parts[2] << 16) | parts[3]
    ffi.dwProductVersionMS = (parts[0] << 16) | parts[1]
    ffi.dwProductVersionLS = (parts[2] << 16) | parts[3]
    ffi.dwFileFlagsMask    = 0x3F
    ffi.dwFileFlags        = 0x00
    ffi.dwFileOS           = VOS_NT_WINDOWS32
    ffi.dwFileType         = VFT_APP
    
    for lang, strings in version_strings.items():
        if 'SpecialBuild' in strings:
            ffi.dwFileFlags |= VS_FF_SPECIALBUILD

    root = VersionNode('VS_VERSION_INFO', ffi)

    sfi = VersionNode('StringFileInfo', None)
    root.children.append(sfi)

    for lang, strings in version_strings.items():
        lang = VersionNode('{:04X}{:04X}'.format(lang, 0x04B0), None)
        sfi.children.append(lang)

        for name, value in strings.items():
            lang.children.append(VersionNode(name, compat.toucs2(value) + UCS2_NULL))

    vfi = VersionNode('VarFileInfo', None)
    root.children.append(vfi)

    words = []
    for lang in version_strings:
        words.append(lang)
        words.append(0x04B0)

    translation = struct.pack('H' * len(words), *words)
    vfi.children.append(VersionNode('Translation', translation))

    UpdateFileVersion(exe, root.tobytes())
Esempio n. 4
0
    from . import compat3 as compat
else:
    import compat2 as compat

RT_VERSION  = 16
RT_MANIFEST = 24

VOS_NT_WINDOWS32   = 0x00040004
VS_FF_SPECIALBUILD = 0x00000020
VS_FF_PRERELEASE   = 0x00000002
VFT_APP            = 0x00000001

WORD  = c_short
DWORD = c_long

UCS2_NULL = compat.toucs2('\0')

def AddVersionResource(exe, version, version_strings):
    """
    Adds a version resource to the given executable, constructed from `version_strings`.
    """
    # Parse version numbers.  We'll take any integers in the order they were found.
    # We need 4 parts total, so fill with 0s and truncate.

    parts = [ int(n) for n in re.findall('\d+', version) ]
    parts = (parts + [ 0, 0, 0, 0 ])[:4]

    ffi = VS_FIXEDFILEINFO()
    ffi.dwSignature        = 0xFEEF04BD
    ffi.dwStrucVersion     = 0x00010000
    ffi.dwFileVersionMS    = (parts[0] << 16) | parts[1]