| author | |
| committer | |
| log | 5f50980880181774de83dab3294ddeb0a121d6f2 |
| tree | 7ee889d4aa02db1c576451c968f3b099c362ce8f |
| parent | f73044dae598da2b84bff7977be5a8e02093902a |
| parent | 65299c37d1b4b4395616d6f86b5f064000951cf6 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
std: validate frame-pointer address in stack walking13 files changed, 143 insertions(+), 1 deletions(-)
lib/std/c.zig+1| ... | @@ -123,6 +123,7 @@ pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; | ... | @@ -123,6 +123,7 @@ pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; |
| 123 | pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize; | 123 | pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize; |
| 124 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: c.fd_t, offset: c.off_t) *anyopaque; | 124 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: c.fd_t, offset: c.off_t) *anyopaque; |
| 125 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; | 125 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; |
| 126 | pub extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; | ||
| 126 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; | 127 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; |
| 127 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; | 128 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; |
| 128 | pub extern "c" fn linkat(oldfd: c.fd_t, oldpath: [*:0]const u8, newfd: c.fd_t, newpath: [*:0]const u8, flags: c_int) c_int; | 129 | pub extern "c" fn linkat(oldfd: c.fd_t, oldpath: [*:0]const u8, newfd: c.fd_t, newpath: [*:0]const u8, flags: c_int) c_int; |
lib/std/c/darwin.zig+6| ... | @@ -636,6 +636,12 @@ pub const MAP = struct { | ... | @@ -636,6 +636,12 @@ pub const MAP = struct { |
| 636 | pub const FAILED = @intToPtr(*anyopaque, maxInt(usize)); | 636 | pub const FAILED = @intToPtr(*anyopaque, maxInt(usize)); |
| 637 | }; | 637 | }; |
| 638 | 638 | ||
| 639 | pub const MSF = struct { | ||
| 640 | pub const ASYNC = 1; | ||
| 641 | pub const INVALIDATE = 2; | ||
| 642 | pub const SYNC = 4; | ||
| 643 | }; | ||
| 644 | |||
| 639 | pub const SA = struct { | 645 | pub const SA = struct { |
| 640 | /// take signal on signal stack | 646 | /// take signal on signal stack |
| 641 | pub const ONSTACK = 0x0001; | 647 | pub const ONSTACK = 0x0001; |
lib/std/c/dragonfly.zig+6| ... | @@ -185,6 +185,12 @@ pub const MAP = struct { | ... | @@ -185,6 +185,12 @@ pub const MAP = struct { |
| 185 | pub const SIZEALIGN = 262144; | 185 | pub const SIZEALIGN = 262144; |
| 186 | }; | 186 | }; |
| 187 | 187 | ||
| 188 | pub const MSF = struct { | ||
| 189 | pub const ASYNC = 1; | ||
| 190 | pub const INVALIDATE = 2; | ||
| 191 | pub const SYNC = 4; | ||
| 192 | }; | ||
| 193 | |||
| 188 | pub const W = struct { | 194 | pub const W = struct { |
| 189 | pub const NOHANG = 0x0001; | 195 | pub const NOHANG = 0x0001; |
| 190 | pub const UNTRACED = 0x0002; | 196 | pub const UNTRACED = 0x0002; |
lib/std/c/freebsd.zig+6| ... | @@ -410,6 +410,12 @@ pub const MAP = struct { | ... | @@ -410,6 +410,12 @@ pub const MAP = struct { |
| 410 | pub const @"32BIT" = 0x00080000; | 410 | pub const @"32BIT" = 0x00080000; |
| 411 | }; | 411 | }; |
| 412 | 412 | ||
| 413 | pub const MSF = struct { | ||
| 414 | pub const ASYNC = 1; | ||
| 415 | pub const INVALIDATE = 2; | ||
| 416 | pub const SYNC = 4; | ||
| 417 | }; | ||
| 418 | |||
| 413 | pub const W = struct { | 419 | pub const W = struct { |
| 414 | pub const NOHANG = 1; | 420 | pub const NOHANG = 1; |
| 415 | pub const UNTRACED = 2; | 421 | pub const UNTRACED = 2; |
lib/std/c/linux.zig+1| ... | @@ -30,6 +30,7 @@ pub const MAP = struct { | ... | @@ -30,6 +30,7 @@ pub const MAP = struct { |
| 30 | /// Only used by libc to communicate failure. | 30 | /// Only used by libc to communicate failure. |
| 31 | pub const FAILED = @intToPtr(*anyopaque, maxInt(usize)); | 31 | pub const FAILED = @intToPtr(*anyopaque, maxInt(usize)); |
| 32 | }; | 32 | }; |
| 33 | pub const MSF = linux.MSF; | ||
| 33 | pub const MMAP2_UNIT = linux.MMAP2_UNIT; | 34 | pub const MMAP2_UNIT = linux.MMAP2_UNIT; |
| 34 | pub const MSG = linux.MSG; | 35 | pub const MSG = linux.MSG; |
| 35 | pub const NAME_MAX = linux.NAME_MAX; | 36 | pub const NAME_MAX = linux.NAME_MAX; |
lib/std/c/netbsd.zig+6| ... | @@ -575,6 +575,12 @@ pub const MAP = struct { | ... | @@ -575,6 +575,12 @@ pub const MAP = struct { |
| 575 | pub const STACK = 0x2000; | 575 | pub const STACK = 0x2000; |
| 576 | }; | 576 | }; |
| 577 | 577 | ||
| 578 | pub const MSF = struct { | ||
| 579 | pub const ASYNC = 1; | ||
| 580 | pub const INVALIDATE = 2; | ||
| 581 | pub const SYNC = 4; | ||
| 582 | }; | ||
| 583 | |||
| 578 | pub const W = struct { | 584 | pub const W = struct { |
| 579 | pub const NOHANG = 0x00000001; | 585 | pub const NOHANG = 0x00000001; |
| 580 | pub const UNTRACED = 0x00000002; | 586 | pub const UNTRACED = 0x00000002; |
lib/std/c/openbsd.zig+6| ... | @@ -363,6 +363,12 @@ pub const MAP = struct { | ... | @@ -363,6 +363,12 @@ pub const MAP = struct { |
| 363 | pub const CONCEAL = 0x8000; | 363 | pub const CONCEAL = 0x8000; |
| 364 | }; | 364 | }; |
| 365 | 365 | ||
| 366 | pub const MSF = struct { | ||
| 367 | pub const ASYNC = 1; | ||
| 368 | pub const INVALIDATE = 2; | ||
| 369 | pub const SYNC = 4; | ||
| 370 | }; | ||
| 371 | |||
| 366 | pub const W = struct { | 372 | pub const W = struct { |
| 367 | pub const NOHANG = 1; | 373 | pub const NOHANG = 1; |
| 368 | pub const UNTRACED = 2; | 374 | pub const UNTRACED = 2; |
lib/std/c/solaris.zig+6| ... | @@ -534,6 +534,12 @@ pub const MAP = struct { | ... | @@ -534,6 +534,12 @@ pub const MAP = struct { |
| 534 | pub const INITDATA = 0x0800; | 534 | pub const INITDATA = 0x0800; |
| 535 | }; | 535 | }; |
| 536 | 536 | ||
| 537 | pub const MSF = struct { | ||
| 538 | pub const ASYNC = 1; | ||
| 539 | pub const INVALIDATE = 2; | ||
| 540 | pub const SYNC = 4; | ||
| 541 | }; | ||
| 542 | |||
| 537 | pub const MADV = struct { | 543 | pub const MADV = struct { |
| 538 | /// no further special treatment | 544 | /// no further special treatment |
| 539 | pub const NORMAL = 0; | 545 | pub const NORMAL = 0; |
lib/std/debug.zig+47-1| ... | @@ -424,6 +424,52 @@ pub const StackIterator = struct { | ... | @@ -424,6 +424,52 @@ pub const StackIterator = struct { |
| 424 | return address; | 424 | return address; |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | fn isValidMemory(address: usize) bool { | ||
| 428 | const aligned_address = address & ~@intCast(usize, (mem.page_size - 1)); | ||
| 429 | |||
| 430 | // If the address does not span 2 pages, query only the first one | ||
| 431 | const length: usize = if (aligned_address == address) mem.page_size else 2 * mem.page_size; | ||
| 432 | |||
| 433 | const aligned_memory = @intToPtr([*]align(mem.page_size) u8, aligned_address)[0..length]; | ||
| 434 | |||
| 435 | if (native_os != .windows) { | ||
| 436 | if (native_os != .wasi) { | ||
| 437 | os.msync(aligned_memory, os.MSF.ASYNC) catch |err| { | ||
| 438 | switch (err) { | ||
| 439 | os.MSyncError.UnmappedMemory => { | ||
| 440 | return false; | ||
| 441 | }, | ||
| 442 | else => unreachable, | ||
| 443 | } | ||
| 444 | }; | ||
| 445 | } | ||
| 446 | |||
| 447 | return true; | ||
| 448 | } else { | ||
| 449 | const w = os.windows; | ||
| 450 | var memory_info: w.MEMORY_BASIC_INFORMATION = undefined; | ||
| 451 | //const memory_info_ptr = @ptrCast(w.PMEMORY_BASIC_INFORMATION, buffer); | ||
| 452 | |||
| 453 | // The only error this function can throw is ERROR_INVALID_PARAMETER. | ||
| 454 | // supply an address that invalid i'll be thrown. | ||
| 455 | const rc = w.VirtualQuery(aligned_memory.ptr, &memory_info, aligned_memory.len) catch { | ||
| 456 | return false; | ||
| 457 | }; | ||
| 458 | |||
| 459 | // Result code has to be bigger than zero (number of bytes written) | ||
| 460 | if (rc == 0) { | ||
| 461 | return false; | ||
| 462 | } | ||
| 463 | |||
| 464 | // Free pages cannot be read, they are unmapped | ||
| 465 | if (memory_info.State == w.MEM_FREE) { | ||
| 466 | return false; | ||
| 467 | } | ||
| 468 | |||
| 469 | return true; | ||
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 427 | fn next_internal(self: *StackIterator) ?usize { | 473 | fn next_internal(self: *StackIterator) ?usize { |
| 428 | const fp = if (comptime native_arch.isSPARC()) | 474 | const fp = if (comptime native_arch.isSPARC()) |
| 429 | // On SPARC the offset is positive. (!) | 475 | // On SPARC the offset is positive. (!) |
| ... | @@ -432,7 +478,7 @@ pub const StackIterator = struct { | ... | @@ -432,7 +478,7 @@ pub const StackIterator = struct { |
| 432 | math.sub(usize, self.fp, fp_offset) catch return null; | 478 | math.sub(usize, self.fp, fp_offset) catch return null; |
| 433 | 479 | ||
| 434 | // Sanity check. | 480 | // Sanity check. |
| 435 | if (fp == 0 or !mem.isAligned(fp, @alignOf(usize))) | 481 | if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)) or !isValidMemory(fp)) |
| 436 | return null; | 482 | return null; |
| 437 | 483 | ||
| 438 | const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null; | 484 | const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null; |
lib/std/os.zig+14| ... | @@ -88,6 +88,7 @@ pub const Kevent = system.Kevent; | ... | @@ -88,6 +88,7 @@ pub const Kevent = system.Kevent; |
| 88 | pub const LOCK = system.LOCK; | 88 | pub const LOCK = system.LOCK; |
| 89 | pub const MADV = system.MADV; | 89 | pub const MADV = system.MADV; |
| 90 | pub const MAP = system.MAP; | 90 | pub const MAP = system.MAP; |
| 91 | pub const MSF = system.MSF; | ||
| 91 | pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; | 92 | pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN; |
| 92 | pub const MMAP2_UNIT = system.MMAP2_UNIT; | 93 | pub const MMAP2_UNIT = system.MMAP2_UNIT; |
| 93 | pub const MSG = system.MSG; | 94 | pub const MSG = system.MSG; |
| ... | @@ -4016,6 +4017,19 @@ pub fn munmap(memory: []align(mem.page_size) const u8) void { | ... | @@ -4016,6 +4017,19 @@ pub fn munmap(memory: []align(mem.page_size) const u8) void { |
| 4016 | } | 4017 | } |
| 4017 | } | 4018 | } |
| 4018 | 4019 | ||
| 4020 | pub const MSyncError = error{ | ||
| 4021 | UnmappedMemory, | ||
| 4022 | } || UnexpectedError; | ||
| 4023 | |||
| 4024 | pub fn msync(memory: []align(mem.page_size) u8, flags: i32) MSyncError!void { | ||
| 4025 | switch (errno(system.msync(memory.ptr, memory.len, flags))) { | ||
| 4026 | .SUCCESS => return, | ||
| 4027 | .NOMEM => return error.UnmappedMemory, // Unsuccessful, provided pointer does not point mapped memory | ||
| 4028 | .INVAL => unreachable, // Invalid parameters. | ||
| 4029 | else => unreachable, | ||
| 4030 | } | ||
| 4031 | } | ||
| 4032 | |||
| 4019 | pub const AccessError = error{ | 4033 | pub const AccessError = error{ |
| 4020 | PermissionDenied, | 4034 | PermissionDenied, |
| 4021 | FileNotFound, | 4035 | FileNotFound, |
lib/std/os/linux.zig+10| ... | @@ -406,6 +406,16 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { | ... | @@ -406,6 +406,16 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { |
| 406 | return syscall3(.mprotect, @ptrToInt(address), length, protection); | 406 | return syscall3(.mprotect, @ptrToInt(address), length, protection); |
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | pub const MSF = struct { | ||
| 410 | pub const ASYNC = 1; | ||
| 411 | pub const INVALIDATE = 2; | ||
| 412 | pub const SYNC = 4; | ||
| 413 | }; | ||
| 414 | |||
| 415 | pub fn msync(address: [*]const u8, length: usize, flags: i32) usize { | ||
| 416 | return syscall3(.msync, @ptrToInt(address), length, @bitCast(u32, flags)); | ||
| 417 | } | ||
| 418 | |||
| 409 | pub fn munmap(address: [*]const u8, length: usize) usize { | 419 | pub fn munmap(address: [*]const u8, length: usize) usize { |
| 410 | return syscall2(.munmap, @ptrToInt(address), length); | 420 | return syscall2(.munmap, @ptrToInt(address), length); |
| 411 | } | 421 | } |
lib/std/os/windows.zig+32| ... | @@ -1495,6 +1495,19 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { | ... | @@ -1495,6 +1495,19 @@ pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void { |
| 1495 | assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); | 1495 | assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0); |
| 1496 | } | 1496 | } |
| 1497 | 1497 | ||
| 1498 | pub const VirtualQuerryError = error{Unexpected}; | ||
| 1499 | |||
| 1500 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQuerryError!SIZE_T { | ||
| 1501 | const rc = kernel32.VirtualQuery(lpAddress, lpBuffer, dwLength); | ||
| 1502 | if (rc == 0) { | ||
| 1503 | switch (kernel32.GetLastError()) { | ||
| 1504 | else => |err| return unexpectedError(err), | ||
| 1505 | } | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | return rc; | ||
| 1509 | } | ||
| 1510 | |||
| 1498 | pub const SetConsoleTextAttributeError = error{Unexpected}; | 1511 | pub const SetConsoleTextAttributeError = error{Unexpected}; |
| 1499 | 1512 | ||
| 1500 | pub fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) SetConsoleTextAttributeError!void { | 1513 | pub fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) SetConsoleTextAttributeError!void { |
| ... | @@ -2586,6 +2599,11 @@ pub const CREATE_EVENT_MANUAL_RESET = 0x00000001; | ... | @@ -2586,6 +2599,11 @@ pub const CREATE_EVENT_MANUAL_RESET = 0x00000001; |
| 2586 | pub const EVENT_ALL_ACCESS = 0x1F0003; | 2599 | pub const EVENT_ALL_ACCESS = 0x1F0003; |
| 2587 | pub const EVENT_MODIFY_STATE = 0x0002; | 2600 | pub const EVENT_MODIFY_STATE = 0x0002; |
| 2588 | 2601 | ||
| 2602 | // MEMORY_BASIC_INFORMATION.Type flags for VirtualQuery | ||
| 2603 | pub const MEM_IMAGE = 0x1000000; | ||
| 2604 | pub const MEM_MAPPED = 0x40000; | ||
| 2605 | pub const MEM_PRIVATE = 0x20000; | ||
| 2606 | |||
| 2589 | pub const PROCESS_INFORMATION = extern struct { | 2607 | pub const PROCESS_INFORMATION = extern struct { |
| 2590 | hProcess: HANDLE, | 2608 | hProcess: HANDLE, |
| 2591 | hThread: HANDLE, | 2609 | hThread: HANDLE, |
| ... | @@ -2661,6 +2679,7 @@ pub const HEAP_NO_SERIALIZE = 0x00000001; | ... | @@ -2661,6 +2679,7 @@ pub const HEAP_NO_SERIALIZE = 0x00000001; |
| 2661 | // AllocationType values | 2679 | // AllocationType values |
| 2662 | pub const MEM_COMMIT = 0x1000; | 2680 | pub const MEM_COMMIT = 0x1000; |
| 2663 | pub const MEM_RESERVE = 0x2000; | 2681 | pub const MEM_RESERVE = 0x2000; |
| 2682 | pub const MEM_FREE = 0x10000; | ||
| 2664 | pub const MEM_RESET = 0x80000; | 2683 | pub const MEM_RESET = 0x80000; |
| 2665 | pub const MEM_RESET_UNDO = 0x1000000; | 2684 | pub const MEM_RESET_UNDO = 0x1000000; |
| 2666 | pub const MEM_LARGE_PAGES = 0x20000000; | 2685 | pub const MEM_LARGE_PAGES = 0x20000000; |
| ... | @@ -2960,6 +2979,19 @@ pub const COINIT = enum(c_int) { | ... | @@ -2960,6 +2979,19 @@ pub const COINIT = enum(c_int) { |
| 2960 | COINIT_SPEED_OVER_MEMORY = 8, | 2979 | COINIT_SPEED_OVER_MEMORY = 8, |
| 2961 | }; | 2980 | }; |
| 2962 | 2981 | ||
| 2982 | pub const MEMORY_BASIC_INFORMATION = extern struct { | ||
| 2983 | BaseAddress: PVOID, | ||
| 2984 | AllocationBase: PVOID, | ||
| 2985 | AllocationProtect: DWORD, | ||
| 2986 | PartitionId: WORD, | ||
| 2987 | RegionSize: SIZE_T, | ||
| 2988 | State: DWORD, | ||
| 2989 | Protect: DWORD, | ||
| 2990 | Type: DWORD, | ||
| 2991 | }; | ||
| 2992 | |||
| 2993 | pub const PMEMORY_BASIC_INFORMATION = *MEMORY_BASIC_INFORMATION; | ||
| 2994 | |||
| 2963 | /// > The maximum path of 32,767 characters is approximate, because the "\\?\" | 2995 | /// > The maximum path of 32,767 characters is approximate, because the "\\?\" |
| 2964 | /// > prefix may be expanded to a longer string by the system at run time, and | 2996 | /// > prefix may be expanded to a longer string by the system at run time, and |
| 2965 | /// > this expansion applies to the total length. | 2997 | /// > this expansion applies to the total length. |
lib/std/os/windows/kernel32.zig+2| ... | @@ -56,6 +56,7 @@ const LPOVERLAPPED_COMPLETION_ROUTINE = windows.LPOVERLAPPED_COMPLETION_ROUTINE; | ... | @@ -56,6 +56,7 @@ const LPOVERLAPPED_COMPLETION_ROUTINE = windows.LPOVERLAPPED_COMPLETION_ROUTINE; |
| 56 | const UCHAR = windows.UCHAR; | 56 | const UCHAR = windows.UCHAR; |
| 57 | const FARPROC = windows.FARPROC; | 57 | const FARPROC = windows.FARPROC; |
| 58 | const INIT_ONCE_FN = windows.INIT_ONCE_FN; | 58 | const INIT_ONCE_FN = windows.INIT_ONCE_FN; |
| 59 | const PMEMORY_BASIC_INFORMATION = windows.PMEMORY_BASIC_INFORMATION; | ||
| 59 | 60 | ||
| 60 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; | 61 | pub extern "kernel32" fn AddVectoredExceptionHandler(First: c_ulong, Handler: ?VECTORED_EXCEPTION_HANDLER) callconv(WINAPI) ?*anyopaque; |
| 61 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; | 62 | pub extern "kernel32" fn RemoveVectoredExceptionHandler(Handle: HANDLE) callconv(WINAPI) c_ulong; |
| ... | @@ -245,6 +246,7 @@ pub extern "kernel32" fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*co | ... | @@ -245,6 +246,7 @@ pub extern "kernel32" fn HeapValidate(hHeap: HANDLE, dwFlags: DWORD, lpMem: ?*co |
| 245 | 246 | ||
| 246 | pub extern "kernel32" fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) callconv(WINAPI) ?LPVOID; | 247 | pub extern "kernel32" fn VirtualAlloc(lpAddress: ?LPVOID, dwSize: SIZE_T, flAllocationType: DWORD, flProtect: DWORD) callconv(WINAPI) ?LPVOID; |
| 247 | pub extern "kernel32" fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) callconv(WINAPI) BOOL; | 248 | pub extern "kernel32" fn VirtualFree(lpAddress: ?LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) callconv(WINAPI) BOOL; |
| 249 | pub extern "kernel32" fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) callconv(WINAPI) SIZE_T; | ||
| 248 | 250 | ||
| 249 | pub extern "kernel32" fn LocalFree(hMem: HLOCAL) callconv(WINAPI) ?HLOCAL; | 251 | pub extern "kernel32" fn LocalFree(hMem: HLOCAL) callconv(WINAPI) ?HLOCAL; |
| 250 | 252 |