levistone 0.10.15__cp312-cp312-win_amd64.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.
@@ -0,0 +1,199 @@
1
+ import _winapi
2
+ import ctypes
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ import warnings
7
+ from subprocess import STARTUPINFO, Handle, list2cmdline
8
+
9
+ from endstone._internal import _detours
10
+ from endstone._internal.bootstrap.base import Bootstrap
11
+
12
+
13
+ class PopenWithDll(subprocess.Popen):
14
+ def __init__(self, *args, **kwargs):
15
+ self.dll_names = kwargs.pop("dll_names", None)
16
+ super().__init__(*args, **kwargs)
17
+
18
+ def _execute_child(
19
+ self,
20
+ args,
21
+ executable,
22
+ preexec_fn,
23
+ close_fds,
24
+ pass_fds,
25
+ cwd,
26
+ env,
27
+ startupinfo,
28
+ creationflags,
29
+ shell,
30
+ p2cread,
31
+ p2cwrite,
32
+ c2pread,
33
+ c2pwrite,
34
+ errread,
35
+ errwrite,
36
+ # unused_restore_signals,
37
+ # unused_gid,
38
+ # unused_gids,
39
+ # unused_uid,
40
+ # unused_umask,
41
+ # unused_start_new_session,
42
+ # unused_process_group,
43
+ *unused_args,
44
+ **unused_kwargs,
45
+ ):
46
+ """Execute program (MS Windows version)"""
47
+
48
+ assert not pass_fds, "pass_fds not supported on Windows."
49
+
50
+ if isinstance(args, str):
51
+ pass
52
+ elif isinstance(args, bytes):
53
+ if shell:
54
+ raise TypeError("bytes args is not allowed on Windows")
55
+ args = list2cmdline([args])
56
+ elif isinstance(args, os.PathLike):
57
+ if shell:
58
+ raise TypeError("path-like args is not allowed when shell is true")
59
+ args = list2cmdline([args])
60
+ else:
61
+ args = list2cmdline(args)
62
+
63
+ if executable is not None:
64
+ executable = os.fsdecode(executable)
65
+
66
+ if startupinfo is None:
67
+ startupinfo = STARTUPINFO()
68
+ else:
69
+ startupinfo = startupinfo.copy()
70
+
71
+ use_std_handles = -1 not in (p2cread, c2pwrite, errwrite)
72
+ if use_std_handles:
73
+ startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES
74
+ startupinfo.hStdInput = p2cread
75
+ startupinfo.hStdOutput = c2pwrite
76
+ startupinfo.hStdError = errwrite
77
+
78
+ attribute_list = startupinfo.lpAttributeList
79
+ have_handle_list = bool(attribute_list and "handle_list" in attribute_list and attribute_list["handle_list"])
80
+
81
+ # If we were given an handle_list or need to create one
82
+ if have_handle_list or (use_std_handles and close_fds):
83
+ if attribute_list is None:
84
+ attribute_list = startupinfo.lpAttributeList = {}
85
+ handle_list = attribute_list["handle_list"] = list(attribute_list.get("handle_list", []))
86
+
87
+ if use_std_handles:
88
+ handle_list += [int(p2cread), int(c2pwrite), int(errwrite)]
89
+
90
+ handle_list[:] = self._filter_handle_list(handle_list)
91
+
92
+ if handle_list:
93
+ if not close_fds:
94
+ warnings.warn("startupinfo.lpAttributeList['handle_list'] overriding close_fds", RuntimeWarning)
95
+
96
+ # When using the handle_list we always request to inherit
97
+ # handles but the only handles that will be inherited are
98
+ # the ones in the handle_list
99
+ close_fds = False
100
+
101
+ assert not shell
102
+
103
+ if cwd is not None:
104
+ cwd = os.fsdecode(cwd)
105
+
106
+ # Start the process
107
+ try:
108
+ hp, ht, pid, tid = _detours.CreateProcessWithDllEx(
109
+ executable,
110
+ args,
111
+ # no special security
112
+ None,
113
+ None,
114
+ not close_fds,
115
+ creationflags,
116
+ env,
117
+ cwd,
118
+ startupinfo,
119
+ dll_name=self.dll_names,
120
+ )
121
+ finally:
122
+ self._close_pipe_fds(p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
123
+
124
+ # Retain the process handle, but close the thread handle
125
+ self._child_created = True
126
+ self._handle = Handle(hp)
127
+ self.pid = pid
128
+ _winapi.CloseHandle(ht)
129
+
130
+
131
+ class WindowsBootstrap(Bootstrap):
132
+ @property
133
+ def name(self) -> str:
134
+ return "WindowsBootstrap"
135
+
136
+ @property
137
+ def target_system(self) -> str:
138
+ return "windows"
139
+
140
+ @property
141
+ def executable_filename(self) -> str:
142
+ return "bedrock_server.exe"
143
+
144
+ @property
145
+ def _endstone_runtime_filename(self) -> str:
146
+ return "endstone_runtime_loader.dll"
147
+
148
+ @property
149
+ def _endstone_runtime_env(self) -> dict[str, str]:
150
+ env = super()._endstone_runtime_env
151
+ symbol_path = env.get("_NT_SYMBOL_PATH", "")
152
+ symbol_path_list = symbol_path.split(os.pathsep)
153
+ symbol_path_list = [
154
+ str(self._endstone_runtime_path.parent.absolute()),
155
+ str(self.plugin_path.absolute()),
156
+ ] + symbol_path_list
157
+ env["_NT_SYMBOL_PATH"] = os.pathsep.join(symbol_path_list)
158
+ return env
159
+
160
+ def _add_loopback_exemption(self) -> None:
161
+ sid = "S-1-15-2-1958404141-86561845-1752920682-3514627264-368642714-62675701-733520436"
162
+ ret = subprocess.run(
163
+ ["CheckNetIsolation", "LoopbackExempt", "-s", f"-p={sid}"], check=True, capture_output=True
164
+ )
165
+ if sid not in str(ret.stdout):
166
+ ret = ctypes.windll.shell32.ShellExecuteW(
167
+ None, "runas", "CheckNetIsolation", " ".join(["LoopbackExempt", "-a", f"-p={sid}"]), None, 1
168
+ )
169
+ if ret <= 32:
170
+ raise RuntimeError(f"CheckNetIsolation LoopbackExempt -a failed with exit code {ret}.")
171
+
172
+ def _check_python_distribution(self) -> None:
173
+ if "WindowsApp" in sys.base_prefix:
174
+ self._logger.warning("You are using a Microsoft Store distribution of Python which is not supported.")
175
+ self._logger.warning(
176
+ "If you experience issues, please use a regular Python distribution instead "
177
+ "from https://www.python.org/downloads/ ."
178
+ )
179
+
180
+ def _run(self, *args, **kwargs) -> int:
181
+ try:
182
+ self._add_loopback_exemption()
183
+ except Exception as e:
184
+ self._logger.warning(
185
+ f"Unable to add loopback exemption: %s. See bedrock_server_how_to.html for more details. {e}"
186
+ )
187
+
188
+ self._check_python_distribution()
189
+ process = PopenWithDll(
190
+ [str(self.executable_path.absolute())],
191
+ text=True,
192
+ encoding="utf-8",
193
+ cwd=str(self.server_path.absolute()),
194
+ env=self._endstone_runtime_env,
195
+ dll_names=str(self._endstone_runtime_path.absolute()),
196
+ *args,
197
+ **kwargs,
198
+ )
199
+ return process.wait()