Skip to content

Commit 56a8373

Browse files
authored
Consolidate winerror message handling in modules _ctpyes and nt (#1470)
1 parent 9162b30 commit 56a8373

3 files changed

Lines changed: 21 additions & 33 deletions

File tree

Src/IronPython.Modules/_ctypes/_ctypes.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,23 +166,16 @@ public static int CopyComPointer(object src, object dest) {
166166

167167
#nullable enable
168168

169+
[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
169170
public static string FormatError() {
170171
return FormatError(get_last_error());
171172
}
172173

174+
[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
173175
public static string FormatError(int errorCode) {
174176
return new Win32Exception(errorCode).Message;
175177
}
176178

177-
private static string FormatError(int errorCode, string? fileName) {
178-
string msg = FormatError(errorCode);
179-
// error codes: https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
180-
if (errorCode is not (< 0 or >= 8200 or 34 or 106 or 317 or 718)) {
181-
msg = msg.Replace("%1", $"'{fileName}'");
182-
}
183-
return msg;
184-
}
185-
186179
[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
187180
public static void FreeLibrary(int handle) {
188181
FreeLibrary(new IntPtr(handle));
@@ -203,9 +196,7 @@ private static object LoadDLL(string? library, int mode) {
203196
IntPtr res = NativeFunctions.LoadDLL(library, mode);
204197
if (res == IntPtr.Zero) {
205198
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
206-
int code = NativeFunctions.GetLastError();
207-
string msg = FormatError(code, library);
208-
throw PythonExceptions.CreateThrowable(PythonExceptions.OSError, 0, msg, null, code);
199+
throw PythonNT.GetLastWin32Error(library);
209200
}
210201

211202
throw PythonOps.OSError("cannot load library '{0}'", library);
@@ -430,6 +421,7 @@ public static int get_errno() {
430421
return 0;
431422
}
432423

424+
[SupportedOSPlatform("windows"), PythonHidden(PlatformsAttribute.PlatformFamily.Unix)]
433425
public static int get_last_error() {
434426
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
435427
return NativeFunctions.GetLastError();

Src/IronPython.Modules/nt.cs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,7 @@ private static Exception ToPythonException(Exception e, string? filename = null)
20552055
return PythonOps.OSError(errorCode, message, filename, errorCode);
20562056
}
20572057

2058-
return PythonExceptions.CreateThrowable(PythonExceptions.OSError, errorCode, message);
2058+
return PythonOps.OSError(errorCode, message, filename);
20592059
}
20602060

20612061
private static Exception? IOExceptionToPythonException(IOException? ioe, int error, string? filename) {
@@ -2214,29 +2214,22 @@ private static Exception GetUnixError(int error, string? filename = null, string
22142214
return PythonOps.OSError(error, msg, filename, null, filename2);
22152215
}
22162216

2217-
[DllImport("kernel32.dll", EntryPoint = "FormatMessageW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = true)]
2218-
private static extern int FormatMessage(int dwFlags, IntPtr lpSource,
2219-
int dwMessageId, int dwLanguageId, [Out] StringBuilder lpBuffer,
2220-
int nSize, IntPtr arguments);
2217+
#endif
22212218

2222-
private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
2223-
private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
2224-
private const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
2219+
#if FEATURE_NATIVE || FEATURE_CTYPES
22252220

22262221
// Gets an error message for a Win32 error code.
22272222
internal static string GetMessage(int errorCode) {
2228-
var buf = new StringBuilder(256);
2229-
int msgLen = 0;
2230-
int lastError = ERROR_INSUFFICIENT_BUFFER;
2231-
while (msgLen == 0 && lastError == ERROR_INSUFFICIENT_BUFFER) {
2232-
msgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, IntPtr.Zero, errorCode, 0, buf, buf.Capacity, IntPtr.Zero);
2233-
if (msgLen == 0) {
2234-
lastError = Marshal.GetLastWin32Error();
2235-
if (lastError == ERROR_INSUFFICIENT_BUFFER)
2236-
buf.Capacity *= 2;
2237-
}
2238-
}
2239-
return buf.ToString().TrimEnd('\r', '\n', '.');
2223+
string msg = new Win32Exception(errorCode).Message;
2224+
// error codes: https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
2225+
if (errorCode is not (< 0 or >= 8200 or 34 or 106 or 317 or 718)) {
2226+
msg = msg.IndexOf('%') switch {
2227+
0 => "The file specified" + msg.Substring(2),
2228+
> 0 => msg.Replace("%1", "the file specified"),
2229+
_ => msg
2230+
};
2231+
}
2232+
return msg.TrimEnd('\r', '\n', '.');
22402233
}
22412234

22422235
internal static Exception GetLastWin32Error(string? filename = null, string? filename2 = null)

Tests/modules/type_related/test_ctypes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,10 @@ def test_loadlibrary_error(self):
228228
self.assertEqual(cm.exception.errno, 8)
229229
self.assertEqual(cm.exception.winerror, 193)
230230
self.assertIn(" is not a valid Win32 application", cm.exception.strerror)
231-
self.assertIsNone(cm.exception.filename)
231+
if is_cli:
232+
self.assertEqual(cm.exception.filename, __file__)
233+
else:
234+
self.assertIsNone(cm.exception.filename)
232235
self.assertIsNone(cm.exception.filename2)
233236

234237
run_test(__name__)

0 commit comments

Comments
 (0)