Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/host_env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ windows-sys = { workspace = true, features = [
"Win32_System_Console",
"Win32_System_Diagnostics_Debug",
"Win32_System_Environment",
"Win32_System_EventLog",
"Win32_System_Ole",
"Win32_System_IO",
"Win32_System_Ioctl",
Expand Down
42 changes: 42 additions & 0 deletions crates/host_env/src/winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ pub use windows_sys::Win32::{
},
System::{
Console::{STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE},
EventLog::{
EVENTLOG_AUDIT_FAILURE, EVENTLOG_AUDIT_SUCCESS, EVENTLOG_ERROR_TYPE,
EVENTLOG_INFORMATION_TYPE, EVENTLOG_SUCCESS, EVENTLOG_WARNING_TYPE,
},
Memory::{
FILE_MAP_ALL_ACCESS, FILE_MAP_COPY, FILE_MAP_EXECUTE, FILE_MAP_READ, FILE_MAP_WRITE,
MEM_COMMIT, MEM_FREE, MEM_IMAGE, MEM_MAPPED, MEM_PRIVATE, MEM_RESERVE, PAGE_EXECUTE,
Expand Down Expand Up @@ -86,6 +90,44 @@ pub const LCMAP_HASH_FLAG: u32 = windows_sys::Win32::Globalization::LCMAP_HASH;
pub const LCMAP_SORTHANDLE_FLAG: u32 = windows_sys::Win32::Globalization::LCMAP_SORTHANDLE;
pub const LCMAP_SORTKEY_FLAG: u32 = windows_sys::Win32::Globalization::LCMAP_SORTKEY;

pub fn register_event_source_w(
server: Option<&widestring::WideCStr>,
source: &widestring::WideCStr,
) -> io::Result<HANDLE> {
let server = server.map_or(core::ptr::null(), |name| name.as_ptr());
unsafe { windows_sys::Win32::System::EventLog::RegisterEventSourceW(server, source.as_ptr()) }
.check_nonnull()
}

pub fn deregister_event_source(handle: HANDLE) -> io::Result<()> {
unsafe { windows_sys::Win32::System::EventLog::DeregisterEventSource(handle) }
.check_win32_bool()
}

pub fn report_event_w(
handle: HANDLE,
event_type: u16,
category: u16,
event_id: u32,
message: &widestring::WideCStr,
) -> io::Result<()> {
let message = message.as_ptr();
unsafe {
windows_sys::Win32::System::EventLog::ReportEventW(
handle,
event_type,
category,
event_id,
core::ptr::null_mut(),
1,
0,
&message,
core::ptr::null(),
)
}
.check_win32_bool()
}

pub struct PeekNamedPipeResult {
pub data: Option<Vec<u8>>,
pub available: u32,
Expand Down
46 changes: 46 additions & 0 deletions crates/vm/src/stdlib/_winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ mod _winapi {
ERROR_ALREADY_EXISTS, ERROR_BROKEN_PIPE, ERROR_IO_PENDING, ERROR_MORE_DATA,
ERROR_NETNAME_DELETED, ERROR_NO_DATA, ERROR_NO_SYSTEM_RESOURCES, ERROR_OPERATION_ABORTED,
ERROR_PIPE_BUSY, ERROR_PIPE_CONNECTED, ERROR_PRIVILEGE_NOT_HELD, ERROR_SEM_TIMEOUT,
EVENTLOG_AUDIT_FAILURE, EVENTLOG_AUDIT_SUCCESS, EVENTLOG_ERROR_TYPE,
EVENTLOG_INFORMATION_TYPE, EVENTLOG_SUCCESS, EVENTLOG_WARNING_TYPE,
FILE_FLAG_FIRST_PIPE_INSTANCE, FILE_FLAG_OVERLAPPED, FILE_GENERIC_READ, FILE_GENERIC_WRITE,
FILE_MAP_ALL_ACCESS, FILE_MAP_COPY, FILE_MAP_EXECUTE, FILE_MAP_READ, FILE_MAP_WRITE,
FILE_TYPE_CHAR, FILE_TYPE_DISK, FILE_TYPE_PIPE, FILE_TYPE_REMOTE, FILE_TYPE_UNKNOWN,
Expand Down Expand Up @@ -74,6 +76,50 @@ mod _winapi {
WindowsSysResult(host_winapi::close_handle(handle.0))
}

#[pyfunction]
fn RegisterEventSource(
server: Option<PyStrRef>,
source: PyStrRef,
vm: &VirtualMachine,
) -> PyResult<WinHandle> {
let server = server
.map(|server| server.as_wtf8().to_wide_cstring())
.transpose()
.map_err(|_| nul_char_error(vm))?;
let source = source
.as_wtf8()
.to_wide_cstring()
.map_err(|_| nul_char_error(vm))?;
vm.allow_threads(|| host_winapi::register_event_source_w(server.as_deref(), &source))
.map(WinHandle)
.map_err(|error| error.to_pyexception(vm))
}

#[pyfunction]
fn DeregisterEventSource(handle: WinHandle, vm: &VirtualMachine) -> PyResult<()> {
vm.allow_threads(|| host_winapi::deregister_event_source(handle.0))
.map_err(|error| error.to_pyexception(vm))
}

#[pyfunction]
fn ReportEvent(
handle: WinHandle,
event_type: u16,
category: u16,
event_id: u32,
message: PyStrRef,
vm: &VirtualMachine,
) -> PyResult<()> {
let message = message
.as_wtf8()
.to_wide_cstring()
.map_err(|_| nul_char_error(vm))?;
vm.allow_threads(|| {
host_winapi::report_event_w(handle.0, event_type, category, event_id, &message)
})
.map_err(|error| error.to_pyexception(vm))
}

/// CreateFile - Create or open a file or I/O device.
#[expect(
clippy::too_many_arguments,
Expand Down
39 changes: 39 additions & 0 deletions extra_tests/snippets/stdlib_winapi.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stdlib_winapi.py

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Check Windows event-log conversions without invoking host operations."""

import sys

from testutils import assert_raises

if sys.platform == "win32":
import _winapi

# Every call fails before a host operation. ReportEvent overflow cases
# also retain an embedded NUL as an independent safety barrier.
assert _winapi.EVENTLOG_SUCCESS == 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the prohibited test assertions

This newly created snippet adds assertion logic, which is outside the only two test-file changes permitted by the root AGENTS.md (adding or removing expected-failure decorators). Remove this test addition or secure a policy exception before landing it; as written, the change violates the repository's mandatory test-code modification rules.

AGENTS.md reference: AGENTS.md:L273-L280

Useful? React with 👍 / 👎.

assert _winapi.EVENTLOG_ERROR_TYPE == 1
assert _winapi.EVENTLOG_WARNING_TYPE == 2
assert _winapi.EVENTLOG_INFORMATION_TYPE == 4
assert _winapi.EVENTLOG_AUDIT_SUCCESS == 8
assert _winapi.EVENTLOG_AUDIT_FAILURE == 16

assert_raises(TypeError, _winapi.RegisterEventSource, 1, "source\0")
assert_raises(TypeError, _winapi.RegisterEventSource, None, 1)
assert_raises(TypeError, _winapi.RegisterEventSource, None, None)
assert_raises(ValueError, _winapi.RegisterEventSource, None, "source\0")
assert_raises(ValueError, _winapi.RegisterEventSource, "server\0", "source\0")
assert_raises(ValueError, _winapi.RegisterEventSource, "", "source\0")
assert_raises(TypeError, _winapi.DeregisterEventSource, "invalid handle")
assert_raises(TypeError, _winapi.DeregisterEventSource, None)
assert_raises(
TypeError, _winapi.ReportEvent, "invalid handle", 0, 0, 0, "message\0"
)
assert_raises(ValueError, _winapi.ReportEvent, 0, 0, 0, 0, "message\0")
assert_raises(TypeError, _winapi.ReportEvent, 0, 0, 0, 0, None)
for index, bits in ((1, 16), (2, 16), (3, 32)):
for invalid, exception in ((-1, ValueError), (1 << bits, OverflowError)):
arguments = [0, 0, 0, 0, "message\0"]
arguments[index] = invalid
assert_raises(exception, _winapi.ReportEvent, *arguments)
arguments = [0, 0, 0, 0, "message\0"]
arguments[index] = "invalid integer"
assert_raises(TypeError, _winapi.ReportEvent, *arguments)
Loading