| author | |
| committer | |
| log | d3599ec73cc07692c2579a8cf7151c918eea525f |
| tree | 1977456fd9b813cb60e7b3ea12842435f725144d |
| parent | a9eb463202f46f6190f57c3b9a5c4913d6c5d6c5 |
4 files changed, 60 insertions(+), 6 deletions(-)
lib/std/c/windows.zig+12| ... | @@ -94,6 +94,18 @@ pub const SEEK = struct { | ... | @@ -94,6 +94,18 @@ pub const SEEK = struct { |
| 94 | pub const END = 2; | 94 | pub const END = 2; |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | /// Basic memory protection flags | ||
| 98 | pub const PROT = struct { | ||
| 99 | /// page can not be accessed | ||
| 100 | pub const NONE = 0x0; | ||
| 101 | /// page can be read | ||
| 102 | pub const READ = 0x1; | ||
| 103 | /// page can be written | ||
| 104 | pub const WRITE = 0x2; | ||
| 105 | /// page can be executed | ||
| 106 | pub const EXEC = 0x4; | ||
| 107 | }; | ||
| 108 | |||
| 97 | pub const E = enum(u16) { | 109 | pub const E = enum(u16) { |
| 98 | /// No error occurred. | 110 | /// No error occurred. |
| 99 | SUCCESS = 0, | 111 | SUCCESS = 0, |
lib/std/os.zig+24-6| ... | @@ -4226,12 +4226,30 @@ pub const MProtectError = error{ | ... | @@ -4226,12 +4226,30 @@ pub const MProtectError = error{ |
| 4226 | /// `memory.len` must be page-aligned. | 4226 | /// `memory.len` must be page-aligned. |
| 4227 | pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void { | 4227 | pub fn mprotect(memory: []align(mem.page_size) u8, protection: u32) MProtectError!void { |
| 4228 | assert(mem.isAligned(memory.len, mem.page_size)); | 4228 | assert(mem.isAligned(memory.len, mem.page_size)); |
| 4229 | switch (errno(system.mprotect(memory.ptr, memory.len, protection))) { | 4229 | if (builtin.os.tag == .windows) { |
| 4230 | .SUCCESS => return, | 4230 | const win_prot: windows.DWORD = switch (@truncate(u3, protection)) { |
| 4231 | .INVAL => unreachable, | 4231 | 0b000 => windows.PAGE_NOACCESS, |
| 4232 | .ACCES => return error.AccessDenied, | 4232 | 0b001 => windows.PAGE_READONLY, |
| 4233 | .NOMEM => return error.OutOfMemory, | 4233 | 0b010 => unreachable, // +w -r not allowed |
| 4234 | else => |err| return unexpectedErrno(err), | 4234 | 0b011 => windows.PAGE_READWRITE, |
| 4235 | 0b100 => windows.PAGE_EXECUTE, | ||
| 4236 | 0b101 => windows.PAGE_EXECUTE_READ, | ||
| 4237 | 0b110 => unreachable, // +w -r not allowed | ||
| 4238 | 0b111 => windows.PAGE_EXECUTE_READWRITE, | ||
| 4239 | }; | ||
| 4240 | var old: windows.DWORD = undefined; | ||
| 4241 | windows.VirtualProtect(memory.ptr, memory.len, win_prot, &old) catch |err| switch (err) { | ||
| 4242 | error.InvalidAddress => return error.AccessDenied, | ||
| 4243 | error.Unexpected => return error.Unexpected, | ||
| 4244 | }; | ||
| 4245 | } else { | ||
| 4246 | switch (errno(system.mprotect(memory.ptr, memory.len, protection))) { | ||
| 4247 | .SUCCESS => return, | ||
| 4248 | .INVAL => unreachable, | ||
| 4249 | .ACCES => return error.AccessDenied, | ||
| 4250 | .NOMEM => return error.OutOfMemory, | ||
| 4251 | else => |err| return unexpectedErrno(err), | ||
| 4252 | } | ||
| 4235 | } | 4253 | } |
| 4236 | } | 4254 | } |
| 4237 | 4255 |
lib/std/os/windows.zig+16| ... | @@ -1499,6 +1499,22 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { | ... | @@ -1499,6 +1499,22 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { |
| 1499 | assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); | 1499 | assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); |
| 1500 | } | 1500 | } |
| 1501 | 1501 | ||
| 1502 | pub const VirtualProtectError = error{ | ||
| 1503 | InvalidAddress, | ||
| 1504 | Unexpected, | ||
| 1505 | }; | ||
| 1506 | |||
| 1507 | pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, lpflOldProtect: *DWORD) VirtualProtectError!void { | ||
| 1508 | // ntdll takes an extra level of indirection here | ||
| 1509 | var addr = lpAddress; | ||
| 1510 | var size = dwSize; | ||
| 1511 | switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) { | ||
| 1512 | .SUCCESS => {}, | ||
| 1513 | .INVALID_ADDRESS => return error.InvalidAddress, | ||
| 1514 | else => |st| return unexpectedStatus(st), | ||
| 1515 | } | ||
| 1516 | } | ||
| 1517 | |||
| 1502 | pub const VirtualQueryError = error{Unexpected}; | 1518 | pub const VirtualQueryError = error{Unexpected}; |
| 1503 | 1519 | ||
| 1504 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T { | 1520 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T { |
lib/std/os/windows/ntdll.zig+8| ... | @@ -291,3 +291,11 @@ pub extern "ntdll" fn RtlQueryRegistryValues( | ... | @@ -291,3 +291,11 @@ pub extern "ntdll" fn RtlQueryRegistryValues( |
| 291 | Context: ?*anyopaque, | 291 | Context: ?*anyopaque, |
| 292 | Environment: ?*anyopaque, | 292 | Environment: ?*anyopaque, |
| 293 | ) callconv(WINAPI) NTSTATUS; | 293 | ) callconv(WINAPI) NTSTATUS; |
| 294 | |||
| 295 | pub extern "ntdll" fn NtProtectVirtualMemory( | ||
| 296 | ProcessHandle: HANDLE, | ||
| 297 | BaseAddress: *PVOID, | ||
| 298 | NumberOfBytesToProtect: *ULONG, | ||
| 299 | NewAccessProtection: ULONG, | ||
| 300 | OldAccessProtection: *ULONG, | ||
| 301 | ) callconv(WINAPI) NTSTATUS; |