Source code for winspsrc.resource_file

"""Windows Resource file."""

import logging

import pyexe
import pywrc


[docs] class WindowsResourceFile: """Windows Resource file. Attributes: windows_path (str): Windows path of the resource file. """ _VERSION_INFORMATION_RESOURCE_IDENTIFIER = 0x10
[docs] def __init__( self, windows_path, ascii_codepage="cp1252", preferred_language_identifier=0x0409, ): """Initializes the Windows Resource file. Args: windows_path (str): normalized version of the Windows path. ascii_codepage (Optional[str]): ASCII string codepage. preferred_language_identifier (Optional[int]): preferred language identifier (LCID). """ super().__init__() self._ascii_codepage = ascii_codepage self._exe_file = pyexe.file() self._exe_file.set_ascii_codepage(self._ascii_codepage) self._exe_section = None self._file_object = None self._file_version = None self._is_open = False self._preferred_language_identifier = preferred_language_identifier self._product_version = None # TODO: wrc stream set codepage? self._wrc_stream = pywrc.stream() self.windows_path = windows_path
def _GetVersionInformation(self): """Determines the file and product version.""" version_information_resource = self._GetVersionInformationResource() if not version_information_resource: return file_version = version_information_resource.file_version major_version = (file_version >> 48) & 0xFFFF minor_version = (file_version >> 32) & 0xFFFF build_number = (file_version >> 16) & 0xFFFF revision_number = file_version & 0xFFFF self._file_version = ( f"{major_version:d}.{minor_version:d}.{build_number:d}." f"{revision_number:d}" ) product_version = version_information_resource.product_version major_version = (product_version >> 48) & 0xFFFF minor_version = (product_version >> 32) & 0xFFFF build_number = (product_version >> 16) & 0xFFFF revision_number = product_version & 0xFFFF self._product_version = ( f"{major_version:d}.{minor_version:d}.{build_number:d}." f"{revision_number:d}" ) if file_version != product_version: logging.warning( f"Mismatch between file version: {self._file_version:s} and product " f"version: {self._product_version:s} in resource file: " f"{self.windows_path:s}." ) def _GetVersionInformationResource(self): """Retrieves the version information resource. Returns: pywrc.version_information_resource: version information resource or None if not available. """ preferred_wrc_resource_sub_item = None wrc_resource = self._wrc_stream.get_resource_by_identifier( self._VERSION_INFORMATION_RESOURCE_IDENTIFIER ) if wrc_resource: first_wrc_resource_sub_item = None for wrc_resource_item in wrc_resource.items: for wrc_resource_sub_item in wrc_resource_item.sub_items: if not first_wrc_resource_sub_item: first_wrc_resource_sub_item = wrc_resource_sub_item language_identifier = wrc_resource_sub_item.identifier if language_identifier == self._preferred_language_identifier: if not preferred_wrc_resource_sub_item: preferred_wrc_resource_sub_item = wrc_resource_sub_item if not preferred_wrc_resource_sub_item: preferred_wrc_resource_sub_item = first_wrc_resource_sub_item if not preferred_wrc_resource_sub_item: return None resource_data = preferred_wrc_resource_sub_item.read() version_information_resource = pywrc.version_information_resource() version_information_resource.copy_from_byte_stream(resource_data) return version_information_resource @property def file_version(self): """str: the file version.""" if self._file_version is None: self._GetVersionInformation() return self._file_version @property def product_version(self): """str: the product version.""" if self._product_version is None: self._GetVersionInformation() return self._product_version
[docs] def Close(self): """Closes the Windows Resource file. Raises: OSError: if not open. """ if not self._is_open: raise OSError("Not opened.") if self._exe_section: self._wrc_stream.close() self._exe_file.close() self._file_object = None self._is_open = False
[docs] def OpenFileObject(self, file_object): """Opens the Windows Resource file using a file-like object. Args: file_object (file): file-like object. Raises: OSError: if already open. """ if self._is_open: raise OSError("Already open.") self._exe_file.open_file_object(file_object) self._exe_section = self._exe_file.get_section_by_name(".rsrc") if self._exe_section: self._wrc_stream.set_virtual_address(self._exe_section.virtual_address) self._wrc_stream.open_file_object(self._exe_section) self._file_object = file_object self._is_open = True