123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- #-----------------------------------------------------------------------------
- # Copyright (c) 2013-2021, PyInstaller Development Team.
- #
- # Distributed under the terms of the GNU General Public License (version 2
- # or later) with exception for distributing the bootloader.
- #
- # The full license is in the file COPYING.txt, distributed with this software.
- #
- # SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
- #-----------------------------------------------------------------------------
- """
- Utilities for Windows platform.
- """
- import os
- import sys
- import PyInstaller.log as logging
- from PyInstaller import compat
- logger = logging.getLogger(__name__)
- def get_windows_dir():
- """
- Return the Windows directory, e.g., C:\\Windows.
- """
- # Imported here to avoid circular import.
- from PyInstaller import compat
- windir = compat.win32api.GetWindowsDirectory()
- if not windir:
- raise SystemExit("Error: Cannot determine Windows directory!")
- return windir
- def get_system_path():
- """
- Return the required Windows system paths.
- """
- # Imported here to avoid circular import.
- from PyInstaller import compat
- _bpath = []
- sys_dir = compat.win32api.GetSystemDirectory()
- # Ensure C:\Windows\system32 and C:\Windows directories are always present in PATH variable.
- # C:\Windows\system32 is valid even for 64-bit Windows. Access do DLLs are transparently redirected to
- # C:\Windows\syswow64 for 64bit applactions.
- # See http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx
- _bpath = [sys_dir, get_windows_dir()]
- return _bpath
- def extend_system_path(paths):
- """
- Add new paths at the beginning of environment variable PATH.
- Some hooks might extend PATH where PyInstaller should look for dlls.
- """
- # imported here to avoid circular import
- from PyInstaller import compat
- old_path = compat.getenv('PATH', '')
- paths.append(old_path)
- new_path = os.pathsep.join(paths)
- compat.setenv('PATH', new_path)
- def import_pywin32_module(module_name):
- """
- Import and return the PyWin32 module with the passed name.
- When imported, the `pywintypes` and `pythoncom` modules both internally import dynamic libraries
- (e.g., `pywintypes.py` imports `pywintypes34.dll` under Python 3.4). The Anaconda Python distribution for Windows
- installs these libraries to non-standard directories, resulting in
- `"ImportError: No system module 'pywintypes' (pywintypes34.dll)"`
- exceptions. This function catches these exceptions, searches for these libraries, adds their directories to
- `sys.path`, and retries.
- Parameters
- ----------
- module_name : str
- Fully-qualified name of this module.
- Returns
- ----------
- types.ModuleType
- The desired module.
- """
- module = None
- try:
- module = __import__(module_name, globals={}, locals={}, fromlist=[''])
- except ImportError as exc:
- if str(exc).startswith('No system module'):
- # True if "sys.frozen" is currently set.
- is_sys_frozen = hasattr(sys, 'frozen')
- # Current value of "sys.frozen" if any.
- sys_frozen = getattr(sys, 'frozen', None)
- # Force PyWin32 to search "sys.path" for DLLs. By default, PyWin32 only searches "site-packages\win32\lib",
- # "sys.prefix", and Windows system directories (e.g., "C:\Windows\System32"). This is an ugly hack, but
- # there is no other way.
- sys.frozen = '|_|GLYH@CK'
- # If isolated to a venv, the preferred site.getsitepackages() function is unreliable. Fall back to searching
- # "sys.path" instead.
- if compat.is_venv:
- sys_paths = sys.path
- else:
- sys_paths = compat.getsitepackages()
- for sys_path in sys_paths:
- # Absolute path of the directory containing PyWin32 DLLs.
- pywin32_dll_dir = os.path.join(sys_path, 'pywin32_system32')
- if os.path.isdir(pywin32_dll_dir):
- sys.path.append(pywin32_dll_dir)
- try:
- module = __import__(name=module_name, globals={}, locals={}, fromlist=[''])
- break
- except ImportError:
- pass
- # If "sys.frozen" was previously set, restore its prior value.
- if is_sys_frozen:
- sys.frozen = sys_frozen
- # Else, undo this hack entirely.
- else:
- del sys.frozen
- # If this module remains unimportable, PyWin32 is not installed. Fail.
- if module is None:
- raise
- return module
- def convert_dll_name_to_str(dll_name):
- """
- Convert dll names from 'bytes' to 'str'.
- Latest pefile returns type 'bytes'.
- :param dll_name:
- :return:
- """
- # Imported here to avoid circular import.
- if isinstance(dll_name, bytes):
- return str(dll_name, encoding='UTF-8')
- else:
- return dll_name
- def fixup_exe_headers(exe_path, timestamp=None):
- """
- Set executable's checksum and build timestamp in its headers.
- This optional checksum is supposed to protect the executable against corruption but some anti-viral software have
- taken to flagging anything without it set correctly as malware. See issue #5579.
- """
- import pefile
- pe = pefile.PE(exe_path, fast_load=False) # full load because we need all headers
- # Set build timestamp.
- # See: https://0xc0decafe.com/malware-analyst-guide-to-pe-timestamps
- if timestamp is not None:
- timestamp = int(timestamp)
- # Set timestamp field in FILE_HEADER
- pe.FILE_HEADER.TimeDateStamp = timestamp
- # MSVC-compiled executables contain (at least?) one DIRECTORY_ENTRY_DEBUG entry that also contains timestamp
- # with same value as set in FILE_HEADER. So modify that as well, as long as it is set.
- debug_entries = getattr(pe, 'DIRECTORY_ENTRY_DEBUG', [])
- for debug_entry in debug_entries:
- if debug_entry.struct.TimeDateStamp:
- debug_entry.struct.TimeDateStamp = timestamp
- # Set PE checksum
- pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
- pe.close()
- pe.write(exe_path)
|