Coverage for sources/mimeogram/fsprotect/windows.py: 0%
72 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-03 00:13 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-03 00:13 +0000
1# vim: set filetype=python fileencoding=utf-8:
2# -*- coding: utf-8 -*-
4#============================================================================#
5# #
6# Licensed under the Apache License, Version 2.0 (the "License"); #
7# you may not use this file except in compliance with the License. #
8# You may obtain a copy of the License at #
9# #
10# http://www.apache.org/licenses/LICENSE-2.0 #
11# #
12# Unless required by applicable law or agreed to in writing, software #
13# distributed under the License is distributed on an "AS IS" BASIS, #
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15# See the License for the specific language governing permissions and #
16# limitations under the License. #
17# #
18#============================================================================#
21''' Sensitive filesystem locations on Windows. '''
24from __future__ import annotations
26from . import __
29_scribe = __.produce_scribe( __name__ )
32CSIDL_PROGRAM_FILES_COMMON = 0x002b # C:\Program Files\Common Files
33CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c # C:\Program Files (x86)\Common Files
36def discover_system_paths( ) -> frozenset[ __.Path ]:
37 ''' Discovers system paths via standard Windows mechanisms. '''
38 paths: set[ __.Path ] = set( )
39 paths.update( _discover_system_paths_via_environment( ) )
40 paths.update( _discover_system_paths_via_api( ) )
41 # TODO? Cygwin
42 if _detect_mingw( ): _discover_add_mingw_system_paths( paths )
43 return frozenset( paths )
46def _detect_mingw( ) -> bool:
47 ''' Checks if running in MinGW environment. '''
48 # TODO: If environment vars are not set, then return False.
49 # Else, proceed to more expensive checck to ensure sane MinGW.
50 mingw_env = __.os.environ.get( 'MSYSTEM', '' )
51 if mingw_env.startswith( ('MINGW', 'MSYS') ):
52 _scribe.debug( f'MinGW detected via MSYSTEM={mingw_env}' )
53 return True
54 mingw_paths = ( '/mingw32', '/mingw64', '/msys', '/usr/bin/msys-2.0.dll' )
55 for path in mingw_paths:
56 if not __.Path( path ).exists( ): continue
57 _scribe.debug( f'MinGW detected via path: {path}' )
58 return True
59 return False
62def _discover_add_mingw_system_paths( paths: set[ __.Path ] ) -> None:
63 paths_: set[ __.Path ] = set( )
64 for path in paths:
65 parts = path.parts
66 if 1 >= len( parts ): continue
67 drive = parts[ 0 ][ 0 ].lower( ) # TODO? Consider UNC paths.
68 paths_.add( __.Path( f"/{drive}" ).joinpath( *parts[ 1 : ] ) )
69 _scribe.debug(
70 "Calculated {} MingGW system paths.".format( len( paths_ ) ) )
71 paths_.update( map(
72 __.Path,
73 ( '/bin', '/dev', '/etc',
74 '/mingw32', '/mingw64', '/msys', '/proc', '/usr',
75 ) ) )
76 paths.update( paths_ )
79def _discover_system_paths_via_environment( ) -> frozenset[ __.Path ]:
80 ''' Discovers system paths via environment. '''
81 environ = __.os.environ
82 paths: set[ __.Path ] = set( )
83 system_drive = environ.get( 'SystemDrive', 'C:' )
84 system_root = environ.get( 'SystemRoot', f"{system_drive}\\Windows" )
85 paths.add( __.Path( system_root ) )
86 paths.add( __.Path( f"{system_drive}/System Volume Information" ) )
87 # Program Files variations
88 progfiles = __.os.environ.get(
89 'ProgramFiles', f"{system_drive}\\Program Files" )
90 paths.add( __.Path( progfiles ) )
91 for progfiles_ename in (
92 'ProgramFiles(x86)', 'ProgramFiles(Arm)', 'ProgramW6432'
93 ):
94 progfiles = environ.get( progfiles_ename )
95 if progfiles: paths.add( __.Path( progfiles ) )
96 return frozenset( paths )
99def _discover_system_paths_via_api( ) -> set[ __.Path ]:
100 ''' Discovers system paths via API. '''
101 import ctypes
102 from ctypes.wintypes import MAX_PATH
103 dmessage = "Could not retrieve additional Windows system paths via API."
104 paths: set[ __.Path ] = set( )
105 try: dll = ctypes.windll.shell32 # pyright: ignore
106 except Exception: # pylint: disable=broad-exception-caught
107 _scribe.debug( dmessage )
108 buf = ctypes.create_unicode_buffer( MAX_PATH + 1 )
109 for key in (
110 CSIDL_PROGRAM_FILES_COMMON,
111 CSIDL_PROGRAM_FILES_COMMONX86,
112 ):
113 try:
114 dll.SHGetFolderPathW( # pyright: ignore
115 None, key, None, 0, buf )
116 paths.add( __.Path( buf.value ) )
117 except Exception: # pylint: disable=broad-exception-caught
118 _scribe.debug( dmessage )
119 return paths
122def discover_user_paths( ) -> frozenset[ __.Path ]:
123 ''' Discovers Windows user-specific paths that should be protected. '''
124 paths: set[ __.Path ] = set( )
125 appdata = __.os.environ.get( 'APPDATA' )
126 local_appdata = __.os.environ.get( 'LOCALAPPDATA' )
127 userprofile = __.os.environ.get( 'USERPROFILE' )
128 if appdata: paths.add( __.Path( appdata ) )
129 if local_appdata: paths.add( __.Path( local_appdata ) )
130 if userprofile:
131 profile = __.Path( userprofile )
132 paths.update( (
133 profile / 'AppData' / 'Local',
134 profile / 'AppData' / 'LocalLow',
135 profile / 'AppData' / 'Roaming',
136 # Legacy Paths
137 profile / 'Application Data',
138 profile / 'Local Settings',
139 ) )
140 return frozenset( paths )