srcanamdw/codescanner/pyinstaller/versionInfo.py
changeset 1 22878952f6e2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanamdw/codescanner/pyinstaller/versionInfo.py	Thu Feb 18 12:29:02 2010 +0530
@@ -0,0 +1,531 @@
+# Copyright (C) 2005, Giovanni Bajo
+# Based on previous work under copyright (c) 2001, 2002 McMillan Enterprises, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+import win32api
+import struct
+import pywintypes
+import string
+import pprint
+
+TEST=0
+
+LOAD_LIBRARY_AS_DATAFILE = 2
+RT_VERSION = 16
+
+def getRaw0(o):
+    return o.raw
+def getRaw1(o):
+    return str(buffer(o))
+import sys
+if hasattr(sys, "version_info"):
+    pyvers = sys.version_info[0]*10 + sys.version_info[1]
+else:
+    toks = string.split(sys.version, '.', 2)
+    pyvers = int(toks[0])*10 + int(toks[1])
+if pyvers < 20:
+    getRaw = getRaw0
+else:
+    getRaw = getRaw1
+
+
+##VS_VERSION_INFO {
+##    WORD  wLength;        // Specifies the length of the VS_VERSION_INFO structure
+##    WORD  wValueLength;   // Specifies the length of the Value member
+##    WORD  wType;          // 1 means text, 0 means binary
+##    WCHAR szKey[];        // Contains the Unicode string "VS_VERSION_INFO".
+##    WORD  Padding1[];
+##    VS_FIXEDFILEINFO Value;
+##    WORD  Padding2[];
+##    WORD  Children[];     // Specifies a list of zero or more StringFileInfo or VarFileInfo structures (or both) that are children of the current version structure.
+##};
+def decode(pathnm):
+    h = win32api.LoadLibraryEx(pathnm, 0, LOAD_LIBRARY_AS_DATAFILE)
+    nm = win32api.EnumResourceNames(h, RT_VERSION)[0]
+    data = win32api.LoadResource(h, RT_VERSION, nm)
+    vs = VSVersionInfo()
+    j = vs.fromRaw(data)
+    if TEST:
+        print vs
+        if data[:j] != vs.toRaw():
+            print "AAAAAGGHHHH"
+        txt = repr(vs)
+        glbls = {}
+        glbls['VSVersionInfo'] = VSVersionInfo
+        glbls['FixedFileInfo'] = FixedFileInfo
+        glbls['StringFileInfo'] = StringFileInfo
+        glbls['StringTable'] = StringTable
+        glbls['StringStruct'] = StringStruct
+        glbls['VarFileInfo'] = VarFileInfo
+        glbls['VarStruct'] = VarStruct
+        vs2 = eval(txt+'\n', glbls)
+        if vs.toRaw() != vs2.toRaw():
+            print
+            print 'reconstruction not the same!'
+            print vs2
+    win32api.FreeLibrary(h)
+    return vs
+
+class VSVersionInfo:
+    def __init__(self, ffi=None, kids=None):
+        self.ffi = ffi
+        self.kids = kids
+        if kids is None:
+            self.kids = []
+    def fromRaw(self, data):
+        i, (sublen, vallen, wType, nm) = parseCommon(data)
+        #vallen is length of the ffi, typ is 0, nm is 'VS_VERSION_INFO'
+        i = ((i + 3) / 4) * 4
+        # now a VS_FIXEDFILEINFO
+        self.ffi = FixedFileInfo()
+        j = self.ffi.fromRaw(data, i)
+        #print ffi
+        if TEST:
+            if data[i:j] != self.ffi.toRaw():
+                print "raw:", `data[i:j]`
+                print "ffi:", `self.ffi.toRaw()`
+        i = j
+        while i < sublen:
+            j = i
+            i, (csublen, cvallen, ctyp, nm) = parseCommon(data, i)
+            if string.strip(str(nm)) == "StringFileInfo":
+                sfi = StringFileInfo()
+                k = sfi.fromRaw(csublen, cvallen, nm, data, i, j+csublen)
+                if TEST:
+                    if data[j:k] != sfi.toRaw():
+                        rd = data[j:k]
+                        sd = sfi.toRaw()
+                        for x in range(0, len(rd), 16):
+                            rds = rd[x:x+16]
+                            sds = sd[x:x+16]
+                            if rds != sds:
+                                print "rd[%s:%s+16]: %s" % (x, x, `rds`)
+                                print "sd[%s:%s+16]: %s" % (x, x, `sds`)
+                                print
+                        print "raw: len %d, wLength %d" % (len(rd), struct.unpack('h', rd[:2])[0])
+                        print "sfi: len %d, wLength %d" % (len(sd), struct.unpack('h', sd[:2])[0])
+                self.kids.append(sfi)
+                i = k
+            else:
+                vfi = VarFileInfo()
+                k = vfi.fromRaw(csublen, cvallen, nm, data, i, j+csublen)
+                self.kids.append(vfi)
+                if TEST:
+                    if data[j:k] != vfi.toRaw():
+                        print "raw:", `data[j:k]`
+                        print "vfi:", `vfi.toRaw()`
+                i = k
+            i = j + csublen
+            i = ((i + 3) / 4) * 4
+        return i
+    def toRaw(self):
+        nm = pywintypes.Unicode('VS_VERSION_INFO')
+        rawffi = self.ffi.toRaw()
+        vallen = len(rawffi)
+        typ = 0
+        sublen = 6 + 2*len(nm) + 2
+        pad = ''
+        if sublen % 4:
+            pad = '\000\000'
+        sublen = sublen + len(pad) + vallen
+        pad2 = ''
+        if sublen % 4:
+            pad2 = '\000\000'
+        tmp = []
+        for kid in self.kids:
+            tmp.append(kid.toRaw())
+        tmp = string.join(tmp, '')
+        sublen = sublen + len(pad2) + len(tmp)
+        return struct.pack('hhh', sublen, vallen, typ) + getRaw(nm) + '\000\000' + pad + rawffi + pad2 + tmp
+    def __repr__(self, indent=''):
+        tmp = []
+        newindent = indent + '  '
+        for kid in self.kids:
+            tmp.append(kid.__repr__(newindent+'  '))
+        tmp = string.join(tmp, ', \n')
+        return "VSVersionInfo(\n%sffi=%s,\n%skids=[\n%s\n%s]\n)" % (newindent, self.ffi.__repr__(newindent), newindent, tmp, newindent)
+
+def parseCommon(data, start=0):
+    i = start + 6
+    (wLength, wValueLength, wType) = struct.unpack('3h', data[start:i])
+    #print "wLength, wValueLength, wType, i:", wLength, wValueLength, wType, i
+    i, szKey = parseUString(data, i, i+wLength)
+    #i = ((i + 3) / 4) * 4
+    #print `data[start+6:start+wLength]`
+    return i, (wLength, wValueLength, wType, szKey)
+
+def parseUString(data, start, limit):
+    i = start
+    while i < limit:
+        if data[i:i+2] == '\000\000':
+            break
+        i = i + 2
+    szKey = pywintypes.UnicodeFromRaw(data[start:i])
+    i = i + 2
+    #print "szKey:", '"'+str(szKey)+'"', "(consumed", i-start, "bytes - to", i, ")"
+    return i, szKey
+
+##VS_FIXEDFILEINFO {  // vsffi
+##    DWORD dwSignature;        //Contains the value 0xFEEFO4BD
+##    DWORD dwStrucVersion;     //Specifies the binary version number of this structure. The high-order word of this member contains the major version number, and the low-order word contains the minor version number.
+##    DWORD dwFileVersionMS;    // Specifies the most significant 32 bits of the file's binary version number
+##    DWORD dwFileVersionLS;    //
+##    DWORD dwProductVersionMS; // Specifies the most significant 32 bits of the binary version number of the product with which this file was distributed
+##    DWORD dwProductVersionLS; //
+##    DWORD dwFileFlagsMask;    // Contains a bitmask that specifies the valid bits in dwFileFlags. A bit is valid only if it was defined when the file was created.
+##    DWORD dwFileFlags;        // VS_FF_DEBUG, VS_FF_PATCHED etc.
+##    DWORD dwFileOS;           // VOS_NT, VOS_WINDOWS32 etc.
+##    DWORD dwFileType;         // VFT_APP etc.
+##    DWORD dwFileSubtype;      // 0 unless VFT_DRV or VFT_FONT or VFT_VXD
+##    DWORD dwFileDateMS;
+##    DWORD dwFileDateLS;
+##};
+
+class FixedFileInfo:
+    def __init__(self, filevers=(0, 0, 0, 0), prodvers=(0, 0, 0, 0), mask=0x3f, flags=0x0, OS=0x40004, fileType=0x1, subtype=0x0, date=(0, 0)):
+        self.sig = 0xfeef04bdL
+        self.strucVersion = 0x10000
+        self.fileVersionMS = (filevers[0] << 16) | (filevers[1] & 0xffff)
+        self.fileVersionLS = (filevers[2] << 16) | (filevers[3] & 0xffff)
+        self.productVersionMS = (prodvers[0] << 16) | (prodvers[1] & 0xffff)
+        self.productVersionLS = (prodvers[2] << 16) | (prodvers[3] & 0xffff)
+        self.fileFlagsMask = mask
+        self.fileFlags = flags
+        self.fileOS = OS
+        self.fileType = fileType
+        self.fileSubtype = subtype
+        self.fileDateMS = date[0]
+        self.fileDateLS = date[1]
+    def fromRaw(self, data, i):
+        (self.sig,
+         self.strucVersion,
+         self.fileVersionMS,
+         self.fileVersionLS,
+         self.productVersionMS,
+         self.productVersionLS,
+         self.fileFlagsMask,
+         self.fileFlags,
+         self.fileOS,
+         self.fileType,
+         self.fileSubtype,
+         self.fileDateMS,
+         self.fileDateLS) = struct.unpack('13l', data[i:i+52])
+        return i+52
+    def toRaw(self):
+        return struct.pack('L12l', self.sig,
+                             self.strucVersion,
+                             self.fileVersionMS,
+                             self.fileVersionLS,
+                             self.productVersionMS,
+                             self.productVersionLS,
+                             self.fileFlagsMask,
+                             self.fileFlags,
+                             self.fileOS,
+                             self.fileType,
+                             self.fileSubtype,
+                             self.fileDateMS,
+                             self.fileDateLS)
+    def __repr__(self, indent=''):
+        fv = (self.fileVersionMS >> 16, self.fileVersionMS & 0xffff, self.fileVersionLS >> 16, self.fileVersionLS & 0xFFFF)
+        pv = (self.productVersionMS >> 16, self.productVersionMS & 0xffff, self.productVersionLS >> 16, self.productVersionLS & 0xFFFF)
+        fd = (self.fileDateMS, self.fileDateLS)
+        tmp = ["FixedFileInfo(",
+               "filevers=%s," % (fv,),
+               "prodvers=%s," % (pv,),
+               "mask=%s," % hex(self.fileFlagsMask),
+               "flags=%s," % hex(self.fileFlags),
+               "OS=%s," % hex(self.fileOS),
+               "fileType=%s," % hex(self.fileType),
+               "subtype=%s," % hex(self.fileSubtype),
+               "date=%s" % (fd,),
+               ")"
+              ]
+        return string.join(tmp, '\n'+indent+'  ')
+
+##StringFileInfo {
+##    WORD        wLength;      // Specifies the length of the version resource
+##    WORD        wValueLength; // Specifies the length of the Value member in the current VS_VERSION_INFO structure
+##    WORD        wType;        // 1 means text, 0 means binary
+##    WCHAR       szKey[];      // Contains the Unicode string "StringFileInfo".
+##    WORD        Padding[];
+##    StringTable Children[];   // Specifies a list of zero or more String structures
+##};
+
+class StringFileInfo:
+    def __init__(self, kids=None):
+        self.name = "StringFileInfo"
+        if kids is None:
+            self.kids = []
+        else:
+            self.kids = kids
+    def fromRaw(self, sublen, vallen, name, data, i, limit):
+        self.name = name
+        while i < limit:
+            st = StringTable()
+            j = st.fromRaw(data, i, limit)
+            if TEST:
+                if data[i:j] != st.toRaw():
+                    rd = data[i:j]
+                    sd = st.toRaw()
+                    for x in range(0, len(rd), 16):
+                        rds = rd[x:x+16]
+                        sds = sd[x:x+16]
+                        if rds != sds:
+                            print "rd[%s:%s+16]: %s" % (x, x, `rds`)
+                            print "sd[%s:%s+16]: %s" % (x, x, `sds`)
+                            print
+                    print "raw: len %d, wLength %d" % (len(rd), struct.unpack('h', rd[:2])[0])
+                    print " st: len %d, wLength %d" % (len(sd), struct.unpack('h', sd[:2])[0])
+            self.kids.append(st)
+            i = j
+        return i
+    def toRaw(self):
+        if type(self.name) is STRINGTYPE:
+            self.name = pywintypes.Unicode(self.name)
+        vallen = 0
+        typ = 1
+        sublen = 6 + 2*len(self.name) + 2
+        pad = ''
+        if sublen % 4:
+            pad = '\000\000'
+        tmp = []
+        for kid in self.kids:
+            tmp.append(kid.toRaw())
+        tmp = string.join(tmp, '')
+        sublen = sublen + len(pad) + len(tmp)
+        if tmp[-2:] == '\000\000':
+            sublen = sublen - 2
+        return struct.pack('hhh', sublen, vallen, typ) + getRaw(self.name) + '\000\000' + pad + tmp
+    def __repr__(self, indent=''):
+        tmp = []
+        newindent = indent + '  '
+        for kid in self.kids:
+            tmp.append(kid.__repr__(newindent))
+        tmp = string.join(tmp, ', \n')
+        return "%sStringFileInfo(\n%s[\n%s\n%s])" % (indent, newindent, tmp, newindent)
+
+##StringTable {
+##    WORD   wLength;
+##    WORD   wValueLength;
+##    WORD   wType;
+##    WCHAR  szKey[];
+##    String Children[];    // Specifies a list of zero or more String structures.
+##};
+
+class StringTable:
+    def __init__(self, name=None, kids=None):
+        self.name = name
+        self.kids = kids
+        if name is None:
+            self.name = ''
+        if kids is None:
+            self.kids = []
+    def fromRaw(self, data, i, limit):
+        #print "Parsing StringTable"
+        i, (cpsublen, cpwValueLength, cpwType, self.name) = parseCodePage(data, i, limit) # should be code page junk
+        #i = ((i + 3) / 4) * 4
+        while i < limit:
+            ss = StringStruct()
+            j = ss.fromRaw(data, i, limit)
+            if TEST:
+                if data[i:j] != ss.toRaw():
+                    print "raw:", `data[i:j]`
+                    print " ss:", `ss.toRaw()`
+            i = j
+            self.kids.append(ss)
+            i = ((i + 3) / 4) * 4
+        return i
+    def toRaw(self):
+        if type(self.name) is STRINGTYPE:
+            self.name = pywintypes.Unicode(self.name)
+        vallen = 0
+        typ = 1
+        sublen = 6 + 2*len(self.name) + 2
+        tmp = []
+        for kid in self.kids:
+            raw = kid.toRaw()
+            if len(raw) % 4:
+                raw = raw + '\000\000'
+            tmp.append(raw)
+        tmp = string.join(tmp, '')
+        sublen = sublen + len(tmp)
+        if tmp[-2:] == '\000\000':
+            sublen = sublen - 2
+        return struct.pack('hhh', sublen, vallen, typ) + getRaw(self.name) + '\000\000' + tmp
+    def __repr__(self, indent=''):
+        tmp = []
+        newindent = indent + '  '
+        for kid in self.kids:
+            tmp.append(repr(kid))
+        tmp = string.join(tmp, ',\n%s' % newindent)
+        return "%sStringTable(\n%s'%s', \n%s[%s])" % (indent, newindent, str(self.name), newindent, tmp)
+
+##String {
+##    WORD   wLength;
+##    WORD   wValueLength;
+##    WORD   wType;
+##    WCHAR  szKey[];
+##    WORD   Padding[];
+##    String Value[];
+##};
+
+class StringStruct:
+    def __init__(self, name=None, val=None):
+        self.name = name
+        self.val = val
+        if name is None:
+            self.name = ''
+        if val is None:
+            self.val = ''
+    def fromRaw(self, data, i, limit):
+        i, (sublen, vallen, typ, self.name) = parseCommon(data, i)
+        limit = i + sublen
+        i = ((i + 3) / 4) * 4
+        i, self.val = parseUString(data, i, limit)
+        return i
+    def toRaw(self):
+        if type(self.name) is STRINGTYPE:
+            self.name = pywintypes.Unicode(self.name)
+        if type(self.val) is STRINGTYPE:
+            self.val = pywintypes.Unicode(self.val)
+        vallen = len(self.val) + 1
+        typ = 1
+        sublen = 6 + 2*len(self.name) + 2
+        pad = ''
+        if sublen % 4:
+            pad = '\000\000'
+        sublen = sublen + len(pad) + 2*vallen
+        return struct.pack('hhh', sublen, vallen, typ) + getRaw(self.name) + '\000\000' + pad + getRaw(self.val) + '\000\000'
+    def __repr__(self, indent=''):
+        if pyvers < 20:
+            return "StringStruct('%s', '%s')" % (str(self.name), str(self.val))
+        else:
+            return "StringStruct('%s', '%s')" % (self.name, self.val)
+
+def parseCodePage(data, i, limit):
+    #print "Parsing CodePage"
+    i, (sublen, wValueLength, wType, nm) = parseCommon(data, i)
+    #i = ((i + 3) / 4) * 4
+    return i, (sublen, wValueLength, wType, nm)
+
+##VarFileInfo {
+##    WORD  wLength;        // Specifies the length of the version resource
+##    WORD  wValueLength;   // Specifies the length of the Value member in the current VS_VERSION_INFO structure
+##    WORD  wType;          // 1 means text, 0 means binary
+##    WCHAR szKey[];        // Contains the Unicode string "VarFileInfo".
+##    WORD  Padding[];
+##    Var   Children[];     // Specifies a list of zero or more Var structures
+##};
+
+class VarFileInfo:
+    def __init__(self, kids=None):
+        if kids is None:
+            self.kids = []
+        else:
+            self.kids = kids
+    def fromRaw(self, sublen, vallen, name, data, i, limit):
+        self.sublen = sublen
+        self.vallen = vallen
+        self.name = name
+        i = ((i + 3) / 4) * 4
+        while i < limit:
+            vs = VarStruct()
+            j = vs.fromRaw(data, i, limit)
+            self.kids.append(vs)
+            if TEST:
+                if data[i:j] != vs.toRaw():
+                    print "raw:", `data[i:j]`
+                    print "cmp:", `vs.toRaw()`
+            i = j
+        return i
+    def toRaw(self):
+        self.vallen = 0
+        self.wType = 1
+        self.name = pywintypes.Unicode('VarFileInfo')
+        sublen = 6 + 2*len(self.name) + 2
+        pad = ''
+        if sublen % 4:
+            pad = '\000\000'
+        tmp = []
+        for kid in self.kids:
+            tmp.append(kid.toRaw())
+        tmp = string.join(tmp, '')
+        self.sublen = sublen + len(pad) + len(tmp)
+        return struct.pack('hhh', self.sublen, self.vallen, self.wType) + getRaw(self.name) + '\000\000' + pad + tmp
+    def __repr__(self, indent=''):
+        tmp = map(repr, self.kids)
+        return "%sVarFileInfo([%s])" % (indent, string.join(tmp, ', '))
+
+##Var {
+##    WORD  wLength;        // Specifies the length of the version resource
+##    WORD  wValueLength;   // Specifies the length of the Value member in the current VS_VERSION_INFO structure
+##    WORD  wType;          // 1 means text, 0 means binary
+##    WCHAR szKey[];        // Contains the Unicode string "Translation" or a user-defined key string value
+##    WORD  Padding[];      //
+##    WORD  Value[];        // Specifies a list of one or more values that are language and code-page identifiers
+##};
+
+STRINGTYPE = type('')
+
+class VarStruct:
+    def __init__(self, name=None, kids=None):
+        self.name = name
+        self.kids = kids
+        if name is None:
+            self.name = ''
+        if kids is None:
+            self.kids = []
+    def fromRaw(self, data, i, limit):
+        i, (self.sublen, self.wValueLength, self.wType, self.name) = parseCommon(data, i)
+        i = ((i + 3) / 4) * 4
+        for j in range(self.wValueLength/2):
+            kid = struct.unpack('h', data[i:i+2])[0]
+            self.kids.append(kid)
+            i = i + 2
+        return i
+    def toRaw(self):
+        self.wValueLength = len(self.kids) * 2
+        self.wType = 0
+        if type(self.name) is STRINGTYPE:
+            self.name = pywintypes.Unicode(self.name)
+        sublen = 6 + 2*len(self.name) + 2
+        pad = ''
+        if sublen % 4:
+            pad = '\000\000'
+        self.sublen = sublen + len(pad) + self.wValueLength
+        tmp = []
+        for kid in self.kids:
+            tmp.append(struct.pack('h', kid))
+        tmp = string.join(tmp, '')
+        return struct.pack('hhh', self.sublen, self.wValueLength, self.wType) + getRaw(self.name) + '\000\000' + pad + tmp
+    def __repr__(self, indent=''):
+        return "VarStruct('%s', %s)" % (str(self.name), repr(self.kids))
+
+def SetVersion(exenm, versionfile):
+    txt = open(versionfile, 'r').read()
+    vs = eval(txt+'\n', globals())
+    hdst = win32api.BeginUpdateResource(exenm, 0)
+    win32api.UpdateResource(hdst, RT_VERSION, 1, vs.toRaw())
+    win32api.EndUpdateResource (hdst, 0)
+
+if __name__ == '__main__':
+    import sys
+    TEST = 1
+    if len(sys.argv) < 2:
+        decode('c:/Program Files/Netscape/Communicator/Program/netscape.exe')
+    else:
+        print "Examining", sys.argv[1]
+        decode(sys.argv[1])
+