From 1b755a05ea516cc0158cf94fd812e336cd323d7c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:06:38 -0400 Subject: [PATCH 001/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 57 ++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 8d8490736..eaa4669bb 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -93,3 +93,60 @@ def _load_information(self: T) -> List: constants ]) return information + +@staticmethod + def is_valid(data: bytes) -> bool: + """ + Static validation: Checks if bytes follow the DirStream structure. + Expects decompressed bytes. + """ + try: + offset = 0 + + # 1. Check PROJECTSYSKIND (Mandatory first record) + # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) + record_id, size = struct.unpack_from(" bool: + """Helper to validate a compressed .bin file on disk.""" + try: + with open(file_path, "rb") as f: + compressed = f.read() + from ms_ovba_compression.ms_ovba import MsOvba + decompressed = MsOvba().decompress(compressed) + return DirStream.is_valid(decompressed) + except Exception: + return False From 7ea7b17d1507a413ff3e825b796d24dfdcbea3e2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:18:29 -0400 Subject: [PATCH 002/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index eaa4669bb..58ae9afa4 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -150,3 +150,55 @@ def is_file_valid(file_path: str) -> bool: return DirStream.is_valid(decompressed) except Exception: return False + +@staticmethod + def from_bytes(data: bytes, endien: str = 'little') -> dict: + """ + Parses decompressed bytes and extracts project metadata. + Returns a dict of attributes for VbaProject. + """ + offset = 0 + pack_symbol = '<' if endien == 'little' else '>' + + # State to return + project_data = { + "references": [], + "modules": [], + "help_context_id": 0, + "project_cookie": 0, + "codepage_name": "cp1252" # Default + } + + while offset < len(data): + # 1. Read Record ID (2 bytes) + record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] + + # 2. Check for Terminator (ID 16) + if record_id == 16: + break + + # 3. Read Size (4 bytes) + size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] + record_data = data[offset + 6 : offset + 6 + size] + + # 4. Map IDs to VbaProject attributes + # Reference MS-OVBA Section 2.3.4.2 + if record_id == 0x0003: # PROJECTCODEPAGE + # Map code page to name if necessary + cp_val = struct.unpack(pack_symbol + "H", record_data)[0] + project_data["codepage_name"] = f"cp{cp_val}" + + elif record_id == 0x0007: # PROJECTHELPCONTEXT + project_data["help_context_id"] = struct.unpack(pack_symbol + "I", record_data)[0] + + elif record_id == 0x0013: # PROJECTCOOKIE + project_data["project_cookie"] = struct.unpack(pack_symbol + "H", record_data)[0] + + # Record parsing for References/Modules would go here + # e.g., if record_id in [0x0016, 0x0033]: append to references + # e.g., if record_id == 0x0019: append to modules + + # Move to next record + offset += 6 + size + + return project_data From 2cca6e9c15fc89487bb798f9bc04bca7eb412443 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:21:15 -0400 Subject: [PATCH 003/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 58ae9afa4..10c3ebeda 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -94,7 +94,7 @@ def _load_information(self: T) -> List: ]) return information -@staticmethod + @staticmethod def is_valid(data: bytes) -> bool: """ Static validation: Checks if bytes follow the DirStream structure. From cbd955503ddf824f515eb23458c5846dc968bfea Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:21:52 -0400 Subject: [PATCH 004/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 10c3ebeda..b9c19c9fe 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -151,7 +151,7 @@ def is_file_valid(file_path: str) -> bool: except Exception: return False -@staticmethod + @staticmethod def from_bytes(data: bytes, endien: str = 'little') -> dict: """ Parses decompressed bytes and extracts project metadata. From ad88e1f1359c75c6129b2c80a100f50798ecd032 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:24:20 -0400 Subject: [PATCH 005/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index b9c19c9fe..384688fac 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -102,7 +102,7 @@ def is_valid(data: bytes) -> bool: """ try: offset = 0 - + # 1. Check PROJECTSYSKIND (Mandatory first record) # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) record_id, size = struct.unpack_from(" bool: # 2. Skip through variable Information/Reference records # Real validation would loop through known IDs (1-12, 16, 17, etc.) # For brevity, we verify the specific 'Terminator' at the end. - + # 3. Check for the Modules Header and Project Cookie # These appear after references but before the modules list # to_bytes() uses: IdSizeField(0x000F, 2, len(modules)) @@ -125,8 +125,8 @@ def is_valid(data: bytes) -> bool: found_modules_header = True break # Jump by standard Record header (ID + Size) or typical lengths - offset += 2 - + offset += 2 + if not found_modules_header: return False @@ -159,7 +159,7 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: """ offset = 0 pack_symbol = '<' if endien == 'little' else '>' - + # State to return project_data = { "references": [], @@ -172,33 +172,33 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: while offset < len(data): # 1. Read Record ID (2 bytes) record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - + # 2. Check for Terminator (ID 16) if record_id == 16: break - + # 3. Read Size (4 bytes) size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] record_data = data[offset + 6 : offset + 6 + size] - + # 4. Map IDs to VbaProject attributes # Reference MS-OVBA Section 2.3.4.2 if record_id == 0x0003: # PROJECTCODEPAGE # Map code page to name if necessary cp_val = struct.unpack(pack_symbol + "H", record_data)[0] project_data["codepage_name"] = f"cp{cp_val}" - + elif record_id == 0x0007: # PROJECTHELPCONTEXT project_data["help_context_id"] = struct.unpack(pack_symbol + "I", record_data)[0] - + elif record_id == 0x0013: # PROJECTCOOKIE project_data["project_cookie"] = struct.unpack(pack_symbol + "H", record_data)[0] - + # Record parsing for References/Modules would go here # e.g., if record_id in [0x0016, 0x0033]: append to references # e.g., if record_id == 0x0019: append to modules # Move to next record offset += 6 + size - + return project_data From 3b03231dc78b055e2bb43e72aa4e2f8ae6f644b0 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:30:30 -0400 Subject: [PATCH 006/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 384688fac..033131a4f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -102,7 +102,7 @@ def is_valid(data: bytes) -> bool: """ try: offset = 0 - + # 1. Check PROJECTSYSKIND (Mandatory first record) # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) record_id, size = struct.unpack_from(" bool: # 2. Skip through variable Information/Reference records # Real validation would loop through known IDs (1-12, 16, 17, etc.) # For brevity, we verify the specific 'Terminator' at the end. - + # 3. Check for the Modules Header and Project Cookie # These appear after references but before the modules list # to_bytes() uses: IdSizeField(0x000F, 2, len(modules)) @@ -126,7 +126,7 @@ def is_valid(data: bytes) -> bool: break # Jump by standard Record header (ID + Size) or typical lengths offset += 2 - + if not found_modules_header: return False @@ -166,39 +166,39 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: "modules": [], "help_context_id": 0, "project_cookie": 0, - "codepage_name": "cp1252" # Default + "codepage_name": "cp1252" # Default } while offset < len(data): # 1. Read Record ID (2 bytes) record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - + # 2. Check for Terminator (ID 16) if record_id == 16: break - + # 3. Read Size (4 bytes) size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] record_data = data[offset + 6 : offset + 6 + size] - + # 4. Map IDs to VbaProject attributes # Reference MS-OVBA Section 2.3.4.2 if record_id == 0x0003: # PROJECTCODEPAGE # Map code page to name if necessary cp_val = struct.unpack(pack_symbol + "H", record_data)[0] project_data["codepage_name"] = f"cp{cp_val}" - + elif record_id == 0x0007: # PROJECTHELPCONTEXT project_data["help_context_id"] = struct.unpack(pack_symbol + "I", record_data)[0] - + elif record_id == 0x0013: # PROJECTCOOKIE project_data["project_cookie"] = struct.unpack(pack_symbol + "H", record_data)[0] - + # Record parsing for References/Modules would go here # e.g., if record_id in [0x0016, 0x0033]: append to references # e.g., if record_id == 0x0019: append to modules # Move to next record offset += 6 + size - + return project_data From 9ed06adcb4d22bc520bb19eecafa139f4e5b5af4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:32:44 -0400 Subject: [PATCH 007/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 033131a4f..f82bc0b6f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -179,11 +179,11 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: # 3. Read Size (4 bytes) size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - record_data = data[offset + 6 : offset + 6 + size] + record_data = data[offset + 6:offset + 6 + size] # 4. Map IDs to VbaProject attributes # Reference MS-OVBA Section 2.3.4.2 - if record_id == 0x0003: # PROJECTCODEPAGE + if record_id == 0x0003: # PROJECTCODEPAGE # Map code page to name if necessary cp_val = struct.unpack(pack_symbol + "H", record_data)[0] project_data["codepage_name"] = f"cp{cp_val}" From 48836a07c41707cb38cb73d26a52de8ebfc5dcd1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:34:05 -0400 Subject: [PATCH 008/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index f82bc0b6f..e7baef53b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -188,10 +188,10 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: cp_val = struct.unpack(pack_symbol + "H", record_data)[0] project_data["codepage_name"] = f"cp{cp_val}" - elif record_id == 0x0007: # PROJECTHELPCONTEXT + elif record_id == 0x0007: # PROJECTHELPCONTEXT project_data["help_context_id"] = struct.unpack(pack_symbol + "I", record_data)[0] - elif record_id == 0x0013: # PROJECTCOOKIE + elif record_id == 0x0013: # PROJECTCOOKIE project_data["project_cookie"] = struct.unpack(pack_symbol + "H", record_data)[0] # Record parsing for References/Modules would go here From e0cc3fcfa1dabb4f681ea9ce2b9d5be7b4b5600f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 11:38:52 -0400 Subject: [PATCH 009/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index e7baef53b..a8dda2c2f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -189,10 +189,14 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: project_data["codepage_name"] = f"cp{cp_val}" elif record_id == 0x0007: # PROJECTHELPCONTEXT - project_data["help_context_id"] = struct.unpack(pack_symbol + "I", record_data)[0] + project_data["help_context_id"] = ( + struct.unpack(pack_symbol + "I", record_data)[0] + ) elif record_id == 0x0013: # PROJECTCOOKIE - project_data["project_cookie"] = struct.unpack(pack_symbol + "H", record_data)[0] + project_data["project_cookie"] = ( + struct.unpack(pack_symbol + "H", record_data)[0] + ) # Record parsing for References/Modules would go here # e.g., if record_id in [0x0016, 0x0033]: append to references From e67157ebccffb39c794824f21ee0164ec02ccc13 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 12:30:19 -0400 Subject: [PATCH 010/115] Create test_dir.py --- tests/Unit/Views/test_dir.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/Unit/Views/test_dir.py diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py new file mode 100644 index 000000000..99243ba26 --- /dev/null +++ b/tests/Unit/Views/test_dir.py @@ -0,0 +1,11 @@ +from ms_ovba.Views.dirStream import DirStream +from typing import TypeVar +from unittest import mock + + +mock_vbaproject = mock.Mock() + + +def test_construct() -> None: + dir = DirStream(mock_vbaproject) + assert isinstance(dir, DirStream) From 24f15be266879a8890692a19b91d25d1b2df3700 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 13:58:06 -0400 Subject: [PATCH 011/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 99243ba26..967b50d2b 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -1,5 +1,4 @@ from ms_ovba.Views.dirStream import DirStream -from typing import TypeVar from unittest import mock From 8d9c0aea27f382e33c619a9c3431341a3130a096 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:27:08 -0400 Subject: [PATCH 012/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 967b50d2b..3e67be25a 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -1,4 +1,6 @@ +from ms_cfb.ole_file import OleFile from ms_ovba.Views.dirStream import DirStream +from ms_ovba_compression.ms_ovba import MsOvba from unittest import mock @@ -8,3 +10,17 @@ def test_construct() -> None: dir = DirStream(mock_vbaproject) assert isinstance(dir, DirStream) + + +def test_is_valid() -> None: + file = "test/blank/vbaProject.bin" + ole_file = OleFile.create_from_file(file) + ole_file.extract_stream('dir', 'test/blank/') + with open('test/blank/dir.bin', 'rb' as f: + compressed_data = f.read() + + # Use MsOvba to decompress the stream + ms_ovba = MsOvba() + decompressed_data = ms_ovba.decompress(compressed_data) + assert DirStream.is_valid(f) + From d2c46946f968805e768272b029aaa111187923bd Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:28:46 -0400 Subject: [PATCH 013/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 3e67be25a..fa6c32a52 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -16,7 +16,7 @@ def test_is_valid() -> None: file = "test/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) ole_file.extract_stream('dir', 'test/blank/') - with open('test/blank/dir.bin', 'rb' as f: + with open('test/blank/dir.bin', 'rb') as f: compressed_data = f.read() # Use MsOvba to decompress the stream From 4e4fc3eaf172dce029147cdf9900ea5c30d69e5d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:38:10 -0400 Subject: [PATCH 014/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index fa6c32a52..81da40e3f 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -22,5 +22,5 @@ def test_is_valid() -> None: # Use MsOvba to decompress the stream ms_ovba = MsOvba() decompressed_data = ms_ovba.decompress(compressed_data) - assert DirStream.is_valid(f) + assert DirStream.is_valid(decompressed_data) From bd2b3eff23187c94e629f6c903873954ee91656f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:44:49 -0400 Subject: [PATCH 015/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 81da40e3f..d5035fdb1 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -23,4 +23,3 @@ def test_is_valid() -> None: ms_ovba = MsOvba() decompressed_data = ms_ovba.decompress(compressed_data) assert DirStream.is_valid(decompressed_data) - From ad7ab1d866db32b5aeffe9bc5b8b020a7740613b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:46:26 -0400 Subject: [PATCH 016/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index d5035fdb1..c777701ff 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -13,10 +13,10 @@ def test_construct() -> None: def test_is_valid() -> None: - file = "test/blank/vbaProject.bin" + file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) ole_file.extract_stream('dir', 'test/blank/') - with open('test/blank/dir.bin', 'rb') as f: + with open('tests/blank/dir.bin', 'rb') as f: compressed_data = f.read() # Use MsOvba to decompress the stream From e69c868abd9bb708fb3b2bd5c345663fa4885c13 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:48:37 -0400 Subject: [PATCH 017/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index c777701ff..a11ec207f 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -15,7 +15,7 @@ def test_construct() -> None: def test_is_valid() -> None: file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) - ole_file.extract_stream('dir', 'test/blank/') + ole_file.extract_stream('dir', 'test/blank') with open('tests/blank/dir.bin', 'rb') as f: compressed_data = f.read() From 3322f3091c192968702134a4581ad0f4679fbecc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 14:56:55 -0400 Subject: [PATCH 018/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index a11ec207f..933943104 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -15,7 +15,7 @@ def test_construct() -> None: def test_is_valid() -> None: file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) - ole_file.extract_stream('dir', 'test/blank') + ole_file.extract_stream('dir', 'tests/blank') with open('tests/blank/dir.bin', 'rb') as f: compressed_data = f.read() From 086a63c3b3fd27c3d3b69298f91d7f0cff6fec5f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 15:11:46 -0400 Subject: [PATCH 019/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 79 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index a8dda2c2f..1f7c12524 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -153,56 +153,57 @@ def is_file_valid(file_path: str) -> bool: @staticmethod def from_bytes(data: bytes, endien: str = 'little') -> dict: - """ - Parses decompressed bytes and extracts project metadata. - Returns a dict of attributes for VbaProject. - """ offset = 0 pack_symbol = '<' if endien == 'little' else '>' - - # State to return + project_data = { "references": [], "modules": [], "help_context_id": 0, "project_cookie": 0, - "codepage_name": "cp1252" # Default + "codepage_name": "cp1252" } while offset < len(data): - # 1. Read Record ID (2 bytes) record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - - # 2. Check for Terminator (ID 16) - if record_id == 16: - break - - # 3. Read Size (4 bytes) + + # --- REFERENCES SECTION --- + # Using your factory for IDs: 0x000D, 0x000E, 0x002F, 0x0033 + if record_id in [0x000D, 0x000E, 0x002F, 0x0033]: + # We need to know how many bytes to send to ReferenceRecord.unpack + size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] + total_len = 6 + size + + # Extract specific slice for the factory + ref_bytes = data[offset : offset + total_len] + project_data["references"].append(ReferenceRecord.unpack(ref_bytes, endien)) + + offset += total_len + continue + + # --- MODULES HEADER & COOKIE --- + if record_id == 0x000F: + offset += 6 # Skip ID/Size of the 0x000F record + # Peek for the Cookie (0x0013) which follows immediately + cookie_id, c_size, cookie = struct.unpack_from(pack_symbol + "H I H", data, offset) + project_data["project_cookie"] = cookie + offset += 8 # Skip ID/Size/Value of 0x0013 + continue + + # --- MODULES SECTION (0x0019) --- + if record_id == 0x0019: + module_obj, new_offset = DirStream._parse_module_group(data, offset, endien) + project_data["modules"].append(module_obj) + offset = new_offset + continue + + # --- INFORMATION RECORDS --- + if record_id == 0x0010: break # Terminator + size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - record_data = data[offset + 6:offset + 6 + size] - - # 4. Map IDs to VbaProject attributes - # Reference MS-OVBA Section 2.3.4.2 - if record_id == 0x0003: # PROJECTCODEPAGE - # Map code page to name if necessary - cp_val = struct.unpack(pack_symbol + "H", record_data)[0] - project_data["codepage_name"] = f"cp{cp_val}" - - elif record_id == 0x0007: # PROJECTHELPCONTEXT - project_data["help_context_id"] = ( - struct.unpack(pack_symbol + "I", record_data)[0] - ) - - elif record_id == 0x0013: # PROJECTCOOKIE - project_data["project_cookie"] = ( - struct.unpack(pack_symbol + "H", record_data)[0] - ) - - # Record parsing for References/Modules would go here - # e.g., if record_id in [0x0016, 0x0033]: append to references - # e.g., if record_id == 0x0019: append to modules - - # Move to next record + if record_id == 0x0007: # HELPCONTEXT + project_data["help_context_id"] = struct.unpack_from(pack_symbol + "I", data, offset + 6)[0] + offset += 6 + size - + return project_data From 13f38264a943965f6eb9776776d25898acbb6204 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 15:16:35 -0400 Subject: [PATCH 020/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 1f7c12524..13bd4512e 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -155,7 +155,7 @@ def is_file_valid(file_path: str) -> bool: def from_bytes(data: bytes, endien: str = 'little') -> dict: offset = 0 pack_symbol = '<' if endien == 'little' else '>' - + project_data = { "references": [], "modules": [], @@ -166,18 +166,18 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: while offset < len(data): record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - + # --- REFERENCES SECTION --- # Using your factory for IDs: 0x000D, 0x000E, 0x002F, 0x0033 if record_id in [0x000D, 0x000E, 0x002F, 0x0033]: # We need to know how many bytes to send to ReferenceRecord.unpack size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] total_len = 6 + size - + # Extract specific slice for the factory ref_bytes = data[offset : offset + total_len] project_data["references"].append(ReferenceRecord.unpack(ref_bytes, endien)) - + offset += total_len continue @@ -199,11 +199,11 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: # --- INFORMATION RECORDS --- if record_id == 0x0010: break # Terminator - + size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] if record_id == 0x0007: # HELPCONTEXT project_data["help_context_id"] = struct.unpack_from(pack_symbol + "I", data, offset + 6)[0] - + offset += 6 + size - + return project_data From c479cdce0e4d3273388bedab8a86e3c9934315b9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 16:37:34 -0400 Subject: [PATCH 021/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 13bd4512e..2761b6b08 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -170,8 +170,11 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: # --- REFERENCES SECTION --- # Using your factory for IDs: 0x000D, 0x000E, 0x002F, 0x0033 if record_id in [0x000D, 0x000E, 0x002F, 0x0033]: - # We need to know how many bytes to send to ReferenceRecord.unpack - size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] + # We need to know how many bytes to send to + # ReferenceRecord.unpack + size = ( + struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] + ) total_len = 6 + size # Extract specific slice for the factory From 557634c4107e1e8715c2d3c9215b95aa1be447c3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 16:38:37 -0400 Subject: [PATCH 022/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 2761b6b08..41418b243 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -178,8 +178,10 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: total_len = 6 + size # Extract specific slice for the factory - ref_bytes = data[offset : offset + total_len] - project_data["references"].append(ReferenceRecord.unpack(ref_bytes, endien)) + ref_bytes = data[offset:offset + total_len] + project_data["references"].append( + ReferenceRecord.unpack(ref_bytes, endien) + ) offset += total_len continue From 2c05d14db24e43f4c2af3759a22ea21bc6d0605d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 16:40:21 -0400 Subject: [PATCH 023/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 41418b243..99dd5a4a2 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -188,11 +188,13 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: # --- MODULES HEADER & COOKIE --- if record_id == 0x000F: - offset += 6 # Skip ID/Size of the 0x000F record + offset += 6 # Skip ID/Size of the 0x000F record # Peek for the Cookie (0x0013) which follows immediately - cookie_id, c_size, cookie = struct.unpack_from(pack_symbol + "H I H", data, offset) + cookie_id, c_size, cookie = ( + struct.unpack_from(pack_symbol + "H I H", data, offset) + ) project_data["project_cookie"] = cookie - offset += 8 # Skip ID/Size/Value of 0x0013 + offset += 8 # Skip ID/Size/Value of 0x0013 continue # --- MODULES SECTION (0x0019) --- @@ -206,8 +208,10 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: if record_id == 0x0010: break # Terminator size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - if record_id == 0x0007: # HELPCONTEXT - project_data["help_context_id"] = struct.unpack_from(pack_symbol + "I", data, offset + 6)[0] + if record_id == 0x0007: # HELPCONTEXT + project_data["help_context_id"] = ( + struct.unpack_from(pack_symbol + "I", data, offset + 6)[0] + ) offset += 6 + size From 6f757145f78d08b3befe35e2158658f34427f901 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 16:48:57 -0400 Subject: [PATCH 024/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 99dd5a4a2..dc102de88 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -199,13 +199,16 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: # --- MODULES SECTION (0x0019) --- if record_id == 0x0019: - module_obj, new_offset = DirStream._parse_module_group(data, offset, endien) + module_obj, new_offset = ( + DirStream._parse_module_group(data, offset, endien) + ) project_data["modules"].append(module_obj) offset = new_offset continue # --- INFORMATION RECORDS --- - if record_id == 0x0010: break # Terminator + if record_id == 0x0010: + break # Terminator size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] if record_id == 0x0007: # HELPCONTEXT @@ -216,3 +219,28 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: offset += 6 + size return project_data + + @staticmethod + def _parse_reference_group(data, offset, pack_symbol): + """Consumes records until the end of a single Reference definition.""" + # A Reference is a cluster of records (Name, Libid, etc.) + # Logic: Consume the first record, then peek for optional sub-records + # like REFERENCECONTROL (0x002F) or Ref-Original (0x0033) + start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] + size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] + # In a real impl, you'd wrap this data into a Reference Model object + record_content = data[offset : offset + 6 + size] + return record_content, offset + 6 + size + + @staticmethod + def _parse_module_group(data, offset, pack_symbol): + """Consumes all records for one Module until the 0x002B terminator.""" + module_bytes = b'' + while offset < len(data): + r_id, size = struct.unpack_from(pack_symbol + "H I", data, offset) + record_total_len = 6 + size + module_bytes += data[offset : offset + record_total_len] + offset += record_total_len + if r_id == 0x002B: # MODULE Terminator + break + return module_bytes, offset From eb2df34c270d6edf0cb7f4a23d0a527d8678a3d4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 16:52:40 -0400 Subject: [PATCH 025/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index dc102de88..016b12298 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -221,7 +221,7 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: return project_data @staticmethod - def _parse_reference_group(data, offset, pack_symbol): + def _parse_reference_group(data: bytes, offset: int, pack_symbol: str): """Consumes records until the end of a single Reference definition.""" # A Reference is a cluster of records (Name, Libid, etc.) # Logic: Consume the first record, then peek for optional sub-records @@ -233,7 +233,7 @@ def _parse_reference_group(data, offset, pack_symbol): return record_content, offset + 6 + size @staticmethod - def _parse_module_group(data, offset, pack_symbol): + def _parse_module_group(data: bytes, offset: int, pack_symbol: str): """Consumes all records for one Module until the 0x002B terminator.""" module_bytes = b'' while offset < len(data): @@ -241,6 +241,6 @@ def _parse_module_group(data, offset, pack_symbol): record_total_len = 6 + size module_bytes += data[offset : offset + record_total_len] offset += record_total_len - if r_id == 0x002B: # MODULE Terminator + if r_id == 0x002B: # MODULE Terminator break return module_bytes, offset From 916c7253bdeb90323e0b0f33133bd334fb110850 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 17:03:17 -0400 Subject: [PATCH 026/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 016b12298..d0e7e9877 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -1,6 +1,7 @@ import struct from ms_ovba_compression.ms_ovba import MsOvba from ms_ovba.vbaProject import VbaProject +from ms_ovba.Models.Entities.reference_record import ReferenceRecord from ms_ovba.Models.Fields.idSizeField import IdSizeField from ms_ovba.Models.Fields.doubleEncodedString import ( DoubleEncodedString From 2f27b59c6a8e796f08c08d511013d1d1c93e64b5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 17:32:31 -0400 Subject: [PATCH 027/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index d0e7e9877..70ee0ad82 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -222,10 +222,10 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: return project_data @staticmethod - def _parse_reference_group(data: bytes, offset: int, pack_symbol: str): + def _parse_reference_group(data: bytes, offset: int, pack_symbol: str) -> tuple[bytes, int]: """Consumes records until the end of a single Reference definition.""" # A Reference is a cluster of records (Name, Libid, etc.) - # Logic: Consume the first record, then peek for optional sub-records + # Logic: Consume the first record, then peek for optional sub-records # like REFERENCECONTROL (0x002F) or Ref-Original (0x0033) start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] @@ -234,13 +234,13 @@ def _parse_reference_group(data: bytes, offset: int, pack_symbol: str): return record_content, offset + 6 + size @staticmethod - def _parse_module_group(data: bytes, offset: int, pack_symbol: str): + def _parse_module_group(data: bytes, offset: int, pack_symbol: str) -> tuple[bytes, int]: """Consumes all records for one Module until the 0x002B terminator.""" module_bytes = b'' while offset < len(data): r_id, size = struct.unpack_from(pack_symbol + "H I", data, offset) record_total_len = 6 + size - module_bytes += data[offset : offset + record_total_len] + module_bytes += data[offset:offset + record_total_len] offset += record_total_len if r_id == 0x002B: # MODULE Terminator break From 0caf0bf4acd9f61ef21a22e229dd06633e05c885 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 17:38:11 -0400 Subject: [PATCH 028/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 70ee0ad82..01c94cbf7 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -222,7 +222,8 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: return project_data @staticmethod - def _parse_reference_group(data: bytes, offset: int, pack_symbol: str) -> tuple[bytes, int]: + def _parse_reference_group(data: bytes, offset: int, + pack_symbol: str) -> tuple[bytes, int]: """Consumes records until the end of a single Reference definition.""" # A Reference is a cluster of records (Name, Libid, etc.) # Logic: Consume the first record, then peek for optional sub-records @@ -234,7 +235,8 @@ def _parse_reference_group(data: bytes, offset: int, pack_symbol: str) -> tuple[ return record_content, offset + 6 + size @staticmethod - def _parse_module_group(data: bytes, offset: int, pack_symbol: str) -> tuple[bytes, int]: + def _parse_module_group(data: bytes, offset: int, + pack_symbol: str) -> tuple[bytes, int]: """Consumes all records for one Module until the 0x002B terminator.""" module_bytes = b'' while offset < len(data): From c53d846ec71db9ea493a7a6ae4e2fe27f0b28131 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 17:48:13 -0400 Subject: [PATCH 029/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 01c94cbf7..c9fd27373 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -231,7 +231,7 @@ def _parse_reference_group(data: bytes, offset: int, start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] # In a real impl, you'd wrap this data into a Reference Model object - record_content = data[offset : offset + 6 + size] + record_content = data[offset:offset + 6 + size] return record_content, offset + 6 + size @staticmethod From df71cb8cb89a143d3d9a0856cc56b8bab4af039d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:12:08 -0400 Subject: [PATCH 030/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index c9fd27373..8a8651661 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -228,7 +228,7 @@ def _parse_reference_group(data: bytes, offset: int, # A Reference is a cluster of records (Name, Libid, etc.) # Logic: Consume the first record, then peek for optional sub-records # like REFERENCECONTROL (0x002F) or Ref-Original (0x0033) - start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] + # start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] # In a real impl, you'd wrap this data into a Reference Model object record_content = data[offset:offset + 6 + size] From db479a04d8b51ef33f91328324fc8bd6b77e65c9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:22:00 -0400 Subject: [PATCH 031/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 8a8651661..2ef7168d8 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -7,13 +7,21 @@ DoubleEncodedString ) from ms_ovba.Models.Fields.packed_data import PackedData -from typing import List, TypeVar +from typing import List, TypedDict, TypeVar T = TypeVar('T', bound='DirStream') -PackableData = DoubleEncodedString | IdSizeField | PackedData +ParackableData = DoubleEncodedString | IdSizeField | PackedData + + +class Parameters(TypedDict): + references: list[], + modules: list, + help_context_id: int, + project_cookie: int, + codepage_name: str class DirStream(): @@ -157,7 +165,7 @@ def from_bytes(data: bytes, endien: str = 'little') -> dict: offset = 0 pack_symbol = '<' if endien == 'little' else '>' - project_data = { + project_data: Parameters = { "references": [], "modules": [], "help_context_id": 0, From a4720be129bb36f110f4f974a7e6568ec62dd8a3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:26:16 -0400 Subject: [PATCH 032/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 2ef7168d8..6c64d9405 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -17,7 +17,7 @@ class Parameters(TypedDict): - references: list[], + references: list[ReferenceRecord], modules: list, help_context_id: int, project_cookie: int, From 3e3db64b797856ba7cee3e0fb47e2eb86095882c Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:27:17 -0400 Subject: [PATCH 033/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 6c64d9405..82890850b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -17,10 +17,10 @@ class Parameters(TypedDict): - references: list[ReferenceRecord], - modules: list, - help_context_id: int, - project_cookie: int, + references: list[ReferenceRecord] + modules: list + help_context_id: int + project_cookie: int codepage_name: str From 86ca4c2449ccd0cfcdd4b994e0b118dea09200e1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:28:22 -0400 Subject: [PATCH 034/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 82890850b..1a34f866a 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -13,7 +13,7 @@ T = TypeVar('T', bound='DirStream') -ParackableData = DoubleEncodedString | IdSizeField | PackedData +PackableData = DoubleEncodedString | IdSizeField | PackedData class Parameters(TypedDict): From 24249139b7f8f128f7eeb9a5d4d4a5f06e2883ac Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:30:03 -0400 Subject: [PATCH 035/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 1a34f866a..9a8a474d5 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -161,7 +161,7 @@ def is_file_valid(file_path: str) -> bool: return False @staticmethod - def from_bytes(data: bytes, endien: str = 'little') -> dict: + def from_bytes(data: bytes, endien: str = 'little') -> Parameters: offset = 0 pack_symbol = '<' if endien == 'little' else '>' From 245baedd841e8088685ad505b621dff5e0a995e4 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 18:47:22 -0400 Subject: [PATCH 036/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 933943104..00b7761fd 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -23,3 +23,17 @@ def test_is_valid() -> None: ms_ovba = MsOvba() decompressed_data = ms_ovba.decompress(compressed_data) assert DirStream.is_valid(decompressed_data) + + +def test_from_bytes() -> None: + expected = {} + file = "tests/blank/vbaProject.bin" + ole_file = OleFile.create_from_file(file) + ole_file.extract_stream('dir', 'tests/blank') + with open('tests/blank/dir.bin', 'rb') as f: + compressed_data = f.read() + + # Use MsOvba to decompress the stream + ms_ovba = MsOvba() + decompressed_data = ms_ovba.decompress(compressed_data) + assert DirStream.from_bytes(decompressed_data) == expected From 925808acf823a897c120e27c928f25a1ea3ccf12 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 19:48:14 -0400 Subject: [PATCH 037/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 00b7761fd..92262f46f 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -1,3 +1,4 @@ +from pathlib import osPath from ms_cfb.ole_file import OleFile from ms_ovba.Views.dirStream import DirStream from ms_ovba_compression.ms_ovba import MsOvba @@ -7,6 +8,16 @@ mock_vbaproject = mock.Mock() +@pytest.fixture +def my_fixture(): + # Setup: Runs BEFORE the test + # print("\nSetting up...") + yield + # Teardown: Runs AFTER the test + osPath("tests/blank/dir.bin").unlink(missing_ok=True) + + + def test_construct() -> None: dir = DirStream(mock_vbaproject) assert isinstance(dir, DirStream) From 7876ac39ea22a9860e09692564c12da593cb21de Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 19:48:27 -0400 Subject: [PATCH 038/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 92262f46f..3ed83d232 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -17,7 +17,6 @@ def my_fixture(): osPath("tests/blank/dir.bin").unlink(missing_ok=True) - def test_construct() -> None: dir = DirStream(mock_vbaproject) assert isinstance(dir, DirStream) From 0ce98874741490ceec7cbfb381f80cb42c30db3f Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:20:42 -0400 Subject: [PATCH 039/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 3ed83d232..7afdb990a 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -1,3 +1,4 @@ +import pytest from pathlib import osPath from ms_cfb.ole_file import OleFile from ms_ovba.Views.dirStream import DirStream From a8ba111a44f456d7c6c05fe17044f8ffd00bfc67 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:27:41 -0400 Subject: [PATCH 040/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 7afdb990a..79109fd95 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -10,7 +10,7 @@ @pytest.fixture -def my_fixture(): +def my_fixture() -> None: # Setup: Runs BEFORE the test # print("\nSetting up...") yield From 00bbc1a9a9b5edf845e98c1042c3606febafc555 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:29:19 -0400 Subject: [PATCH 041/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 79109fd95..6485452f1 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -1,5 +1,5 @@ import pytest -from pathlib import osPath +from pathlib import Path from ms_cfb.ole_file import OleFile from ms_ovba.Views.dirStream import DirStream from ms_ovba_compression.ms_ovba import MsOvba @@ -15,7 +15,7 @@ def my_fixture() -> None: # print("\nSetting up...") yield # Teardown: Runs AFTER the test - osPath("tests/blank/dir.bin").unlink(missing_ok=True) + Path("tests/blank/dir.bin").unlink(missing_ok=True) def test_construct() -> None: From 9affbdaeb3835cafe04169a8f8bc5b17ec35179d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:40:21 -0400 Subject: [PATCH 042/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 6485452f1..deee851b7 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -23,7 +23,7 @@ def test_construct() -> None: assert isinstance(dir, DirStream) -def test_is_valid() -> None: +def test_is_valid(my_fixture) -> None: file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) ole_file.extract_stream('dir', 'tests/blank') @@ -36,7 +36,7 @@ def test_is_valid() -> None: assert DirStream.is_valid(decompressed_data) -def test_from_bytes() -> None: +def test_from_bytes(my_fixture) -> None: expected = {} file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) From a02dc2d1a0427e3ac6749ea54168e9554e68ed4a Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:45:56 -0400 Subject: [PATCH 043/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index deee851b7..362b03e61 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -23,6 +23,7 @@ def test_construct() -> None: assert isinstance(dir, DirStream) +@pytest.mark.usefixtures("my_fixture") def test_is_valid(my_fixture) -> None: file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) @@ -36,6 +37,7 @@ def test_is_valid(my_fixture) -> None: assert DirStream.is_valid(decompressed_data) +@pytest.mark.usefixtures("my_fixture") def test_from_bytes(my_fixture) -> None: expected = {} file = "tests/blank/vbaProject.bin" From 6269753bc494dc58d5937da3e38eb6bc9e5834e8 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 20:48:08 -0400 Subject: [PATCH 044/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index 362b03e61..b2021894b 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -24,7 +24,7 @@ def test_construct() -> None: @pytest.mark.usefixtures("my_fixture") -def test_is_valid(my_fixture) -> None: +def test_is_valid() -> None: file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) ole_file.extract_stream('dir', 'tests/blank') @@ -38,7 +38,7 @@ def test_is_valid(my_fixture) -> None: @pytest.mark.usefixtures("my_fixture") -def test_from_bytes(my_fixture) -> None: +def test_from_bytes() -> None: expected = {} file = "tests/blank/vbaProject.bin" ole_file = OleFile.create_from_file(file) From e3367a2dbe640b347578087f295757f1b5324bb9 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 21:17:23 -0400 Subject: [PATCH 045/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 9a8a474d5..424d0aa4d 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -114,11 +114,28 @@ def is_valid(data: bytes) -> bool: # 1. Check PROJECTSYSKIND (Mandatory first record) # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) - record_id, size = struct.unpack_from(" Date: Fri, 3 Apr 2026 21:26:30 -0400 Subject: [PATCH 046/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 424d0aa4d..997fa4438 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -124,7 +124,9 @@ def is_valid(data: bytes) -> bool: if size != 4: return False offset += 10 - record_id, size, value = struct.unpack_from(" Date: Fri, 3 Apr 2026 21:32:05 -0400 Subject: [PATCH 047/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 997fa4438..a25d89e7d 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -116,12 +116,15 @@ def is_valid(data: bytes) -> bool: # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) record_id, size, value = struct.unpack_from(" Date: Fri, 3 Apr 2026 22:08:25 -0400 Subject: [PATCH 048/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index a25d89e7d..f4a5cbba4 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -1,4 +1,5 @@ import struct +import warnings from ms_ovba_compression.ms_ovba import MsOvba from ms_ovba.vbaProject import VbaProject from ms_ovba.Models.Entities.reference_record import ReferenceRecord From cbb51d078d9110af0b5da66b2c4d5a2b4646a4b3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Fri, 3 Apr 2026 22:16:50 -0400 Subject: [PATCH 049/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index f4a5cbba4..fcf32f8ba 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -132,10 +132,14 @@ def is_valid(data: bytes) -> bool: struct.unpack_from(" Date: Fri, 3 Apr 2026 23:19:43 -0400 Subject: [PATCH 050/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index fcf32f8ba..b45c48264 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -118,7 +118,7 @@ def is_valid(data: bytes) -> bool: record_id, size, value = struct.unpack_from(" bool: if size != 4: warnings.warn( "Incorrect PROJECTCOMPATVERSION", SyntaxWarning) - return False + return 2 offset += 10 record_id, size, value = ( struct.unpack_from(" bool: if record_id != 2 or size != 4 or value != 0x409: warnings.warn( "Incorrect PROJECTLCID", SyntaxWarning) - return False + return 3 offset += 10 record_id, size, value = struct.unpack_from(" bool: offset += 2 if not found_modules_header: - return False + return 6 # 4. Check the Terminator (Last 6 bytes of the stream) # output += struct.pack(pack_symbol + "HI", 16, 0) From 5f018356dd28d6e027d256a29c88ebc1d8e7117b Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 06:03:39 -0400 Subject: [PATCH 051/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index b2021894b..e48311363 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -34,7 +34,7 @@ def test_is_valid() -> None: # Use MsOvba to decompress the stream ms_ovba = MsOvba() decompressed_data = ms_ovba.decompress(compressed_data) - assert DirStream.is_valid(decompressed_data) + assert DirStream.is_valid(decompressed_data) == 0 @pytest.mark.usefixtures("my_fixture") From ed5abf9d625e6cf5f3cd08159ebcc75fd77eca9e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 06:06:49 -0400 Subject: [PATCH 052/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index b45c48264..8584aaca5 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -117,7 +117,9 @@ def is_valid(data: bytes) -> bool: # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 06:09:49 -0400 Subject: [PATCH 053/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 8584aaca5..6c23b4446 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -116,9 +116,9 @@ def is_valid(data: bytes) -> bool: # 1. Check PROJECTSYSKIND (Mandatory first record) # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 06:12:12 -0400 Subject: [PATCH 054/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 6c23b4446..73a4bf4d6 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -120,7 +120,7 @@ def is_valid(data: bytes) -> bool: warnings.warn( f"Incorrect PROJECTSYSKIND ({record_id}, {size}, {value}", SyntaxWarning) - return 1 + return False offset += 10 record_id, size, value = struct.unpack_from(" bool: if size != 4: warnings.warn( "Incorrect PROJECTCOMPATVERSION", SyntaxWarning) - return 2 + return False offset += 10 record_id, size, value = ( struct.unpack_from(" bool: if record_id != 2 or size != 4 or value != 0x409: warnings.warn( "Incorrect PROJECTLCID", SyntaxWarning) - return 3 + return False offset += 10 record_id, size, value = struct.unpack_from(" bool: offset += 2 if not found_modules_header: - return 6 + return False # 4. Check the Terminator (Last 6 bytes of the stream) # output += struct.pack(pack_symbol + "HI", 16, 0) From 7f83e63a5ed203fb5470bb4eb8a18b9fd23425bc Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 06:13:40 -0400 Subject: [PATCH 055/115] Update test_dir.py --- tests/Unit/Views/test_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Views/test_dir.py b/tests/Unit/Views/test_dir.py index e48311363..b2021894b 100644 --- a/tests/Unit/Views/test_dir.py +++ b/tests/Unit/Views/test_dir.py @@ -34,7 +34,7 @@ def test_is_valid() -> None: # Use MsOvba to decompress the stream ms_ovba = MsOvba() decompressed_data = ms_ovba.decompress(compressed_data) - assert DirStream.is_valid(decompressed_data) == 0 + assert DirStream.is_valid(decompressed_data) @pytest.mark.usefixtures("my_fixture") From c5c49576028bbafcb08c0b31c7a10302a6cd56ed Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 07:00:51 -0400 Subject: [PATCH 056/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 57 +++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 73a4bf4d6..63a0b1ca0 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -145,9 +145,64 @@ def is_valid(data: bytes) -> bool: return False offset += 10 record_id, size, value = struct.unpack_from(" 2000 or s2 != 0x40 or s2 != 2 * size: + warnings.warn( + "Incorrect PROJECTDOCSTRING", SyntaxWarning) + return False + offset += 12 + size * 3 + + record_id, size = struct.unpack_from(" 260 or s2 != size or value != v2: + warnings.warn( + "Incorrect PROJECTHELPFILEPATH", SyntaxWarning) + return False + offset += 12 + size * 2 + + record_id, size, value = struct.unpack_from(" 2015 or s2 != 2 * size: + warnings.warn( + "Incorrect PROJECTCONSTANTS", SyntaxWarning) + return False + offset += 12 + size * 3 + # 2. Skip through variable Information/Reference records # Real validation would loop through known IDs (1-12, 16, 17, etc.) # For brevity, we verify the specific 'Terminator' at the end. From ceccf730087dcbcd3c8e059c2793e3c1eff34cd2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 07:29:12 -0400 Subject: [PATCH 057/115] Update dir --- tests/blank/dir | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/blank/dir b/tests/blank/dir index 530e7b735..59d68ba7f 100644 --- a/tests/blank/dir +++ b/tests/blank/dir @@ -1,14 +1,19 @@ -00000000 01 00 04 00 00 00 03 00 00 00 4A 00 04 00 00 00 ..........J..... -00000010 03 00 00 00 02 00 04 00 00 00 09 04 00 00 14 00 ................ -00000020 04 00 00 00 09 04 00 00 03 00 02 00 00 00 E4 04 ..............ä. -00000030 04 00 0A 00 00 00 56 42 41 50 72 6F 6A 65 63 74 ......VBAProject -00000040 05 00 00 00 00 00 40 00 00 00 00 00 06 00 00 00 ......@......... -00000050 00 00 3D 00 00 00 00 00 07 00 04 00 00 00 00 00 ..=............. -00000060 00 00 08 00 04 00 00 00 00 00 00 00 09 00 04 00 ................ -00000070 00 00 57 02 BE 65 11 00 0C 00 00 00 00 00 3C 00 ..W.¾e........<. -00000080 00 00 00 00 16 00 06 00 00 00 73 74 64 6F 6C 65 ..........stdole References begin at 84 -00000090 3E 00 0C 00 00 00 73 00 74 00 64 00 6F 00 6C 00 >.....s.t.d.o.l. -000000A0 65 00 0D 00 68 00 00 00 5E 00 00 00 2A 5C 47 7B e...h...^...*\G{ +01 00 04 00 00 00 03 00 00 00 .......... +4A 00 04 00 00 00 03 00 00 00 J......... +02 00 04 00 00 00 09 04 00 00 .......... +14 00 04 00 00 00 09 04 00 00 .......... +03 00 02 00 00 00 E4 04 ......ä. +04 00 0A 00 00 00 56 42 41 50 72 6F 6A 65 63 74 ......VBAProject +05 00 00 00 00 00 40 00 00 00 00 00 ......@..... +06 00 00 00 00 00 3D 00 00 00 00 00 ......=..... +07 00 04 00 00 00 00 00 00 00 .......... +08 00 04 00 00 00 00 00 00 00 .......... +09 00 04 00 00 00 57 02 BE 65 11 00 ......W.¾e.. +0C 00 00 00 00 00 3C 00 00 00 00 00 ......<..... + +16 00 06 00 00 00 73 74 64 6F 6C 65 3E 00 0C 00 ......stdole>... +00 00 73 00 74 00 64 00 6F 00 6C 00 65 00 ..s.t.d.o.l.e. +0D 00 68 00 00 00 5E 00 00 00 2A 5C 47 7B ..h...^...*\G{ 000000B0 30 30 30 32 30 34 33 30 2D 30 30 30 30 2D 30 30 00020430-0000-00 000000C0 30 30 2D 43 30 30 30 2D 30 30 30 30 30 30 30 30 00-C000-00000000 000000D0 30 30 34 36 7D 23 32 2E 30 23 30 23 43 3A 5C 57 0046}#2.0#0#C:\W From ec79c0ce9ed9d4e1f3a9552c41851293864065a6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 07:43:47 -0400 Subject: [PATCH 058/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 63a0b1ca0..e49c99985 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -203,6 +203,13 @@ def is_valid(data: bytes) -> bool: return False offset += 12 + size * 3 + record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 08:24:20 -0400 Subject: [PATCH 059/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 60 +++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index e49c99985..df93e62c4 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -110,6 +110,13 @@ def is_valid(data: bytes) -> bool: Static validation: Checks if bytes follow the DirStream structure. Expects decompressed bytes. """ + project_data: Parameters = { + "references": [], + "modules": [], + "help_context_id": 0, + "project_cookie": 0, + "codepage_name": "cp1252" + } try: offset = 0 @@ -204,16 +211,51 @@ def is_valid(data: bytes) -> bool: offset += 12 + size * 3 record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 08:42:57 -0400 Subject: [PATCH 060/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 94 ++++++++++++++++------------------ 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index df93e62c4..16d7022ea 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -106,6 +106,15 @@ def _load_information(self: T) -> List: @staticmethod def is_valid(data: bytes) -> bool: + try: + DirStream.from_bytes(data) + except Exception as e: + warnings.warn(str(e), SyntaxWarning) + return False + return True + + @staticmethod + def from_bytes(data: bytes) -> Parameters: """ Static validation: Checks if bytes follow the DirStream structure. Expects decompressed bytes. @@ -117,59 +126,46 @@ def is_valid(data: bytes) -> bool: "project_cookie": 0, "codepage_name": "cp1252" } - try: - offset = 0 + offset = 0 - # 1. Check PROJECTSYSKIND (Mandatory first record) - # IdSizeField(1, 4, 3) -> ID=1 (2 bytes), Size=4 (4 bytes) - record_id, size, value = struct.unpack_from(" ID=1 (2 bytes), Size=4 (4 bytes) + record_id, size, value = struct.unpack_from(" 2000 or s2 != 0x40 or s2 != 2 * size: - warnings.warn( - "Incorrect PROJECTDOCSTRING", SyntaxWarning) - return False - offset += 12 + size * 3 + record_id, size = struct.unpack_from(" 2000 or s2 != 0x40 or s2 != 2 * size: + raise ValueError("Incorrect PROJECTDOCSTRING") + offset += 12 + size * 3 record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 09:47:11 -0400 Subject: [PATCH 061/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 264 +++++++++------------------------ 1 file changed, 67 insertions(+), 197 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 16d7022ea..beca6f185 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -167,115 +167,81 @@ def from_bytes(data: bytes) -> Parameters: raise ValueError("Incorrect PROJECTDOCSTRING") offset += 12 + size * 3 - record_id, size = struct.unpack_from(" 260 or s2 != size or value != v2: - warnings.warn( - "Incorrect PROJECTHELPFILEPATH", SyntaxWarning) - return False - offset += 12 + size * 2 - - record_id, size, value = struct.unpack_from(" 260 or s2 != size or value != v2: + raise ValueError("Incorrect PROJECTHELPFILEPATH") + return False + offset += 12 + size * 2 - record_id, size, value = struct.unpack_from(" 2015 or s2 != 2 * size: - warnings.warn( - "Incorrect PROJECTCONSTANTS", SyntaxWarning) - return False - offset += 12 + size * 3 + record_id, size, value, v2 = struct.unpack_from(" 2015 or s2 != 2 * size: + raise ValueError("Incorrect PROJECTCONSTANTS") + offset += 12 + size * 3 + + record_id, size = struct.unpack_from(" bool: @@ -288,99 +254,3 @@ def is_file_valid(file_path: str) -> bool: return DirStream.is_valid(decompressed) except Exception: return False - - @staticmethod - def from_bytes(data: bytes, endien: str = 'little') -> Parameters: - offset = 0 - pack_symbol = '<' if endien == 'little' else '>' - - project_data: Parameters = { - "references": [], - "modules": [], - "help_context_id": 0, - "project_cookie": 0, - "codepage_name": "cp1252" - } - - while offset < len(data): - record_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - - # --- REFERENCES SECTION --- - # Using your factory for IDs: 0x000D, 0x000E, 0x002F, 0x0033 - if record_id in [0x000D, 0x000E, 0x002F, 0x0033]: - # We need to know how many bytes to send to - # ReferenceRecord.unpack - size = ( - struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - ) - total_len = 6 + size - - # Extract specific slice for the factory - ref_bytes = data[offset:offset + total_len] - project_data["references"].append( - ReferenceRecord.unpack(ref_bytes, endien) - ) - - offset += total_len - continue - - # --- MODULES HEADER & COOKIE --- - if record_id == 0x000F: - offset += 6 # Skip ID/Size of the 0x000F record - # Peek for the Cookie (0x0013) which follows immediately - cookie_id, c_size, cookie = ( - struct.unpack_from(pack_symbol + "H I H", data, offset) - ) - project_data["project_cookie"] = cookie - offset += 8 # Skip ID/Size/Value of 0x0013 - continue - - # --- MODULES SECTION (0x0019) --- - if record_id == 0x0019: - module_obj, new_offset = ( - DirStream._parse_module_group(data, offset, endien) - ) - project_data["modules"].append(module_obj) - offset = new_offset - continue - - # --- INFORMATION RECORDS --- - if record_id == 0x0010: - break # Terminator - - size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - if record_id == 0x0007: # HELPCONTEXT - project_data["help_context_id"] = ( - struct.unpack_from(pack_symbol + "I", data, offset + 6)[0] - ) - - offset += 6 + size - - return project_data - - @staticmethod - def _parse_reference_group(data: bytes, offset: int, - pack_symbol: str) -> tuple[bytes, int]: - """Consumes records until the end of a single Reference definition.""" - # A Reference is a cluster of records (Name, Libid, etc.) - # Logic: Consume the first record, then peek for optional sub-records - # like REFERENCECONTROL (0x002F) or Ref-Original (0x0033) - # start_id = struct.unpack_from(pack_symbol + "H", data, offset)[0] - size = struct.unpack_from(pack_symbol + "I", data, offset + 2)[0] - # In a real impl, you'd wrap this data into a Reference Model object - record_content = data[offset:offset + 6 + size] - return record_content, offset + 6 + size - - @staticmethod - def _parse_module_group(data: bytes, offset: int, - pack_symbol: str) -> tuple[bytes, int]: - """Consumes all records for one Module until the 0x002B terminator.""" - module_bytes = b'' - while offset < len(data): - r_id, size = struct.unpack_from(pack_symbol + "H I", data, offset) - record_total_len = 6 + size - module_bytes += data[offset:offset + record_total_len] - offset += record_total_len - if r_id == 0x002B: # MODULE Terminator - break - return module_bytes, offset From 59f2d1a1336d6b8c97c204a1d48e9b777bd7b201 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 09:53:20 -0400 Subject: [PATCH 062/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index beca6f185..14d109762 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -142,7 +142,7 @@ def from_bytes(data: bytes) -> Parameters: offset += 10 record_id, size, value = (struct.unpack_from(" Parameters: if record_id != 0x0f or size != 2: raise ValueError("Expected ModuleRecord") count, record_id, size, cookie = struct.unpack_from(" Date: Sat, 4 Apr 2026 09:57:08 -0400 Subject: [PATCH 063/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 14d109762..ad0c579af 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -229,7 +229,7 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from( " Date: Sat, 4 Apr 2026 09:59:58 -0400 Subject: [PATCH 064/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index ad0c579af..d0e405c4f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -206,7 +206,8 @@ def from_bytes(data: bytes) -> Parameters: if record_id == 0x16: record_size = 12 + size * 3 - record_id, size = struct.unpack_from(" Parameters: if record_id != 0x0f or size != 2: raise ValueError("Expected ModuleRecord") - count, record_id, size, cookie = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:00:55 -0400 Subject: [PATCH 065/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index d0e405c4f..e069708a7 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -238,7 +238,7 @@ def from_bytes(data: bytes) -> Parameters: data[offset:offset + record_size], "little") project_data["references"] += ref record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:04:46 -0400 Subject: [PATCH 066/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index e069708a7..9e46bf399 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -236,7 +236,7 @@ def from_bytes(data: bytes) -> Parameters: raise ValueError("Unknown Reference Type") ref = ReferenceRecord.unpack( data[offset:offset + record_size], "little") - project_data["references"] += ref + project_data["references"] += [ref] record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:08:07 -0400 Subject: [PATCH 067/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 9e46bf399..5e0a6ea15 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -163,7 +163,7 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from(" 2000 or s2 != 0x40 or s2 != 2 * size: + if record_id != 5 or size > 2000 or r2 != 0x40 or s2 != 2 * size: raise ValueError("Incorrect PROJECTDOCSTRING") offset += 12 + size * 3 From 5163e93e147c48bc2bbe5ea7276b46e13261587e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 10:22:09 -0400 Subject: [PATCH 068/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 5e0a6ea15..7be228e43 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -164,7 +164,8 @@ def from_bytes(data: bytes) -> Parameters: value, r2, s2, v2 = struct.unpack_from( f"{size}sHI{2*size}s", data, offset + 6) if record_id != 5 or size > 2000 or r2 != 0x40 or s2 != 2 * size: - raise ValueError("Incorrect PROJECTDOCSTRING") + raise ValueError( + "Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") offset += 12 + size * 3 record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:23:01 -0400 Subject: [PATCH 069/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 7be228e43..4aae3a89a 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -165,7 +165,7 @@ def from_bytes(data: bytes) -> Parameters: f"{size}sHI{2*size}s", data, offset + 6) if record_id != 5 or size > 2000 or r2 != 0x40 or s2 != 2 * size: raise ValueError( - "Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") + f"Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") offset += 12 + size * 3 record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:32:15 -0400 Subject: [PATCH 070/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 4aae3a89a..82663533b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -158,7 +158,8 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 10:42:37 -0400 Subject: [PATCH 071/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 82663533b..637bbb9ac 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -162,9 +162,12 @@ def from_bytes(data: bytes) -> Parameters: offset += 6 + size record_id, size = struct.unpack_from(" 2000 or r2 != 0x40 or s2 != 2 * size: + if size == 0: + r2, s2 = struct.unpack_from("HI", data, offset + 6) + else: + value, r2, s2, v2 = struct.unpack_from( + f"{size}sHI{2*size}s", data, offset + 6) + if record_id != 5 or size > 2000 or s2 != 2 * size: raise ValueError( f"Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") offset += 12 + size * 3 From 7cbc60e745f63502d939104597332beaf158e193 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 10:54:22 -0400 Subject: [PATCH 072/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 637bbb9ac..4a9921b7c 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -163,10 +163,10 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from(" 2000 or s2 != 2 * size: raise ValueError( f"Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") From f6a22b2f783e4eea9a4f124e9218bfe194ee35c5 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 10:58:42 -0400 Subject: [PATCH 073/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 4a9921b7c..09b09262b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -176,14 +176,12 @@ def from_bytes(data: bytes) -> Parameters: value, r2, s2, v2 = struct.unpack_from( f"{size}sHI{size}s", data, offset + 6) if record_id != 6 or size > 260 or s2 != size or value != v2: - raise ValueError("Incorrect PROJECTHELPFILEPATH") - return False + raise ValueError(f"Incorrect PROJECTHELPFILEPATH({record_id}, {size}, {s2})") offset += 12 + size * 2 record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 11:00:17 -0400 Subject: [PATCH 074/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 09b09262b..32e1cf600 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -176,7 +176,8 @@ def from_bytes(data: bytes) -> Parameters: value, r2, s2, v2 = struct.unpack_from( f"{size}sHI{size}s", data, offset + 6) if record_id != 6 or size > 260 or s2 != size or value != v2: - raise ValueError(f"Incorrect PROJECTHELPFILEPATH({record_id}, {size}, {s2})") + raise ValueError( + f"Incorrect PROJECTHELPFILEPATH({record_id}, {size}, {s2})") offset += 12 + size * 2 record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 11:02:29 -0400 Subject: [PATCH 075/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 32e1cf600..c160b9fb2 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -174,7 +174,7 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from(" 260 or s2 != size or value != v2: raise ValueError( f"Incorrect PROJECTHELPFILEPATH({record_id}, {size}, {s2})") From ce67d3110cd2b1ea57bbe98e948e47debc9df836 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 11:04:51 -0400 Subject: [PATCH 076/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index c160b9fb2..3f29aee0d 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -162,11 +162,8 @@ def from_bytes(data: bytes) -> Parameters: offset += 6 + size record_id, size = struct.unpack_from(" 2000 or s2 != 2 * size: raise ValueError( f"Incorrect PROJECTDOCSTRING({record_id}, {size}, {r2}, {s2})") From a46371807982cebd6fb24f9f59b09e111900d341 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 11:13:31 -0400 Subject: [PATCH 077/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 3f29aee0d..d62e82406 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -194,7 +194,7 @@ def from_bytes(data: bytes) -> Parameters: record_id, size = struct.unpack_from(" 2015 or s2 != 2 * size: raise ValueError("Incorrect PROJECTCONSTANTS") offset += 12 + size * 3 From 2da0d58ef018b386fe0df9d9df553f1327463599 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 11:25:36 -0400 Subject: [PATCH 078/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index d62e82406..90a0d7904 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -206,9 +206,8 @@ def from_bytes(data: bytes) -> Parameters: record_size = 0 if record_id == 0x16: record_size = 12 + size * 3 - - record_id, size = struct.unpack_from( - " Date: Sat, 4 Apr 2026 11:58:10 -0400 Subject: [PATCH 079/115] Update reference_record.py --- src/ms_ovba/Models/Entities/reference_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/reference_record.py b/src/ms_ovba/Models/Entities/reference_record.py index ee1c7fc67..1461ed194 100644 --- a/src/ms_ovba/Models/Entities/reference_record.py +++ b/src/ms_ovba/Models/Entities/reference_record.py @@ -22,7 +22,7 @@ def unpack(bytestring: bytes, endien: str) -> ReferenceRecord: ReferenceOriginal ) endien_symbol = '<' if endien == 'little' else '>' - id = struct.unpack(endien_symbol + "H", bytestring) + id = struct.unpack(f"{endien_symbol}H", bytestring) ref: ReferenceRecord if id == 0x000D: ref = ReferenceRegistered.unpack(bytestring, endien) From c41aa1bac8d1c680c7c3d16371f1fde854842a92 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:02:56 -0400 Subject: [PATCH 080/115] Update reference_record.py --- src/ms_ovba/Models/Entities/reference_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/reference_record.py b/src/ms_ovba/Models/Entities/reference_record.py index 1461ed194..ff86a50f7 100644 --- a/src/ms_ovba/Models/Entities/reference_record.py +++ b/src/ms_ovba/Models/Entities/reference_record.py @@ -22,7 +22,7 @@ def unpack(bytestring: bytes, endien: str) -> ReferenceRecord: ReferenceOriginal ) endien_symbol = '<' if endien == 'little' else '>' - id = struct.unpack(f"{endien_symbol}H", bytestring) + id = struct.unpack_from(f"{endien_symbol}H", bytestring, 0) ref: ReferenceRecord if id == 0x000D: ref = ReferenceRegistered.unpack(bytestring, endien) From cbf1014da67d4e82561e6ea43491762b2c5c69e2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:06:37 -0400 Subject: [PATCH 081/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 90a0d7904..5b9536101 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -233,7 +233,7 @@ def from_bytes(data: bytes) -> Parameters: case 0x0d | 0x0e: record_size += 6 + size case _: - raise ValueError("Unknown Reference Type") + raise ValueError(f"Unknown Reference Type: {record_id}") ref = ReferenceRecord.unpack( data[offset:offset + record_size], "little") project_data["references"] += [ref] From 09bbe1c868b7384d9652160ed228c29f0e82abad Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:12:02 -0400 Subject: [PATCH 082/115] Update reference_record.py --- src/ms_ovba/Models/Entities/reference_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/reference_record.py b/src/ms_ovba/Models/Entities/reference_record.py index ff86a50f7..2007bbb5a 100644 --- a/src/ms_ovba/Models/Entities/reference_record.py +++ b/src/ms_ovba/Models/Entities/reference_record.py @@ -33,5 +33,5 @@ def unpack(bytestring: bytes, endien: str) -> ReferenceRecord: elif id == 0x0033: ref = ReferenceOriginal.unpack(bytestring, endien) else: - raise Exception("Unknown Reference Type") + raise Exception(f"Unknown Reference Type: {id}") return ref From 6852ed873eaba8c12208e618978104b964c01da2 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:13:50 -0400 Subject: [PATCH 083/115] Update reference_record.py --- src/ms_ovba/Models/Entities/reference_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/reference_record.py b/src/ms_ovba/Models/Entities/reference_record.py index 2007bbb5a..704684802 100644 --- a/src/ms_ovba/Models/Entities/reference_record.py +++ b/src/ms_ovba/Models/Entities/reference_record.py @@ -22,7 +22,7 @@ def unpack(bytestring: bytes, endien: str) -> ReferenceRecord: ReferenceOriginal ) endien_symbol = '<' if endien == 'little' else '>' - id = struct.unpack_from(f"{endien_symbol}H", bytestring, 0) + id, = struct.unpack_from(f"{endien_symbol}H", bytestring, 0) ref: ReferenceRecord if id == 0x000D: ref = ReferenceRegistered.unpack(bytestring, endien) From 611c5105007027d965861dd672505ae18722ed79 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:21:38 -0400 Subject: [PATCH 084/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 5b9536101..cee76724f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -2,7 +2,7 @@ import warnings from ms_ovba_compression.ms_ovba import MsOvba from ms_ovba.vbaProject import VbaProject -from ms_ovba.Models.Entities.reference_record import ReferenceRecord +from ms_ovba.Models.Entities.reference import Reference from ms_ovba.Models.Fields.idSizeField import IdSizeField from ms_ovba.Models.Fields.doubleEncodedString import ( DoubleEncodedString @@ -18,7 +18,7 @@ class Parameters(TypedDict): - references: list[ReferenceRecord] + references: list[Reference] modules: list help_context_id: int project_cookie: int @@ -234,7 +234,7 @@ def from_bytes(data: bytes) -> Parameters: record_size += 6 + size case _: raise ValueError(f"Unknown Reference Type: {record_id}") - ref = ReferenceRecord.unpack( + ref = Reference.unpack( data[offset:offset + record_size], "little") project_data["references"] += [ref] record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 12:34:27 -0400 Subject: [PATCH 085/115] Update reference.py --- src/ms_ovba/Models/Entities/reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Models/Entities/reference.py b/src/ms_ovba/Models/Entities/reference.py index 68f304f78..b6db9630e 100644 --- a/src/ms_ovba/Models/Entities/reference.py +++ b/src/ms_ovba/Models/Entities/reference.py @@ -32,7 +32,7 @@ def unpack(data: bytes, endien: str) -> Reference: endien_symbol = '<' if endien == 'little' else '>' name = '' offset = 0 - id = struct.unpack_from(endien_symbol + "H", data, offset) + id, = struct.unpack_from(endien_symbol + "H", data, offset) if id == 0x0016: offset += 2 size1, = struct.unpack_from(endien_symbol + "I", data, offset) From bd3737601d8581d2804e71683c22a79967788b0e Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:41:07 -0400 Subject: [PATCH 086/115] Update reference.py --- src/ms_ovba/Models/Entities/reference.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Models/Entities/reference.py b/src/ms_ovba/Models/Entities/reference.py index b6db9630e..972a83259 100644 --- a/src/ms_ovba/Models/Entities/reference.py +++ b/src/ms_ovba/Models/Entities/reference.py @@ -37,10 +37,10 @@ def unpack(data: bytes, endien: str) -> Reference: offset += 2 size1, = struct.unpack_from(endien_symbol + "I", data, offset) offset += 4 - format = endien_symbol + size1 + "s" + format = f"{endien_symbol}{size1}s" name, = struct.unpack_from(format, data, offset) offset += size1 - size2 = struct.unpack_from(endien_symbol + "I", data, offset) + size2, = struct.unpack_from(f"{endien_symbol}I", data, offset) offset += 4 if size2 != size1 * 2: # raise warning From 74490cd576bc5dcff4c62a5672a2af75d5bce609 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 12:48:42 -0400 Subject: [PATCH 087/115] Update reference.py --- src/ms_ovba/Models/Entities/reference.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/ms_ovba/Models/Entities/reference.py b/src/ms_ovba/Models/Entities/reference.py index 972a83259..05835f1ae 100644 --- a/src/ms_ovba/Models/Entities/reference.py +++ b/src/ms_ovba/Models/Entities/reference.py @@ -32,16 +32,12 @@ def unpack(data: bytes, endien: str) -> Reference: endien_symbol = '<' if endien == 'little' else '>' name = '' offset = 0 - id, = struct.unpack_from(endien_symbol + "H", data, offset) + id, size1 = struct.unpack_from(f"{endien_symbol}HI", data, offset) if id == 0x0016: - offset += 2 - size1, = struct.unpack_from(endien_symbol + "I", data, offset) - offset += 4 - format = f"{endien_symbol}{size1}s" - name, = struct.unpack_from(format, data, offset) - offset += size1 - size2, = struct.unpack_from(f"{endien_symbol}I", data, offset) - offset += 4 + offset += 6 + format = f"{endien_symbol}{size1}sHI" + name, id, size2 = struct.unpack_from(format, data, offset) + offset += size1 + 6 if size2 != size1 * 2: # raise warning pass From c0d8e3ab980ef2a3d334618321bcca0d9a3b786d Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 13:26:51 -0400 Subject: [PATCH 088/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index cee76724f..3c903910c 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -237,6 +237,7 @@ def from_bytes(data: bytes) -> Parameters: ref = Reference.unpack( data[offset:offset + record_size], "little") project_data["references"] += [ref] + offset += record_size record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 14:01:02 -0400 Subject: [PATCH 089/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 3c903910c..9e78bea81 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -244,8 +244,32 @@ def from_bytes(data: bytes) -> Parameters: raise ValueError("Expected ModuleRecord") count, record_id, size, cookie = struct.unpack_from( " Date: Sat, 4 Apr 2026 14:03:37 -0400 Subject: [PATCH 090/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 9e78bea81..d55887a87 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -245,7 +245,7 @@ def from_bytes(data: bytes) -> Parameters: count, record_id, size, cookie = struct.unpack_from( " Date: Sat, 4 Apr 2026 14:52:32 -0400 Subject: [PATCH 091/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index d55887a87..7f1b1cd26 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -242,6 +242,7 @@ def from_bytes(data: bytes) -> Parameters: if record_id != 0x0f or size != 2: raise ValueError("Expected ModuleRecord") + offset += 6 count, record_id, size, cookie = struct.unpack_from( " Date: Sat, 4 Apr 2026 15:41:44 -0400 Subject: [PATCH 092/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 7f1b1cd26..bdc43ef05 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -265,10 +265,14 @@ def from_bytes(data: bytes) -> Parameters: f"<{size}sHI", data, offset + record_size) module_data["stream_name"] = value record_size += size + 6 - value, record_id, size = struct.unpack_from( - f"<{size}sHI", data, offset + record_size) + value, record_id, size, value2 = struct.unpack_from( + f"<{size}sHI{size*2}s", data, offset + record_size) module_data["docstring"] = value - record_size += size + 6 + record_size += size * 3 + 6 + record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 15:49:37 -0400 Subject: [PATCH 093/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index bdc43ef05..e3852ae3b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -269,7 +269,8 @@ def from_bytes(data: bytes) -> Parameters: f"<{size}sHI{size*2}s", data, offset + record_size) module_data["docstring"] = value record_size += size * 3 + 6 - record_id, size, value = struct.unpack_from(" Date: Sat, 4 Apr 2026 15:53:47 -0400 Subject: [PATCH 094/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index e3852ae3b..24fdaae15 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -274,6 +274,16 @@ def from_bytes(data: bytes) -> Parameters: if record_id != 0x31 or size != 4: raise ValueError("Incorrect MODULEOFFSET") offset += 10 + record_id, size, value = struct.unpack_from( + " Date: Sat, 4 Apr 2026 16:14:28 -0400 Subject: [PATCH 095/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 24fdaae15..91148c1f8 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -245,6 +245,7 @@ def from_bytes(data: bytes) -> Parameters: offset += 6 count, record_id, size, cookie = struct.unpack_from( " Date: Sat, 4 Apr 2026 16:24:34 -0400 Subject: [PATCH 096/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 91148c1f8..bc41f96d3 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -259,8 +259,8 @@ def from_bytes(data: bytes) -> Parameters: record_size += size * 3 + 6 # validate sizes and that values match module_data["name"] = value - record_id, size = struct.unpack_from( - f"<{size}sHI", data, offset + record_size) + record_id, size, = struct.unpack_from( + f" Date: Sat, 4 Apr 2026 16:29:18 -0400 Subject: [PATCH 097/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index bc41f96d3..18e7dc2b9 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -260,7 +260,7 @@ def from_bytes(data: bytes) -> Parameters: # validate sizes and that values match module_data["name"] = value record_id, size, = struct.unpack_from( - f" Date: Sat, 4 Apr 2026 16:35:10 -0400 Subject: [PATCH 098/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 18e7dc2b9..b777379c8 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -273,7 +273,7 @@ def from_bytes(data: bytes) -> Parameters: record_id, size, value = struct.unpack_from( " Date: Sat, 4 Apr 2026 16:36:36 -0400 Subject: [PATCH 099/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index b777379c8..c60628a57 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -282,8 +282,8 @@ def from_bytes(data: bytes) -> Parameters: offset += 10 record_id, size, value = struct.unpack_from( " Date: Sat, 4 Apr 2026 16:51:12 -0400 Subject: [PATCH 100/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index c60628a57..3998ad7f8 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -266,6 +266,8 @@ def from_bytes(data: bytes) -> Parameters: f"<{size}sHI", data, offset + record_size) module_data["stream_name"] = value record_size += size + 6 + if record_id != 0x1c: + raise ValueError(f"Incorrect MODULEDOCSTRING({record_id})" value, record_id, size, value2 = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) module_data["docstring"] = value From 2ebf1fe64528e67f31fb265a04a86167d5f78a47 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 16:52:35 -0400 Subject: [PATCH 101/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 3998ad7f8..b6697e6af 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -267,7 +267,7 @@ def from_bytes(data: bytes) -> Parameters: module_data["stream_name"] = value record_size += size + 6 if record_id != 0x1c: - raise ValueError(f"Incorrect MODULEDOCSTRING({record_id})" + raise ValueError(f"Incorrect MODULEDOCSTRING({record_id})") value, record_id, size, value2 = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) module_data["docstring"] = value From 44fe6c3867e25426ff45dce83034ea0df4c349c1 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 16:54:12 -0400 Subject: [PATCH 102/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index b6697e6af..4bb5bc05f 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -275,7 +275,8 @@ def from_bytes(data: bytes) -> Parameters: record_id, size, value = struct.unpack_from( " Date: Sat, 4 Apr 2026 17:02:43 -0400 Subject: [PATCH 103/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 4bb5bc05f..26a20d8fd 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -262,10 +262,15 @@ def from_bytes(data: bytes) -> Parameters: record_id, size, = struct.unpack_from( " Date: Sat, 4 Apr 2026 17:14:11 -0400 Subject: [PATCH 104/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 26a20d8fd..3dc4091b7 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -262,17 +262,17 @@ def from_bytes(data: bytes) -> Parameters: record_id, size, = struct.unpack_from( " Date: Sat, 4 Apr 2026 17:17:15 -0400 Subject: [PATCH 105/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 3dc4091b7..666ca649b 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -264,7 +264,7 @@ def from_bytes(data: bytes) -> Parameters: record_size += 6 value, record_id, size2, value = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) - if record_id != 0x1a or size2 != size * 2 + if record_id != 0x1a or size2 != size * 2: raise ValueError(f"Incorrect MODULESTREAMNAME({record_id})") module_data["stream_name"] = value record_size += size * 3 + 6 From 40da774ffef18e8a1b0463d9d628b410a85067a6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 17:22:01 -0400 Subject: [PATCH 106/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 666ca649b..80076bdb8 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -272,7 +272,8 @@ def from_bytes(data: bytes) -> Parameters: " Date: Sat, 4 Apr 2026 17:23:19 -0400 Subject: [PATCH 107/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 80076bdb8..0131e63ef 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -265,7 +265,7 @@ def from_bytes(data: bytes) -> Parameters: value, record_id, size2, value = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) if record_id != 0x1a or size2 != size * 2: - raise ValueError(f"Incorrect MODULESTREAMNAME({record_id})") + raise ValueError(f"Incorrect MODULESTREAMNAME({record_id}, {size})") module_data["stream_name"] = value record_size += size * 3 + 6 record_id, size, = struct.unpack_from( From 8c82604e111cc7c423a4604b0c43e7cd7da98ef6 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 17:24:31 -0400 Subject: [PATCH 108/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 0131e63ef..862e4cdc1 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -265,7 +265,8 @@ def from_bytes(data: bytes) -> Parameters: value, record_id, size2, value = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) if record_id != 0x1a or size2 != size * 2: - raise ValueError(f"Incorrect MODULESTREAMNAME({record_id}, {size})") + raise ValueError( + f"Incorrect MODULESTREAMNAME({record_id}, {size})") module_data["stream_name"] = value record_size += size * 3 + 6 record_id, size, = struct.unpack_from( From c722e221a864548fb48feb1ed4ffa393a1e5d746 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 17:33:27 -0400 Subject: [PATCH 109/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 862e4cdc1..0634a0aeb 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -257,6 +257,8 @@ def from_bytes(data: bytes) -> Parameters: value, r2, s2, v2 = struct.unpack_from( f"<{size}sHI{size*2}s", data, offset + record_size) record_size += size * 3 + 6 + if record_id != 0x19 or r2 != 0x47 or s2 != size * 2: + f"Incorrect MODULENAME({record_id}, {size})") # validate sizes and that values match module_data["name"] = value record_id, size, = struct.unpack_from( From 04e9f99cef163b6e5646c406cfafee4a7c35b582 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 17:35:35 -0400 Subject: [PATCH 110/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 0634a0aeb..5b2bf9f9a 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -258,7 +258,8 @@ def from_bytes(data: bytes) -> Parameters: f"<{size}sHI{size*2}s", data, offset + record_size) record_size += size * 3 + 6 if record_id != 0x19 or r2 != 0x47 or s2 != size * 2: - f"Incorrect MODULENAME({record_id}, {size})") + raise ValueError( + f"Incorrect MODULENAME({record_id}, {size})") # validate sizes and that values match module_data["name"] = value record_id, size, = struct.unpack_from( From d37c62ca568fb6a9d57243a669e8abc6db10b310 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 17:47:12 -0400 Subject: [PATCH 111/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 5b2bf9f9a..1f459993a 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -265,9 +265,9 @@ def from_bytes(data: bytes) -> Parameters: record_id, size, = struct.unpack_from( " Date: Sat, 4 Apr 2026 21:52:40 -0400 Subject: [PATCH 112/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index 1f459993a..f440ee291 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -254,17 +254,20 @@ def from_bytes(data: bytes) -> Parameters: record_size = 0 record_id, size = struct.unpack_from(" Date: Sat, 4 Apr 2026 21:58:44 -0400 Subject: [PATCH 113/115] Update dir --- tests/blank/dir | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/blank/dir b/tests/blank/dir index 59d68ba7f..2d8cf67d4 100644 --- a/tests/blank/dir +++ b/tests/blank/dir @@ -32,10 +32,12 @@ 000001A0 4D 53 4F 2E 44 4C 4C 23 4D 69 63 72 6F 73 6F 66 MSO.DLL#Microsof 000001B0 74 20 4F 66 66 69 63 65 20 31 36 2E 30 20 4F 62 t Office 16.0 Ob 000001C0 6A 65 63 74 20 4C 69 62 72 61 72 79 00 00 00 00 ject Library.... -000001D0 00 00 0F 00 02 00 00 00 03 00 13 00 02 00 00 00 ................ -000001E0 F3 08 19 00 0C 00 00 00 54 68 69 73 57 6F 72 6B ó.......ThisWork -000001F0 62 6F 6F 6B 47 00 18 00 00 00 54 00 68 00 69 00 bookG.....T.h.i. -00000200 73 00 57 00 6F 00 72 00 6B 00 62 00 6F 00 6F 00 s.W.o.r.k.b.o.o. +000001D0 00 00 0F 00 02 00 00 00 03 00 +13 00 02 00 00 00 F3 08 ......ó. +19 00 0C 00 00 00 54 68 69 73 57 6F 72 6B 62 6F ......ThisWorkbo +6F 6B ok +47 00 18 00 00 00 54 00 68 00 69 00 73 00 57 00 G.....T.h.i.s.W. + 6F 00 72 00 6B 00 62 00 6F 00 6F 00 o.r.k.b.o.o. 00000210 6B 00 1A 00 0C 00 00 00 54 68 69 73 57 6F 72 6B k.......ThisWork 00000220 62 6F 6F 6B 32 00 18 00 00 00 54 00 68 00 69 00 book2.....T.h.i. 00000230 73 00 57 00 6F 00 72 00 6B 00 62 00 6F 00 6F 00 s.W.o.r.k.b.o.o. From 38125ed1a46ff01a3806a19d526ff94142a8ede3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Sat, 4 Apr 2026 23:45:07 -0400 Subject: [PATCH 114/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index f440ee291..bef7fec22 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -265,9 +265,12 @@ def from_bytes(data: bytes) -> Parameters: raise ValueError( f"Incorrect MODULENAMEUNICODE({record_id})") # validate sizes and that values match - value, record_id, size, = struct.unpack_from( - f"<{size}sHI", data, offset + record_size) - record_size += 6 + size + value, struct.unpack_from( + f"<{size}s", data, offset + record_size) + record_size += size + record_id, size, = struct.unpack_from( + " Date: Sat, 4 Apr 2026 23:46:29 -0400 Subject: [PATCH 115/115] Update dirStream.py --- src/ms_ovba/Views/dirStream.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ms_ovba/Views/dirStream.py b/src/ms_ovba/Views/dirStream.py index bef7fec22..2eccbb451 100644 --- a/src/ms_ovba/Views/dirStream.py +++ b/src/ms_ovba/Views/dirStream.py @@ -270,7 +270,7 @@ def from_bytes(data: bytes) -> Parameters: record_size += size record_id, size, = struct.unpack_from( "