Coverage for sources/mimeogram/fsprotect/windows.py: 0%

72 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-19 23:01 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

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#============================================================================# 

19 

20 

21''' Sensitive filesystem locations on Windows. ''' 

22 

23 

24from __future__ import annotations 

25 

26from . import __ 

27 

28 

29_scribe = __.produce_scribe( __name__ ) 

30 

31 

32CSIDL_PROGRAM_FILES_COMMON = 0x002b # C:\Program Files\Common Files 

33CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c # C:\Program Files (x86)\Common Files 

34 

35 

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 ) 

44 

45 

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 

60 

61 

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_ ) 

77 

78 

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 ) 

97 

98 

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 

120 

121 

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 )