atomicshop 2.11.47__py3-none-any.whl → 3.10.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
  3. atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
  4. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  5. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  6. atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  7. atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
  8. atomicshop/a_mains/dns_gateway_setting.py +11 -0
  9. atomicshop/a_mains/get_local_tcp_ports.py +85 -0
  10. atomicshop/a_mains/github_wrapper.py +11 -0
  11. atomicshop/a_mains/install_ca_certificate.py +172 -0
  12. atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
  13. atomicshop/a_mains/process_from_port.py +119 -0
  14. atomicshop/a_mains/set_default_dns_gateway.py +90 -0
  15. atomicshop/a_mains/update_config_toml.py +38 -0
  16. atomicshop/appointment_management.py +5 -3
  17. atomicshop/basics/ansi_escape_codes.py +3 -1
  18. atomicshop/basics/argparse_template.py +2 -0
  19. atomicshop/basics/booleans.py +27 -30
  20. atomicshop/basics/bytes_arrays.py +43 -0
  21. atomicshop/basics/classes.py +149 -1
  22. atomicshop/basics/dicts.py +12 -0
  23. atomicshop/basics/enums.py +2 -2
  24. atomicshop/basics/exceptions.py +5 -1
  25. atomicshop/basics/list_of_classes.py +29 -0
  26. atomicshop/basics/list_of_dicts.py +69 -5
  27. atomicshop/basics/lists.py +14 -0
  28. atomicshop/basics/multiprocesses.py +374 -50
  29. atomicshop/basics/package_module.py +10 -0
  30. atomicshop/basics/strings.py +160 -7
  31. atomicshop/basics/threads.py +14 -0
  32. atomicshop/basics/tracebacks.py +13 -4
  33. atomicshop/certificates.py +153 -52
  34. atomicshop/config_init.py +12 -7
  35. atomicshop/console_user_response.py +7 -14
  36. atomicshop/consoles.py +9 -0
  37. atomicshop/datetimes.py +98 -0
  38. atomicshop/diff_check.py +340 -40
  39. atomicshop/dns.py +128 -12
  40. atomicshop/etws/_pywintrace_fix.py +17 -0
  41. atomicshop/etws/const.py +38 -0
  42. atomicshop/etws/providers.py +21 -0
  43. atomicshop/etws/sessions.py +43 -0
  44. atomicshop/etws/trace.py +168 -0
  45. atomicshop/etws/traces/trace_dns.py +162 -0
  46. atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
  47. atomicshop/etws/traces/trace_tcp.py +130 -0
  48. atomicshop/file_io/csvs.py +222 -24
  49. atomicshop/file_io/docxs.py +35 -18
  50. atomicshop/file_io/file_io.py +35 -19
  51. atomicshop/file_io/jsons.py +49 -0
  52. atomicshop/file_io/tomls.py +139 -0
  53. atomicshop/filesystem.py +864 -293
  54. atomicshop/get_process_list.py +133 -0
  55. atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
  56. atomicshop/http_parse.py +149 -93
  57. atomicshop/ip_addresses.py +6 -1
  58. atomicshop/mitm/centered_settings.py +132 -0
  59. atomicshop/mitm/config_static.py +207 -0
  60. atomicshop/mitm/config_toml_editor.py +55 -0
  61. atomicshop/mitm/connection_thread_worker.py +875 -357
  62. atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
  63. atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
  64. atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
  65. atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
  66. atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
  67. atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
  68. atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
  69. atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
  70. atomicshop/mitm/engines/create_module_template.py +58 -14
  71. atomicshop/mitm/import_config.py +359 -139
  72. atomicshop/mitm/initialize_engines.py +160 -74
  73. atomicshop/mitm/message.py +64 -23
  74. atomicshop/mitm/mitm_main.py +892 -0
  75. atomicshop/mitm/recs_files.py +183 -0
  76. atomicshop/mitm/shared_functions.py +4 -10
  77. atomicshop/mitm/ssh_tester.py +82 -0
  78. atomicshop/mitm/statistic_analyzer.py +257 -166
  79. atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
  80. atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
  81. atomicshop/monitor/change_monitor.py +96 -120
  82. atomicshop/monitor/checks/dns.py +139 -70
  83. atomicshop/monitor/checks/file.py +77 -0
  84. atomicshop/monitor/checks/network.py +81 -77
  85. atomicshop/monitor/checks/process_running.py +33 -34
  86. atomicshop/monitor/checks/url.py +94 -0
  87. atomicshop/networks.py +671 -0
  88. atomicshop/on_exit.py +205 -0
  89. atomicshop/package_mains_processor.py +84 -0
  90. atomicshop/permissions/permissions.py +22 -0
  91. atomicshop/permissions/ubuntu_permissions.py +239 -0
  92. atomicshop/permissions/win_permissions.py +33 -0
  93. atomicshop/print_api.py +24 -41
  94. atomicshop/process.py +63 -17
  95. atomicshop/process_poller/__init__.py +0 -0
  96. atomicshop/process_poller/pollers/__init__.py +0 -0
  97. atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
  98. atomicshop/process_poller/process_pool.py +207 -0
  99. atomicshop/process_poller/simple_process_pool.py +311 -0
  100. atomicshop/process_poller/tracer_base.py +45 -0
  101. atomicshop/process_poller/tracers/__init__.py +0 -0
  102. atomicshop/process_poller/tracers/event_log.py +46 -0
  103. atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
  104. atomicshop/python_file_patcher.py +1 -1
  105. atomicshop/python_functions.py +27 -75
  106. atomicshop/question_answer_engine.py +2 -2
  107. atomicshop/scheduling.py +24 -5
  108. atomicshop/sound.py +4 -2
  109. atomicshop/speech_recognize.py +8 -0
  110. atomicshop/ssh_remote.py +158 -172
  111. atomicshop/startup/__init__.py +0 -0
  112. atomicshop/startup/win/__init__.py +0 -0
  113. atomicshop/startup/win/startup_folder.py +53 -0
  114. atomicshop/startup/win/task_scheduler.py +119 -0
  115. atomicshop/system_resource_monitor.py +61 -46
  116. atomicshop/system_resources.py +8 -8
  117. atomicshop/tempfiles.py +1 -2
  118. atomicshop/timer.py +30 -11
  119. atomicshop/urls.py +41 -0
  120. atomicshop/venvs.py +28 -0
  121. atomicshop/versioning.py +27 -0
  122. atomicshop/web.py +110 -25
  123. atomicshop/web_apis/__init__.py +0 -0
  124. atomicshop/web_apis/google_custom_search.py +44 -0
  125. atomicshop/web_apis/google_llm.py +188 -0
  126. atomicshop/websocket_parse.py +450 -0
  127. atomicshop/wrappers/certauthw/certauth.py +1 -0
  128. atomicshop/wrappers/cryptographyw.py +29 -8
  129. atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
  130. atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
  131. atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
  132. atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
  133. atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
  134. atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
  135. atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
  136. atomicshop/wrappers/ctyping/setup_device.py +466 -0
  137. atomicshop/wrappers/ctyping/win_console.py +39 -0
  138. atomicshop/wrappers/dockerw/dockerw.py +113 -2
  139. atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
  140. atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
  141. atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
  142. atomicshop/wrappers/factw/get_file_data.py +12 -5
  143. atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
  144. atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
  145. atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
  146. atomicshop/wrappers/githubw.py +583 -51
  147. atomicshop/wrappers/loggingw/consts.py +49 -0
  148. atomicshop/wrappers/loggingw/filters.py +102 -0
  149. atomicshop/wrappers/loggingw/formatters.py +58 -71
  150. atomicshop/wrappers/loggingw/handlers.py +459 -40
  151. atomicshop/wrappers/loggingw/loggers.py +19 -0
  152. atomicshop/wrappers/loggingw/loggingw.py +1010 -178
  153. atomicshop/wrappers/loggingw/reading.py +344 -19
  154. atomicshop/wrappers/mongodbw/__init__.py +0 -0
  155. atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
  156. atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
  157. atomicshop/wrappers/netshw.py +271 -0
  158. atomicshop/wrappers/playwrightw/engine.py +34 -19
  159. atomicshop/wrappers/playwrightw/infra.py +5 -0
  160. atomicshop/wrappers/playwrightw/javascript.py +7 -3
  161. atomicshop/wrappers/playwrightw/keyboard.py +14 -0
  162. atomicshop/wrappers/playwrightw/scenarios.py +172 -5
  163. atomicshop/wrappers/playwrightw/waits.py +9 -7
  164. atomicshop/wrappers/powershell_networking.py +80 -0
  165. atomicshop/wrappers/psutilw/processes.py +81 -0
  166. atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
  167. atomicshop/wrappers/psutilw/psutilw.py +9 -0
  168. atomicshop/wrappers/pyopensslw.py +9 -2
  169. atomicshop/wrappers/pywin32w/__init__.py +0 -0
  170. atomicshop/wrappers/pywin32w/cert_store.py +116 -0
  171. atomicshop/wrappers/pywin32w/console.py +34 -0
  172. atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
  173. atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
  174. atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
  175. atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
  176. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
  177. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
  178. atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
  179. atomicshop/wrappers/pywin32w/winshell.py +19 -0
  180. atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
  181. atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
  182. atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
  183. atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
  184. atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
  185. atomicshop/wrappers/socketw/accepter.py +21 -7
  186. atomicshop/wrappers/socketw/certificator.py +216 -150
  187. atomicshop/wrappers/socketw/creator.py +190 -50
  188. atomicshop/wrappers/socketw/dns_server.py +500 -173
  189. atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
  190. atomicshop/wrappers/socketw/process_getter.py +86 -0
  191. atomicshop/wrappers/socketw/receiver.py +144 -102
  192. atomicshop/wrappers/socketw/sender.py +65 -35
  193. atomicshop/wrappers/socketw/sni.py +334 -165
  194. atomicshop/wrappers/socketw/socket_base.py +134 -0
  195. atomicshop/wrappers/socketw/socket_client.py +137 -95
  196. atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
  197. atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
  198. atomicshop/wrappers/socketw/ssl_base.py +15 -14
  199. atomicshop/wrappers/socketw/statistics_csv.py +148 -17
  200. atomicshop/wrappers/sysmonw.py +157 -0
  201. atomicshop/wrappers/ubuntu_terminal.py +65 -26
  202. atomicshop/wrappers/win_auditw.py +189 -0
  203. atomicshop/wrappers/winregw/__init__.py +0 -0
  204. atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
  205. atomicshop/wrappers/winregw/winreg_network.py +232 -0
  206. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
  207. atomicshop-3.10.5.dist-info/RECORD +306 -0
  208. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
  209. atomicshop/_basics_temp.py +0 -101
  210. atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
  211. atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
  212. atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
  213. atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
  214. atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
  215. atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
  216. atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
  217. atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
  218. atomicshop/addons/package_setup/Setup.cmd +0 -7
  219. atomicshop/addons/process_list/compile.cmd +0 -2
  220. atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
  221. atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
  222. atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
  223. atomicshop/archiver/_search_in_zip.py +0 -189
  224. atomicshop/archiver/archiver.py +0 -34
  225. atomicshop/archiver/search_in_archive.py +0 -250
  226. atomicshop/archiver/sevenz_app_w.py +0 -86
  227. atomicshop/archiver/sevenzs.py +0 -44
  228. atomicshop/archiver/zips.py +0 -293
  229. atomicshop/etw/dns_trace.py +0 -118
  230. atomicshop/etw/etw.py +0 -61
  231. atomicshop/file_types.py +0 -24
  232. atomicshop/mitm/engines/create_module_template_example.py +0 -13
  233. atomicshop/mitm/initialize_mitm_server.py +0 -240
  234. atomicshop/monitor/checks/hash.py +0 -44
  235. atomicshop/monitor/checks/hash_checks/file.py +0 -55
  236. atomicshop/monitor/checks/hash_checks/url.py +0 -62
  237. atomicshop/pbtkmultifile_argparse.py +0 -88
  238. atomicshop/permissions.py +0 -110
  239. atomicshop/process_poller.py +0 -237
  240. atomicshop/script_as_string_processor.py +0 -38
  241. atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
  242. atomicshop/ssh_scripts/process_from_port.py +0 -27
  243. atomicshop/wrappers/_process_wrapper_curl.py +0 -27
  244. atomicshop/wrappers/_process_wrapper_tar.py +0 -21
  245. atomicshop/wrappers/dockerw/install_docker.py +0 -209
  246. atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
  247. atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
  248. atomicshop/wrappers/ffmpegw.py +0 -125
  249. atomicshop/wrappers/loggingw/checks.py +0 -20
  250. atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
  251. atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
  252. atomicshop/wrappers/socketw/base.py +0 -59
  253. atomicshop/wrappers/socketw/get_process.py +0 -107
  254. atomicshop/wrappers/wslw.py +0 -191
  255. atomicshop-2.11.47.dist-info/RECORD +0 -251
  256. /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
  257. /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
  258. /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
  259. /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
  260. /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
  261. /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
  262. /atomicshop/{archiver → etws}/__init__.py +0 -0
  263. /atomicshop/{etw → etws/traces}/__init__.py +0 -0
  264. /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
  265. /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
  266. /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
  267. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
  268. {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,259 @@
1
+ from typing import Union
2
+ import socket
3
+ import time
4
+
5
+ from win32com.client import CDispatch
6
+ import pywintypes
7
+
8
+ from . import wmi_helpers, win32networkadapter
9
+ from .... import ip_addresses
10
+
11
+
12
+ def get_network_configuration_by_adapter(
13
+ adapter: CDispatch,
14
+ wmi_instance: CDispatch = None
15
+ ) -> Union[CDispatch, None]:
16
+ """
17
+ Get the network configuration for a specific adapter index.
18
+
19
+ :param adapter: CDispatch, Win32_NetworkAdapter object.
20
+ :param wmi_instance: WMI instance. You can get it from:
21
+ wmi_helpers.get_wmi_instance()
22
+ :return: Win32_NetworkAdapterConfiguration object.
23
+ """
24
+
25
+ network_config: CDispatch = wmi_instance.ExecQuery(
26
+ f"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index={adapter.Index}")[0]
27
+
28
+ return network_config
29
+
30
+
31
+ def get_adapter_network_configuration(
32
+ interface_name: str = None,
33
+ mac_address: str = None,
34
+ wmi_instance: CDispatch = None
35
+ ) -> tuple:
36
+ """
37
+ Get the WMI network configuration for a network adapter.
38
+ :param interface_name: string, adapter name as shown in the network settings.
39
+ :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
40
+ :param wmi_instance: WMI instance. You can get it from:
41
+ wrappers.pywin32s.wmis.wmi_helpers.get_wmi_instance()
42
+ or default will be used.
43
+ :return: tuple(Win32_NetworkAdapterConfiguration, Win32_NetworkAdapter)
44
+ """
45
+
46
+ if not wmi_instance:
47
+ wmi_instance, _ = wmi_helpers.get_wmi_instance()
48
+
49
+ adapters = win32networkadapter.list_network_adapters(wmi_instance)
50
+
51
+ if interface_name is None and mac_address is None:
52
+ raise ValueError("Either 'interface_name' or 'mac_address' must be provided.")
53
+ elif interface_name and mac_address:
54
+ raise ValueError("Only one of 'interface_name' or 'mac_address' must be provided.")
55
+
56
+ current_adapter = None
57
+ if interface_name:
58
+ for adapter in adapters:
59
+ if interface_name == adapter.NetConnectionID:
60
+ current_adapter = adapter
61
+ break
62
+
63
+ if not current_adapter:
64
+ raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with interface name '{interface_name}' not found.")
65
+ elif mac_address:
66
+ for adapter in adapters:
67
+ if mac_address == adapter.MACAddress:
68
+ current_adapter = adapter
69
+ break
70
+
71
+ if current_adapter is None:
72
+ raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with MAC address '{mac_address}' not found.")
73
+
74
+ # Query the network adapter configurations
75
+ query = f"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index='{current_adapter.DeviceID}'"
76
+ adapter_configs = wmi_instance.ExecQuery(query)
77
+
78
+ # Check if the adapter exists
79
+ if len(adapter_configs) == 0:
80
+ raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with interface name '{interface_name}' not found.")
81
+
82
+ return adapter_configs[0], current_adapter
83
+
84
+
85
+ def set_static_ips(
86
+ network_config: CDispatch, # Win32_NetworkAdapterConfiguration (CDispatch)
87
+ ips: list[str], # ["192.168.157.3", ...]
88
+ masks: list[str], # ["255.255.255.0", ...]
89
+ gateways: list[str] = None,
90
+ dns_gateways: list[str] = None,
91
+ availability_wait_seconds: int = 0
92
+ ) -> None:
93
+ """
94
+ • network_config – Win32_NetworkAdapterConfiguration instance for the target NIC
95
+ (you already have it from GetObject / WMI query).
96
+ • ips – list of IPv4 strings.
97
+ • masks – matching subnet‑mask list (same length as ipv4).
98
+ • gateways – list of default gateways (optional).
99
+ • dns_gateways – list of DNS servers (optional).
100
+ • availability_wait_seconds – seconds to wait for the adapter to become available.
101
+ 0 means no wait.
102
+
103
+ Raises RuntimeError if Windows reports anything other than success (0 / 1)
104
+ or "object already exists" (22) for each operation.
105
+
106
+ ==========
107
+
108
+ Example:
109
+ cfg = wmi_instance.Get("Win32_NetworkAdapterConfiguration.Index=12") # your adapter
110
+ set_static_ips(
111
+ cfg,
112
+ ipv4=["192.168.157.129", "192.168.157.3", "192.168.157.4"],
113
+ masks=["255.255.255.0"] * 3,
114
+ # gateways=["192.168.157.2"],
115
+ # dns_gateways=["8.8.8.8", "1.1.1.1"]
116
+ )
117
+ """
118
+
119
+ initial_default_ipv4: str = socket.gethostbyname(socket.gethostname())
120
+
121
+ # -------------------- IPv4 via EnableStatic ----------------------------
122
+ if not masks or len(ips) != len(masks):
123
+ raise ValueError("ipv4 and masks must be lists of equal length")
124
+
125
+ # # refresh the instance – state may have changed after the previous call
126
+ # network_config = network_config.Path_.GetObject_()
127
+
128
+ try:
129
+ in_params = network_config.Methods_("EnableStatic").InParameters.SpawnInstance_()
130
+ except pywintypes.com_error as e:
131
+ if e.excepinfo[1] == 'SWbemMethodSet' and 'Not found' in e.excepinfo[2]:
132
+ raise RuntimeError(f"Probably the adapter is already set to static non-DHCP.\n"
133
+ f"Failed to get [EnableStatic] method parameters: {e}\n")
134
+ else:
135
+ raise
136
+
137
+ in_params.IPAddress = ips
138
+ in_params.SubnetMask = masks
139
+
140
+ rc = network_config.ExecMethod_("EnableStatic", in_params).Properties_('ReturnValue').Value
141
+ if rc not in (0, 1): # 0 = reboot required, 1 = OK
142
+ raise RuntimeError(f"EnableStatic (IPv4) failed, code {rc}")
143
+
144
+ # -------------------- Default Gateway via SetGateways -------------------
145
+ if gateways:
146
+ gateway_metrics = [1] * len(gateways)
147
+ in_params = network_config.Methods_("SetGateways").InParameters.SpawnInstance_()
148
+ in_params.DefaultIPGateway = gateways
149
+ in_params.GatewayCostMetric = [int(m) for m in gateway_metrics]
150
+
151
+ rc = network_config.ExecMethod_("SetGateways", in_params) \
152
+ .Properties_('ReturnValue').Value
153
+ if rc not in (0, 1):
154
+ raise RuntimeError(f"SetGateways failed, code {rc}")
155
+
156
+ # -------------------- DNS via SetDNSServerSearchOrder ------------------
157
+ if dns_gateways:
158
+ in_params = network_config.Methods_("SetDNSServerSearchOrder").InParameters.SpawnInstance_()
159
+ in_params.DNSServerSearchOrder = dns_gateways
160
+
161
+ rc = network_config.ExecMethod_("SetDNSServerSearchOrder", in_params).Properties_('ReturnValue').Value
162
+ if rc not in (0, 1):
163
+ raise RuntimeError(f"SetDNSServerSearchOrder failed, code {rc}")
164
+
165
+ # -------------------- Wait for the adapter to become available -----------
166
+ if availability_wait_seconds > 0:
167
+ count = 0
168
+ while count < 15:
169
+ current_default_ipv4: str = socket.gethostbyname(socket.gethostname())
170
+ if current_default_ipv4 == initial_default_ipv4:
171
+ # print(f"[+] Adapter is available: {current_default_ipv4}")
172
+ break
173
+ else:
174
+ # print(f"[!] Adapter is not available yet: [{current_default_ipv4}]")
175
+ count += 1
176
+
177
+ time.sleep(1)
178
+
179
+
180
+ def set_dynamic_ip(
181
+ nic_cfg,
182
+ reset_dns: bool = True,
183
+ reset_wins: bool = True
184
+ ) -> None:
185
+ """
186
+ Switch the adapter represented by *nic_cfg* (a Win32_NetworkAdapterConfiguration
187
+ COM object) to DHCP.
188
+
189
+ Parameters
190
+ ----------
191
+ nic_cfg : CDispatch
192
+ The adapter’s Win32_NetworkAdapterConfiguration instance (IPEnabled = TRUE).
193
+ reset_dns : bool, default True
194
+ Also clear any static DNS servers (calls SetDNSServerSearchOrder(None)).
195
+ reset_wins : bool, default True
196
+ Also clear any static WINS servers (calls SetWINSServer(None, None)).
197
+
198
+ Raises
199
+ ------
200
+ RuntimeError
201
+ If any WMI call returns a status other than 0 (“Success”) or 1 (“Restart required”).
202
+ """
203
+
204
+ # 1) Turn on DHCP for IPv4
205
+ wmi_helpers.call_method(nic_cfg, 'EnableDHCP')
206
+
207
+ # 2) Clear static gateways (otherwise Windows keeps using them)
208
+ wmi_helpers.call_method(nic_cfg, 'SetGateways', ([], [])) # empty SAFEARRAY → remove gateways
209
+
210
+ # 3) Optional: reset DNS
211
+ if reset_dns:
212
+ wmi_helpers.call_method(nic_cfg, 'SetDNSServerSearchOrder', None) # None = DHCP-provided DNS
213
+
214
+ # 4) Optional: reset WINS
215
+ if reset_wins:
216
+ wmi_helpers.call_method(nic_cfg, 'SetWINSServer', ("", ""))
217
+
218
+
219
+ def get_info_from_network_config(
220
+ network_config: CDispatch
221
+ ) -> dict:
222
+ """
223
+ Collect information about adapter that currently carries the default route.
224
+
225
+ :param network_config: CDispatch, Win32_NetworkAdapterConfiguration object.
226
+ :return: dict of the default adapter.
227
+ """
228
+
229
+ def _split_ips(config):
230
+ """Split IPAddress[] into separate v4 / v6 lists."""
231
+ current_ipv4s: list[str] = []
232
+ current_ipv4_masks: list[str] = []
233
+ current_ipv6s: list[str] = []
234
+ current_ipv6_prefixes: list[int] = []
235
+ for address_index, ip_address in enumerate(config.IPAddress):
236
+ if ip_addresses.is_ip_address(ip_address, 'ipv4'):
237
+ current_ipv4s.append(ip_address)
238
+ current_ipv4_masks.append(config.IPSubnet[address_index])
239
+ elif ip_addresses.is_ip_address(ip_address, 'ipv6'):
240
+ current_ipv6s.append(ip_address)
241
+ current_ipv6_prefixes.append(int(config.IPSubnet[address_index]))
242
+
243
+ return current_ipv4s, current_ipv6s, current_ipv4_masks, current_ipv6_prefixes
244
+
245
+ ipv4s, ipv6s, ipv4subnets, ipv6prefixes = _split_ips(network_config)
246
+ adapter = {
247
+ "caption": network_config.Caption,
248
+ "description": network_config.Description,
249
+ "interface_index": network_config.InterfaceIndex,
250
+ "is_dynamic": bool(network_config.DHCPEnabled),
251
+ "ipv4s": ipv4s,
252
+ "ipv6s": ipv6s,
253
+ "ipv4_subnet_masks": ipv4subnets,
254
+ "ipv6_prefixes": ipv6prefixes,
255
+ "default_gateways": list(network_config.DefaultIPGateway or []),
256
+ "dns_gateways": list(network_config.DNSServerSearchOrder or []),
257
+ }
258
+
259
+ return adapter
@@ -0,0 +1,112 @@
1
+ from logging import Logger
2
+ from typing import Union
3
+
4
+ from win32com.client import CDispatch
5
+
6
+ from . import wmi_helpers, win32_networkadapterconfiguration
7
+ from ...psutilw import psutil_networks
8
+ from ....print_api import print_api
9
+
10
+
11
+ def list_network_adapters(wmi_instance: CDispatch = None) -> list[CDispatch]:
12
+ """
13
+ List all network adapters on the system, from the Win32_NetworkAdapter class.
14
+
15
+ :param wmi_instance: WMI instance. You can get it from:
16
+ wmi_helpers.get_wmi_instance()
17
+ :return: list of Win32_NetworkAdapter objects.
18
+ """
19
+
20
+ if not wmi_instance:
21
+ wmi_instance, _ = wmi_helpers.get_wmi_instance()
22
+
23
+ # Query all network adapters
24
+ adapters: list[CDispatch] = list(wmi_instance.ExecQuery("SELECT * FROM Win32_NetworkAdapter"))
25
+
26
+ # Print adapter descriptions
27
+ # for adapter in adapters:
28
+ # print(f"Description: {adapter.Description}, IPEnabled: {adapter.IPEnabled}")
29
+ return adapters
30
+
31
+
32
+ def get_network_adapter_by_device_name(
33
+ device_name: str,
34
+ wmi_instance: CDispatch = None
35
+ ) -> Union[CDispatch, None]:
36
+ """
37
+ Get a network adapter by its name.
38
+
39
+ :param device_name: string, adapter name as shown in the network settings.
40
+ :param wmi_instance: WMI instance. You can get it from:
41
+ wmi_helpers.get_wmi_instance()
42
+ :return: Win32_NetworkAdapter object.
43
+ """
44
+
45
+ if not wmi_instance:
46
+ wmi_instance, _ = wmi_helpers.get_wmi_instance()
47
+
48
+ query: str = (
49
+ "SELECT * FROM Win32_NetworkAdapter "
50
+ f"WHERE Name LIKE '{device_name}'")
51
+ adapters: list[CDispatch] = list(wmi_instance.ExecQuery(query))
52
+ if not adapters:
53
+ return None
54
+
55
+ return adapters[0]
56
+
57
+
58
+ def get_default_network_adapter(wmi_instance: CDispatch = None):
59
+ """
60
+ Get the default network adapter.
61
+
62
+ :param wmi_instance: WMI instance. You can get it from:
63
+ wmi_helpers.get_wmi_instance()
64
+ :return:
65
+ """
66
+
67
+ if not wmi_instance:
68
+ wmi_instance, _ = wmi_helpers.get_wmi_instance()
69
+
70
+ default_connection_name_dict: dict = psutil_networks.get_default_connection_name()
71
+ # Get the first key from the dictionary.
72
+ default_connection_name: str = list(default_connection_name_dict.keys())[0]
73
+ adapters: list[CDispatch] = list_network_adapters(wmi_instance)
74
+
75
+ for adapter in adapters:
76
+ if default_connection_name == adapter.NetConnectionID:
77
+ return adapter
78
+
79
+ raise wmi_helpers.WMINetworkAdapterNotFoundError("Default network adapter not found.")
80
+
81
+
82
+ def set_dns_server(
83
+ dns_servers: Union[list[str], None],
84
+ interface_name: str = None,
85
+ mac_address: str = None,
86
+ verbose: bool = False,
87
+ logger: Logger = None
88
+ ):
89
+ """
90
+ Set the DNS servers for a network adapter.
91
+ :param dns_servers: list of strings, DNS server IPv4 addresses.
92
+ None, if you want to remove the DNS servers and make the interface to obtain them automatically from DHCP.
93
+ list[str], if you want to set the DNS servers manually to the list of strings.
94
+ :param interface_name: string, network interface name as shown in the network settings.
95
+ :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
96
+
97
+ :param verbose: bool, if True, print verbose output.
98
+ :param logger: Logger object, if provided, will log the output instead of printing.
99
+ :return:
100
+ """
101
+
102
+ adapter_config, current_adapter = win32_networkadapterconfiguration.get_adapter_network_configuration(
103
+ interface_name=interface_name, mac_address=mac_address)
104
+
105
+ if verbose:
106
+ message = (
107
+ f"Adapter [{current_adapter.Description}], Connection name [{current_adapter.NetConnectionID}]\n"
108
+ f"Setting DNS servers to {dns_servers}")
109
+ print_api(message, color='blue', logger=logger)
110
+
111
+ # Set DNS servers
112
+ wmi_helpers.call_method(adapter_config, 'SetDNSServerSearchOrder', dns_servers)
@@ -0,0 +1,236 @@
1
+ import os
2
+ from typing import Union
3
+
4
+ import win32com.client
5
+ from win32com.client import CDispatch
6
+
7
+
8
+ class WmiMethodExecutionError(Exception):
9
+ pass
10
+
11
+
12
+ class WmiMethodParameterError(Exception):
13
+ pass
14
+
15
+
16
+ class EmptyValue:
17
+ pass
18
+ _EMPTY_VALUE = EmptyValue()
19
+
20
+
21
+ class WMINetworkAdapterNotFoundError(Exception):
22
+ pass
23
+
24
+
25
+ LOCAL_SERVER: str = '.'
26
+
27
+
28
+ def get_wmi_instance(
29
+ server: str = LOCAL_SERVER,
30
+ namespace: str = 'root\\cimv2',
31
+ wmi_instance: CDispatch = None,
32
+ locator: CDispatch = None
33
+ ) -> tuple[CDispatch, CDispatch]:
34
+ """
35
+ Get the WMI instance.
36
+
37
+ :param server: str, The server you want to connect to. Default is '.' (local machine).
38
+ :param namespace: str, WMI namespace. Default is 'root\\cimv2'.
39
+ Other examples:
40
+ 'root\\StandardCimv2'
41
+ :param wmi_instance: WMI connected instance.
42
+ :param locator: WMI locator instance. If not provided, a new one will be created.
43
+ :return: WMI instance.
44
+
45
+ ===================
46
+
47
+ If you want to connect directly to a WMI namespace, you can use the following code:
48
+ return win32com.client.GetObject(f"winmgmts:\\\\{location}\\{namespace}")
49
+ """
50
+
51
+ if not locator:
52
+ # This is a better way to get the WMI instance, since you have more control over the WMI object.
53
+ locator: CDispatch = win32com.client.Dispatch('WbemScripting.SWbemLocator')
54
+
55
+ if wmi_instance:
56
+ server_from_instance, namespace_from_instance = get_connection_details(wmi_instance)
57
+
58
+ # If current server name of the wmi connection is not the same as was passed to the function,
59
+ # then create a new connection to the server.
60
+ if server_from_instance.lower() != server.lower():
61
+ if not (server_from_instance.lower() == os.environ["COMPUTERNAME"].lower() and server.lower() == LOCAL_SERVER):
62
+ wmi_instance = locator.ConnectServer(server, namespace)
63
+ # If the namespace is not the same as was passed to the function.
64
+ if namespace_from_instance != namespace:
65
+ wmi_instance = locator.ConnectServer(server, namespace)
66
+
67
+ else:
68
+ wmi_instance: CDispatch = locator.ConnectServer(server, namespace)
69
+
70
+ return wmi_instance, locator
71
+
72
+
73
+ def get_connection_details(wmi_instance: CDispatch) -> tuple[str, str]:
74
+ """
75
+ Get the connection details: connected server and namespace.
76
+
77
+ :param wmi_instance: WMI instance.
78
+ :return: tuple of server and namespace.
79
+ """
80
+
81
+ # Get the current connection details.
82
+ # Get the security object for the WMI instance.
83
+ security_object: CDispatch = wmi_instance.Get("__SystemSecurity=@")
84
+ # Get the Paths.
85
+ path: CDispatch = security_object.Path_
86
+
87
+ server_from_instance: str = path.Server
88
+ namespace_from_instance: str = path.Namespace
89
+
90
+ return server_from_instance, namespace_from_instance
91
+
92
+
93
+ def get_method(
94
+ wmi_object: win32com.client.CDispatch,
95
+ method_name: str
96
+ ):
97
+ """
98
+ Get the WMI method.
99
+
100
+ :param wmi_object: WMI object.
101
+ :param method_name: str, name of the method.
102
+ :return: WMI method object.
103
+ """
104
+
105
+ return wmi_object.Methods_(method_name)
106
+
107
+
108
+ def get_method_parameter_instance(
109
+ method: win32com.client.CDispatch
110
+ ):
111
+ """
112
+ Get the WMI method parameter.
113
+
114
+ :param method: WMI method object.
115
+ :return: WMI method parameter object.
116
+ """
117
+
118
+ return method.inParameters.SpawnInstance_()
119
+
120
+
121
+ def call_method(
122
+ wmi_object: win32com.client.CDispatch,
123
+ method_name: str,
124
+ value: Union[
125
+ Union[tuple, dict],
126
+ Union[bool, str, list]] = _EMPTY_VALUE
127
+ ):
128
+ """
129
+ Call the WMI method.
130
+
131
+ :param wmi_object: WMI object.
132
+ :param method_name: str, name of the method.
133
+ :param value: tuple, value to pass to the method.
134
+ tuple: If ou pass a tuple, it will be unpacked and passed as positional arguments.
135
+ Dor example if a method requires 2 parameters, you can pass a tuple with 2 values.
136
+ dict: If you pass a dictionary, it will be unpacked and passed as keyword arguments.
137
+
138
+ If you pass a single value, which is not a dict or tuple, it will be passed as a single parameter.
139
+
140
+ Methods can receive a None value if they don't require any parameters.
141
+ If the method doesn't require any parameters, leave it as 'EmptyValue' class.
142
+ :return: WMI method object.
143
+ """
144
+
145
+ # Assign the single value to a tuple if it is not already a tuple or dict and not an EmptyValue.
146
+ if not isinstance(value, (EmptyValue, tuple, dict)):
147
+ value = (value,)
148
+
149
+ # Get the method instance out of the WMI object.
150
+ method = get_method(wmi_object, method_name)
151
+
152
+ # ── discover the method’s IN parameters up-front ─────────────────────────────
153
+ if method.InParameters:
154
+ input_properties: list = [(in_property.Name, in_property.IsArray) for in_property in method.InParameters.Properties_]
155
+ else:
156
+ input_properties: list = [] # no inputs expected
157
+
158
+ expected = len(input_properties) # how many inputs the method wants
159
+
160
+ got_tuple = isinstance(value, tuple)
161
+ got_dict = isinstance(value, dict)
162
+ got_empty = isinstance(value, EmptyValue)
163
+
164
+ # ── validate the caller’s intent ─────────────────────────────────────────────
165
+ if expected == 0 and not got_empty:
166
+ raise WmiMethodParameterError(
167
+ f"Method '{method_name}' takes no parameters, got: {value!r}"
168
+ )
169
+ if expected > 0 and got_empty:
170
+ raise WmiMethodParameterError(
171
+ f"Method '{method_name}' expects {expected} parameter(s); none given."
172
+ )
173
+ if got_tuple and len(value) != expected:
174
+ raise WmiMethodParameterError(
175
+ f"Method '{method_name}' expects {expected} parameter(s); "
176
+ f"{len(value)} positional value(s) given."
177
+ )
178
+
179
+ # ── prepare the parameter object if needed ──────────────────────────────────
180
+ if expected == 0: # simple – no inputs
181
+ result = wmi_object.ExecMethod_(method_name)
182
+
183
+ else:
184
+ param_obj = get_method_parameter_instance(method)
185
+
186
+ if got_tuple: # positional list / tuple
187
+ for (name, is_array), val in zip(input_properties, value):
188
+ setattr(param_obj, name, val)
189
+
190
+ elif got_dict: # mapping by name
191
+ for name, _ in input_properties:
192
+ if name in value:
193
+ setattr(param_obj, name, value[name])
194
+
195
+ else: # single scalar for one-input method
196
+ name, is_array = input_properties[0]
197
+ if is_array and not (isinstance(value, list) or value is None):
198
+ raise WmiMethodParameterError(
199
+ f"Parameter '{name}' must be a list.\nValue: {value!r}"
200
+ )
201
+ setattr(param_obj, name, value)
202
+
203
+ result = wmi_object.ExecMethod_(method_name, param_obj)
204
+
205
+ # ── collect OUT parameters & check return code ──────────────────────────────
206
+ out_vals = []
207
+ if method.OutParameters:
208
+ for parameter in method.OutParameters.Properties_:
209
+ out_vals.append(result.Properties_(parameter.Name).Value)
210
+
211
+ # return-code conventions: 0 = OK, 1 = OK-needs-reboot
212
+ if out_vals and out_vals[0] not in (0, 1):
213
+ result_code: int = out_vals[0]
214
+ if result_code == 91:
215
+ raise PermissionError(
216
+ f"Method '{method_name}' failed (code {result_code}) – try with admin rights."
217
+ )
218
+ if result_code == 68:
219
+ raise WmiMethodExecutionError(
220
+ f"Method '{method_name}' failed (code {result_code}) – Invalid input parameter"
221
+ )
222
+ raise WmiMethodExecutionError(
223
+ f"Method '{method_name}' failed with error code {result_code}"
224
+ )
225
+
226
+ return out_vals or None
227
+
228
+
229
+ """
230
+ # Setting SeDebugPrivilege
231
+ import win32security, ntsecuritycon, win32con, win32api
232
+ privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_DEBUG_NAME), win32con.SE_PRIVILEGE_ENABLED),)
233
+ hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), win32security.TOKEN_ALL_ACCESS)
234
+ win32security.AdjustTokenPrivileges(hToken, False, privs)
235
+ win32api.CloseHandle(hToken)
236
+ """
@@ -2,17 +2,21 @@ from . import exception_wrapper
2
2
 
3
3
 
4
4
  @exception_wrapper.connection_exception_decorator
5
- def accept_connection(socket_object, dns_domain, print_kwargs: dict = None):
5
+ def accept_connection(
6
+ socket_object,
7
+ domain_from_dns_server: str = None,
8
+ print_kwargs: dict = None
9
+ ):
6
10
  """
7
11
  Accept connection from client.
8
12
  This function is wrapped with exception wrapper.
9
13
  After you execute the function, you can get the error message if there was any with:
10
14
  error_message = accept_connection.message
11
15
 
12
- :param socket_object:
13
- :param dns_domain:
14
- :param print_kwargs:
15
- :return:
16
+ :param socket_object: The socket object to accept the connection on.
17
+ :param domain_from_dns_server: The domain that will be printed to console on logger, needed for the decorator.
18
+ If not provided, the TCP data will be used.
19
+ :param print_kwargs: Additional arguments for the print_api function, needed for the decorator.
16
20
  """
17
21
 
18
22
  client_socket = None
@@ -33,8 +37,18 @@ def accept_connection(socket_object, dns_domain, print_kwargs: dict = None):
33
37
  return client_socket, client_address_tuple
34
38
 
35
39
 
36
- def accept_connection_with_error(socket_object, dns_domain, print_kwargs: dict = None):
37
- client_socket, client_address_tuple = accept_connection(socket_object, dns_domain, print_kwargs=print_kwargs)
40
+ def accept_connection_with_error(
41
+ socket_object,
42
+ domain_from_dns_server,
43
+ print_kwargs: dict = None
44
+ ):
45
+ """
46
+ :param socket_object: The socket object to accept the connection on.
47
+ :param domain_from_dns_server: The domain that will be printed to console on logger.
48
+ :param print_kwargs: Additional arguments for the print_api function.
49
+ """
50
+ client_socket, client_address_tuple = accept_connection(
51
+ socket_object, domain_from_dns_server, print_kwargs=print_kwargs)
38
52
  error_message = accept_connection.message
39
53
 
40
54
  return client_socket, client_address_tuple, error_message