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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/a_mains/update_config_toml.py +38 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/dicts.py +12 -0
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/list_of_dicts.py +69 -5
- atomicshop/basics/lists.py +14 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/package_module.py +10 -0
- atomicshop/basics/strings.py +160 -7
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -4
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +12 -7
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +98 -0
- atomicshop/diff_check.py +340 -40
- atomicshop/dns.py +128 -12
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/const.py +38 -0
- atomicshop/etws/providers.py +21 -0
- atomicshop/etws/sessions.py +43 -0
- atomicshop/etws/trace.py +168 -0
- atomicshop/etws/traces/trace_dns.py +162 -0
- atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +222 -24
- atomicshop/file_io/docxs.py +35 -18
- atomicshop/file_io/file_io.py +35 -19
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +864 -293
- atomicshop/get_process_list.py +133 -0
- atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -74
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +257 -166
- atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
- atomicshop/monitor/change_monitor.py +96 -120
- atomicshop/monitor/checks/dns.py +139 -70
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/network.py +81 -77
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +205 -0
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -41
- atomicshop/process.py +63 -17
- atomicshop/process_poller/__init__.py +0 -0
- atomicshop/process_poller/pollers/__init__.py +0 -0
- atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
- atomicshop/process_poller/process_pool.py +207 -0
- atomicshop/process_poller/simple_process_pool.py +311 -0
- atomicshop/process_poller/tracer_base.py +45 -0
- atomicshop/process_poller/tracers/__init__.py +0 -0
- atomicshop/process_poller/tracers/event_log.py +46 -0
- atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/question_answer_engine.py +2 -2
- atomicshop/scheduling.py +24 -5
- atomicshop/sound.py +4 -2
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/startup/__init__.py +0 -0
- atomicshop/startup/win/__init__.py +0 -0
- atomicshop/startup/win/startup_folder.py +53 -0
- atomicshop/startup/win/task_scheduler.py +119 -0
- atomicshop/system_resource_monitor.py +61 -46
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/timer.py +30 -11
- atomicshop/urls.py +41 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +110 -25
- atomicshop/web_apis/__init__.py +0 -0
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
- atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
- atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
- atomicshop/wrappers/githubw.py +583 -51
- atomicshop/wrappers/loggingw/consts.py +49 -0
- atomicshop/wrappers/loggingw/filters.py +102 -0
- atomicshop/wrappers/loggingw/formatters.py +58 -71
- atomicshop/wrappers/loggingw/handlers.py +459 -40
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +1010 -178
- atomicshop/wrappers/loggingw/reading.py +344 -19
- atomicshop/wrappers/mongodbw/__init__.py +0 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +81 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/psutilw/psutilw.py +9 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/cert_store.py +116 -0
- atomicshop/wrappers/pywin32w/console.py +34 -0
- atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
- atomicshop/wrappers/pywin32w/winshell.py +19 -0
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +500 -173
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +157 -0
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/addons/process_list/compile.cmd +0 -2
- atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/etw/dns_trace.py +0 -118
- atomicshop/etw/etw.py +0 -61
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -240
- atomicshop/monitor/checks/hash.py +0 -44
- atomicshop/monitor/checks/hash_checks/file.py +0 -55
- atomicshop/monitor/checks/hash_checks/url.py +0 -62
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -110
- atomicshop/process_poller.py +0 -237
- atomicshop/script_as_string_processor.py +0 -38
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/loggingw/checks.py +0 -20
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.11.47.dist-info/RECORD +0 -251
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
- /atomicshop/{archiver → etws}/__init__.py +0 -0
- /atomicshop/{etw → etws/traces}/__init__.py +0 -0
- /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
- /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {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(
|
|
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
|
|
14
|
-
|
|
15
|
-
:
|
|
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(
|
|
37
|
-
|
|
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
|