Skip to content

Commit 59b162c

Browse files
authored
os: fix windows rmdir GetLastError() (fix #24356) (#24357)
1 parent 61a6199 commit 59b162c

1 file changed

Lines changed: 35 additions & 9 deletions

File tree

‎vlib/os/os.c.v‎

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,12 @@ pub fn cp(src string, dst string) ! {
226226
w_src := src.replace('/', '\\')
227227
w_dst := dst.replace('/', '\\')
228228
if C.CopyFile(w_src.to_wide(), w_dst.to_wide(), false) == 0 {
229-
return error_win32(msg: 'failed to copy ${src} to ${dst}')
229+
// we must save error immediately, or it will be overwritten by other API function calls.
230+
code := int(C.GetLastError())
231+
return error_win32(
232+
msg: 'failed to copy ${src} to ${dst}'
233+
code: code
234+
)
230235
}
231236
} $else {
232237
fp_from := C.open(&char(src.str), C.O_RDONLY, 0)
@@ -480,8 +485,11 @@ pub fn rmdir(path string) ! {
480485
rc := C.RemoveDirectory(path.to_wide())
481486
if !rc {
482487
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-removedirectorya - 0 == false, is failure
488+
// we must save error immediately, or it will be overwritten by other API function calls.
489+
code := int(C.GetLastError())
483490
return error_win32(
484-
msg: 'Failed to remove "${path}": ' + get_error_msg(int(C.GetLastError()))
491+
msg: 'Failed to remove "${path}"'
492+
code: code
485493
)
486494
}
487495
} $else {
@@ -1077,7 +1085,7 @@ pub fn last_error() IError {
10771085
}
10781086

10791087
// Magic constant because zero is used explicitly at times
1080-
pub const error_code_not_set = int(0x7EFEFEFE)
1088+
pub const error_code_not_set = int(-1)
10811089

10821090
@[params]
10831091
pub struct SystemError {
@@ -1086,7 +1094,7 @@ pub:
10861094
code int = error_code_not_set
10871095
}
10881096

1089-
// Return a POSIX error:
1097+
// error_posix returns a POSIX error:
10901098
// Code defaults to last error (from C.errno)
10911099
// Message defaults to POSIX error message for the error code
10921100
@[inline; manualfree]
@@ -1096,15 +1104,33 @@ pub fn error_posix(e SystemError) IError {
10961104
return error_with_code(message, code)
10971105
}
10981106

1099-
// Return a Win32 API error:
1100-
// Code defaults to last error (calling C.GetLastError())
1107+
// error_win32 returns a Win32 API error:
1108+
// example:
1109+
// ```
1110+
// // save error code immediately, or it will be overwritten by other API
1111+
// // function calls, even by `str_intp`.
1112+
// code := int(C.GetLastError())
1113+
// error_win32(
1114+
// msg : 'some error'
1115+
// code : code
1116+
// )
1117+
// ```
1118+
// wrong usage:
1119+
// ```
1120+
// error_win32(
1121+
// msg : 'some error ${path}' // this will overwrite error code
1122+
// code : int(C.GetLastError())
1123+
// )
1124+
// ```
11011125
// Message defaults to Win 32 API error message for the error code
11021126
@[inline; manualfree]
11031127
pub fn error_win32(e SystemError) IError {
11041128
$if windows {
1105-
code := if e.code == error_code_not_set { int(C.GetLastError()) } else { e.code }
1106-
message := if e.msg == '' { get_error_msg(code) } else { e.msg }
1107-
return error_with_code(message, code)
1129+
if e.code == error_code_not_set {
1130+
panic('before calling `error_win32`, you must set `e.code` first.')
1131+
}
1132+
message := if e.msg == '' { get_error_msg(e.code) } else { e.msg }
1133+
return error_with_code(message, e.code)
11081134
} $else {
11091135
panic('Win32 API not available on this platform.')
11101136
}

0 commit comments

Comments
 (0)