• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Beakerboy / vbaProject-Compiler / 3971781390

pending completion
3971781390

Pull #41

github

GitHub
Merge 9f8c76a97 into dc30fdb61
Pull Request #41: Update dirStream.py

28 of 28 new or added lines in 1 file covered. (100.0%)

416 of 480 relevant lines covered (86.67%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.86
/vbaProjectCompiler/Directories/dirStream.py
1
import struct
1✔
2
from vbaProjectCompiler.Directories.streamDirectory import StreamDirectory
1✔
3

4
class DirStream(StreamDirectory):
1✔
5
    """
6
    The dir stream is compressed on write
7
    """
8

9
    def __init__(self):
1✔
10
        self.codePage = 0x04E4
1✔
11
        codePageName = "cp" + str(self.codePage)
1✔
12
        syskind = SimpleRecord(1, 4, 3) #0=16bit, 1=32bit, 2=mac, 3=64bit
1✔
13
        compatVersion = SimpleRecord(74, 4, 3)
1✔
14
        lcid = SimpleRecord(2, 4, 0x0409)
1✔
15
        lcidInvoke = SimpleRecord(20, 4, 0x0409)
1✔
16
        codePageRecord = SimpleRecord(3, 2, self.codePage)
1✔
17
        projectName = SimpleRecord(4, 10, "VBAProject")
1✔
18
        
19
        docString1 = SimpleRecord(5, 0, "")       #multibute string
1✔
20
        docString2 = SimpleRecord(0x0040, 0, "")  #UTF-16
1✔
21

22
        helpfile1 = SimpleRecord(6, 0, "")
1✔
23
        helpfile2 = SimpleRecord(0x003D, 0, "")
1✔
24
        helpContext = SimpleRecord(7, 4, 0)
1✔
25
        libFlags = SimpleRecord(8, 4, 0)
1✔
26
        version = SimpleRecord(9, 4, 0x65BE0257)
1✔
27
        minorVersion = SimpleValue(2, 17)
1✔
28
        constants1 = SimpleRecord(12, 0, "")
1✔
29
        constants2 = SimpleRecord(0x003C, 0, "")
1✔
30
        self.information = [
1✔
31
            syskind,
32
            compatVersion,
33
            lcid,
34
            lcidInvoke,
35
            codePageRecord,
36
            projectName,
37
            docString1,
38
            docString2,
39
            helpfile1,
40
            helpfile2,
41
            helpContext,
42
            libFlags,
43
            version,
44
            minorVersion,
45
            constants1,
46
            constants2
47
        ]
48
        libidRef = LibidReference(
1✔
49
            "windows",
50
            "{00020430-0000-0000-C000-000000000046}",
51
            "2.0",
52
            "0",
53
            "C:\\Windows\\System32\\stdole2.tlb",
54
            "OLE Automation"
55
        )
56
        oleReference = ReferenceRecord(codePageName, "stdole", libidRef)
1✔
57
        libidRef2 = LibidReference(
1✔
58
            "windows",
59
            "{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}",
60
            "2.0",
61
            "0",
62
            "C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE16\\MSO.DLL",
63
            "Microsoft Office 16.0 Object Library"
64
        )
65
        officeReference = ReferenceRecord(codePageName, "Office", libidRef2)
1✔
66
        self.references  = [
1✔
67
            oleReference,
68
            officeReference
69
        ]
70
        cookie = SimpleRecord(19, 2, 0x08F3) #should be 0xFFFF
1✔
71
        count = 3
1✔
72
        modulesHeader = SimpleRecord(0x000F, 2, count)
1✔
73
        thisWorkbook = ModuleRecord(codePageName, "ThisWorkbook", "ThisWorkbook", "", 0x0333, 0, 0xB81C, 0x0022)
1✔
74
        self.modules = []
1✔
75

76

77

78
    def toBytes(self):
1✔
79
        output = b''
1✔
80
        for record in self.information:
1✔
81
            output += record.pack()
1✔
82
        for record in self.references:
1✔
83
            output += record.pack()
1✔
84
        return output
1✔
85

86
class SimpleRecord():
1✔
87
    """
88
    Many Records in this class have the same format, a two bye ID, a four byte size and an int value formatted to the defined si
89
    """
90

91
    def __init__(self, id, size, value):
1✔
92
        self.id = id
1✔
93
        self.size = size
1✔
94
        self.value = value
1✔
95

96
    def toDict(self):
1✔
97
        return {"id": self.id, "size": self.size, "value": self.value}
×
98

99
    def pack(self):
1✔
100
        format = "<HI"
1✔
101
        if isinstance(self.value, str):
1✔
102
            self.stringValue = self.value
1✔
103
            self.value = bytes(self.value, encoding = "ascii")
1✔
104
            format += str(self.size) + "s"
1✔
105
        elif isinstance(self.value, bytes):
1✔
106
            format += str(self.size) + "s"
1✔
107
        elif self.size == 2:
1✔
108
            format += "H"
1✔
109
        elif self.size == 4:
1✔
110
            format += "I"
1✔
111
        else:
112
            raise Exception("Received data of type " + type(self.value).__name__)
×
113
        output = struct.pack(format, self.id, self.size, self.value)
1✔
114
        #clean up stringValue
115
        return output
1✔
116

117
class SimpleValue():
1✔
118
    def __init__(self, size, value):
1✔
119
        self.size = size
1✔
120
        self.value = value
1✔
121

122
    def pack(self):
1✔
123
        format = "<"
1✔
124
        if self.size == 2:
1✔
125
            format += "H"
1✔
126
        elif self.size == 4:
×
127
            format += "I"
×
128
        output = struct.pack(format, self.value)
1✔
129
        return output
1✔
130

131
class PackedRecord():
1✔
132
    """
133
    A Record that is already packed
134
    """
135
    def __init__(self, value):
1✔
136
        self.value = value
1✔
137

138
    def pack(self):
1✔
139
        return self.value
1✔
140

141
class LibidReference():
1✔
142
    def __init__(self, pathType, libidGuid, version, libidLcid, libidPath, libidRegName):
1✔
143
        self.LibidReferenceKind = "G" if pathType == "windows" else "H"
1✔
144
        self.libidGuid = libidGuid
1✔
145
        self.version = version
1✔
146
        self.libidLcid = libidLcid
1✔
147
        self.libidPath = libidPath
1✔
148
        self.libidRegName = libidRegName
1✔
149

150
    def toString(self):
1✔
151
        return "*\\" + \
1✔
152
            self.LibidReferenceKind + \
153
            self.libidGuid + "#" + \
154
            self.version + "#" + \
155
            self.libidLcid + "#" + \
156
            self.libidPath + "#" + \
157
            self.libidRegName
158

159
class ReferenceRecord():
1✔
160
    def __init__(self, codePageName, name, libidRef):
1✔
161
        self.codePageName = codePageName
1✔
162
        encoded = name.encode(codePageName)
1✔
163
        self.RefName1 = SimpleRecord(0x0016, len(encoded), encoded)
1✔
164
        encoded = name.encode("utf_16_le")
1✔
165
        self.RefName2 = SimpleRecord(0x003E, len(encoded), encoded)
1✔
166
        self.libidRef = libidRef
1✔
167

168
    def pack(self):
1✔
169
        strlen = len(self.libidRef.toString())
1✔
170
        format = "<HII" + str(strlen) + "sIH"
1✔
171
        refRegistered = PackedRecord(struct.pack(format, 0x000D, strlen + 10, strlen, self.libidRef.toString().encode(self.codePageName), 0, 0))
1✔
172
       
173
        return self.RefName1.pack() + self.RefName2.pack() + refRegistered.pack()
1✔
174

175
class DoubleEncodedSimple():
1✔
176
    def __init__(self, codePageName, ids, text):
1✔
177
        self.codePageName = codePageName
1✔
178
        encoded = text.encode(codePageName)
1✔
179
        self.modName1 = SimpleRecord(ids[0], len(encoded), encoded)
1✔
180
        encoded = text.encode("utf_16_le")
1✔
181
        self.modName2 = SimpleRecord(ids[1], len(encoded), encoded)
1✔
182

183
    def pack(self):
1✔
184
        return self.modName1.pack() + self.modName2.pack()
×
185

186

187
class ModuleRecord():
1✔
188
    def __init__(self, codePageName, name, streamName, docString, offset, helpContext, cookie, type, readonly=False, private=False):
1✔
189
        self.codePageName = codePageName
1✔
190
        self.modName      = DoubleEncodedSimple(codePageName, [0x0019, 0x003E], name)
1✔
191
        self.streamName   = DoubleEncodedSimple(codePageName, [0x001A, 0x0032], streamName)
1✔
192
        self.docString    = DoubleEncodedSimple(codePageName, [0x001C, 0x0048], docString)
1✔
193
        self.offsetRec    = SimpleRecord(0x0031, 4, offset)
1✔
194
        self.helpContext  = SimpleRecord(0x001E, 4, helpContext)
1✔
195
        self.cookie       = SimpleRecord(0x002C, 2, helpContext)
1✔
196
        self.type         = PackedRecord(struct.pack("<HHI", type, 0, 0))
1✔
197
        #self.readonly = SimpleRecord(0x001E, 4, helpContext)
198
        #self.private = SimpleRecord(0x001E, 4, helpContext)
199
       
200
    def pack(self):
1✔
201
        output = self.codePageName.pack() + self.modName.pack() + self.streamName.pack() + self.docString.pack() + self.offsetRec.pack() + self.helpContext.pack() + self.cookie.pack() + self.type.pack()
×
202
        footer = struct.pack("<HI", 0x002B, 0)
×
203
        output += footer
×
204
        return output
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc