@@ -2090,6 +2090,72 @@ pub fn loadWinsockExtensionFunction(comptime T: type, sock: ws2_32.SOCKET, guid:
20902090 return function ;
20912091}
20922092
2093+ /// https://github.com/microsoft/terminal/blob/931aa8c87e5f5dbd28cf838bee450d082474a732/dep/Console/conmsgl1.h#L117-L120
2094+ const CONSOLE_MSG_HEADER = extern struct {
2095+ ApiNumber : ULONG ,
2096+ ApiDescriptorSize : ULONG ,
2097+ };
2098+
2099+ pub const CP_UTF8 = 65001 ;
2100+
2101+ /// Like the kernel32 functions SetConsoleOutputCP/SetConsoleCP, but implemented using ntdll.NtDeviceIoControlFile.
2102+ pub fn setConsoleCodePage (code_page : ULONG , direction : enum { input , output }) DeviceIoControlError ! void {
2103+ const console_handle = peb ().ProcessParameters .ConsoleHandle ;
2104+ // The final control code should be 0x00500016 which means that the function is 0x16 >> 2 or 5.
2105+ const console_set_cp_function = 5 ;
2106+ // Note: The NtDeviceIoControlFile call will fail with 0xc0000010 ['Incorrect function.'] if the method is
2107+ // anything other than METHOD_OUT_DIRECT.
2108+ // TODO: Understand why METHOD_OUT_DIRECT is required.
2109+ const io_control_code = comptime CTL_CODE (FILE_DEVICE_CONSOLE , console_set_cp_function , .METHOD_OUT_DIRECT , FILE_ANY_ACCESS );
2110+ comptime std .debug .assert (io_control_code == 0x00500016 );
2111+
2112+ // This is actually one value in an enum but we just care about this value
2113+ // https://github.com/microsoft/terminal/blob/931aa8c87e5f5dbd28cf838bee450d082474a732/dep/Console/conmsgl2.h#L152-L152
2114+ // https://github.com/microsoft/terminal/blob/931aa8c87e5f5dbd28cf838bee450d082474a732/dep/Console/conmsgl1.h#L29-L30
2115+ const ConsolepSetCP = (2 << 24 ) + 4 ;
2116+
2117+ // https://github.com/microsoft/terminal/blob/931aa8c87e5f5dbd28cf838bee450d082474a732/dep/Console/conmsgl2.h#L52-L55
2118+ const CONSOLE_SETCP_MSG = extern struct {
2119+ CodePage : ULONG ,
2120+ Output : bool ,
2121+ };
2122+
2123+ // https://github.com/microsoft/terminal/blob/931aa8c87e5f5dbd28cf838bee450d082474a732/dep/Console/conmsgl2.h#L196-L201
2124+ const CONSOLE_MSG_L2 = extern struct {
2125+ Header : CONSOLE_MSG_HEADER ,
2126+ // This is actually a union of other types but we just care about this for now
2127+ Body : CONSOLE_SETCP_MSG ,
2128+ };
2129+
2130+ // The _unknown fields of this struct have unknown usage/importance/size. These values were
2131+ // obtained by looking at the `input` memory passed to the NtDeviceIoControlFile call
2132+ // that occurs from a successful call of `kernel32.SetConsoleOutputCP()`.
2133+ const UNKNOWN_IOCTL_INPUT = extern struct {
2134+ _unknown1 : u32 = 0 ,
2135+ _unknown2 : u32 = 0 ,
2136+ _unknown3 : u32 = 1 ,
2137+ _unknown4 : u32 = 1 ,
2138+ _unknown5 : u32 = 0x10 ,
2139+ _unknown6 : u32 = 0x20 ,
2140+ header : * CONSOLE_MSG_HEADER ,
2141+ _unknown7 : u32 = 0x8 ,
2142+ _unknown8 : u32 = 0 ,
2143+ body : * CONSOLE_SETCP_MSG ,
2144+ };
2145+
2146+ // Note: These must be var to ensure the memory gets put on the stack.
2147+ var console_msg = CONSOLE_MSG_L2 {
2148+ .Header = .{ .ApiNumber = ConsolepSetCP , .ApiDescriptorSize = @sizeOf (CONSOLE_SETCP_MSG ) },
2149+ .Body = .{ .CodePage = code_page , .Output = direction == .output },
2150+ };
2151+ var input = UNKNOWN_IOCTL_INPUT {
2152+ .header = & console_msg .Header ,
2153+ .body = & console_msg .Body ,
2154+ };
2155+
2156+ return DeviceIoControl (console_handle , io_control_code , std .mem .asBytes (& input ), null );
2157+ }
2158+
20932159/// Call this when you made a windows DLL call or something that does SetLastError
20942160/// and you get an unexpected error.
20952161pub fn unexpectedError (err : Win32Error ) std.os.UnexpectedError {
0 commit comments