| ... | ... | @@ -1514,6 +1514,23 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l |
| 1514 | 1514 | } |
| 1515 | 1515 | } |
| 1516 | 1516 | |
| 1517 | pub fn VirtualProtectEx(handle: HANDLE, addr: ?LPVOID, size: usize, new_prot: DWORD, old_prot: ?*DWORD) VirtualProtectError!void { |
| 1518 | var out_addr = addr; |
| 1519 | var out_size = size; |
| 1520 | switch (ntdll.NtProtectVirtualMemory( |
| 1521 | handle, |
| 1522 | &out_addr, |
| 1523 | &out_size, |
| 1524 | new_prot, |
| 1525 | old_prot, |
| 1526 | )) { |
| 1527 | .SUCCESS => {}, |
| 1528 | .INVALID_ADDRESS => return error.InvalidAddress, |
| 1529 | // TODO: map errors |
| 1530 | else => |rc| return std.os.windows.unexpectedStatus(rc), |
| 1531 | } |
| 1532 | } |
| 1533 | |
| 1517 | 1534 | pub const VirtualQueryError = error{Unexpected}; |
| 1518 | 1535 | |
| 1519 | 1536 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T { |
| ... | ... | @@ -4457,3 +4474,184 @@ pub const MODULEENTRY32 = extern struct { |
| 4457 | 4474 | szModule: [MAX_MODULE_NAME32 + 1]CHAR, |
| 4458 | 4475 | szExePath: [MAX_PATH]CHAR, |
| 4459 | 4476 | }; |
| 4477 | |
| 4478 | pub const THREADINFOCLASS = enum(c_int) { |
| 4479 | ThreadBasicInformation, |
| 4480 | ThreadTimes, |
| 4481 | ThreadPriority, |
| 4482 | ThreadBasePriority, |
| 4483 | ThreadAffinityMask, |
| 4484 | ThreadImpersonationToken, |
| 4485 | ThreadDescriptorTableEntry, |
| 4486 | ThreadEnableAlignmentFaultFixup, |
| 4487 | ThreadEventPair_Reusable, |
| 4488 | ThreadQuerySetWin32StartAddress, |
| 4489 | ThreadZeroTlsCell, |
| 4490 | ThreadPerformanceCount, |
| 4491 | ThreadAmILastThread, |
| 4492 | ThreadIdealProcessor, |
| 4493 | ThreadPriorityBoost, |
| 4494 | ThreadSetTlsArrayAddress, |
| 4495 | ThreadIsIoPending, |
| 4496 | // Windows 2000+ from here |
| 4497 | ThreadHideFromDebugger, |
| 4498 | // Windows XP+ from here |
| 4499 | ThreadBreakOnTermination, |
| 4500 | ThreadSwitchLegacyState, |
| 4501 | ThreadIsTerminated, |
| 4502 | // Windows Vista+ from here |
| 4503 | ThreadLastSystemCall, |
| 4504 | ThreadIoPriority, |
| 4505 | ThreadCycleTime, |
| 4506 | ThreadPagePriority, |
| 4507 | ThreadActualBasePriority, |
| 4508 | ThreadTebInformation, |
| 4509 | ThreadCSwitchMon, |
| 4510 | // Windows 7+ from here |
| 4511 | ThreadCSwitchPmu, |
| 4512 | ThreadWow64Context, |
| 4513 | ThreadGroupInformation, |
| 4514 | ThreadUmsInformation, |
| 4515 | ThreadCounterProfiling, |
| 4516 | ThreadIdealProcessorEx, |
| 4517 | // Windows 8+ from here |
| 4518 | ThreadCpuAccountingInformation, |
| 4519 | // Windows 8.1+ from here |
| 4520 | ThreadSuspendCount, |
| 4521 | // Windows 10+ from here |
| 4522 | ThreadHeterogeneousCpuPolicy, |
| 4523 | ThreadContainerId, |
| 4524 | ThreadNameInformation, |
| 4525 | ThreadSelectedCpuSets, |
| 4526 | ThreadSystemThreadInformation, |
| 4527 | ThreadActualGroupAffinity, |
| 4528 | }; |
| 4529 | |
| 4530 | pub const PROCESSINFOCLASS = enum(c_int) { |
| 4531 | ProcessBasicInformation, |
| 4532 | ProcessQuotaLimits, |
| 4533 | ProcessIoCounters, |
| 4534 | ProcessVmCounters, |
| 4535 | ProcessTimes, |
| 4536 | ProcessBasePriority, |
| 4537 | ProcessRaisePriority, |
| 4538 | ProcessDebugPort, |
| 4539 | ProcessExceptionPort, |
| 4540 | ProcessAccessToken, |
| 4541 | ProcessLdtInformation, |
| 4542 | ProcessLdtSize, |
| 4543 | ProcessDefaultHardErrorMode, |
| 4544 | ProcessIoPortHandlers, |
| 4545 | ProcessPooledUsageAndLimits, |
| 4546 | ProcessWorkingSetWatch, |
| 4547 | ProcessUserModeIOPL, |
| 4548 | ProcessEnableAlignmentFaultFixup, |
| 4549 | ProcessPriorityClass, |
| 4550 | ProcessWx86Information, |
| 4551 | ProcessHandleCount, |
| 4552 | ProcessAffinityMask, |
| 4553 | ProcessPriorityBoost, |
| 4554 | ProcessDeviceMap, |
| 4555 | ProcessSessionInformation, |
| 4556 | ProcessForegroundInformation, |
| 4557 | ProcessWow64Information, |
| 4558 | ProcessImageFileName, |
| 4559 | ProcessLUIDDeviceMapsEnabled, |
| 4560 | ProcessBreakOnTermination, |
| 4561 | ProcessDebugObjectHandle, |
| 4562 | ProcessDebugFlags, |
| 4563 | ProcessHandleTracing, |
| 4564 | ProcessIoPriority, |
| 4565 | ProcessExecuteFlags, |
| 4566 | ProcessTlsInformation, |
| 4567 | ProcessCookie, |
| 4568 | ProcessImageInformation, |
| 4569 | ProcessCycleTime, |
| 4570 | ProcessPagePriority, |
| 4571 | ProcessInstrumentationCallback, |
| 4572 | ProcessThreadStackAllocation, |
| 4573 | ProcessWorkingSetWatchEx, |
| 4574 | ProcessImageFileNameWin32, |
| 4575 | ProcessImageFileMapping, |
| 4576 | ProcessAffinityUpdateMode, |
| 4577 | ProcessMemoryAllocationMode, |
| 4578 | ProcessGroupInformation, |
| 4579 | ProcessTokenVirtualizationEnabled, |
| 4580 | ProcessConsoleHostProcess, |
| 4581 | ProcessWindowInformation, |
| 4582 | MaxProcessInfoClass, |
| 4583 | }; |
| 4584 | |
| 4585 | pub const PROCESS_BASIC_INFORMATION = extern struct { |
| 4586 | ExitStatus: NTSTATUS, |
| 4587 | PebBaseAddress: *PEB, |
| 4588 | AffinityMask: ULONG_PTR, |
| 4589 | BasePriority: KPRIORITY, |
| 4590 | UniqueProcessId: ULONG_PTR, |
| 4591 | InheritedFromUniqueProcessId: ULONG_PTR, |
| 4592 | }; |
| 4593 | |
| 4594 | pub const ReadMemoryError = error{ |
| 4595 | Unexpected, |
| 4596 | }; |
| 4597 | |
| 4598 | pub fn ReadProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []u8) ReadMemoryError![]u8 { |
| 4599 | var nread: usize = 0; |
| 4600 | switch (ntdll.NtReadVirtualMemory( |
| 4601 | handle, |
| 4602 | addr, |
| 4603 | buffer.ptr, |
| 4604 | buffer.len, |
| 4605 | &nread, |
| 4606 | )) { |
| 4607 | .SUCCESS => return buffer[0..nread], |
| 4608 | // TODO: map errors |
| 4609 | else => |rc| return unexpectedStatus(rc), |
| 4610 | } |
| 4611 | } |
| 4612 | |
| 4613 | pub const WriteMemoryError = error{ |
| 4614 | Unexpected, |
| 4615 | }; |
| 4616 | |
| 4617 | pub fn WriteProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []const u8) WriteMemoryError!usize { |
| 4618 | var nwritten: usize = 0; |
| 4619 | switch (ntdll.NtWriteVirtualMemory( |
| 4620 | handle, |
| 4621 | addr, |
| 4622 | @ptrCast(*const anyopaque, buffer.ptr), |
| 4623 | buffer.len, |
| 4624 | &nwritten, |
| 4625 | )) { |
| 4626 | .SUCCESS => return nwritten, |
| 4627 | // TODO: map errors |
| 4628 | else => |rc| return unexpectedStatus(rc), |
| 4629 | } |
| 4630 | } |
| 4631 | |
| 4632 | pub const ProcessBaseAddressError = GetProcessMemoryInfoError || ReadMemoryError; |
| 4633 | |
| 4634 | /// Returns the base address of the process loaded into memory. |
| 4635 | pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE { |
| 4636 | var info: PROCESS_BASIC_INFORMATION = undefined; |
| 4637 | var nread: DWORD = 0; |
| 4638 | const rc = ntdll.NtQueryInformationProcess( |
| 4639 | handle, |
| 4640 | .ProcessBasicInformation, |
| 4641 | &info, |
| 4642 | @sizeOf(PROCESS_BASIC_INFORMATION), |
| 4643 | &nread, |
| 4644 | ); |
| 4645 | switch (rc) { |
| 4646 | .SUCCESS => {}, |
| 4647 | .ACCESS_DENIED => return error.AccessDenied, |
| 4648 | .INVALID_HANDLE => return error.InvalidHandle, |
| 4649 | .INVALID_PARAMETER => unreachable, |
| 4650 | else => return unexpectedStatus(rc), |
| 4651 | } |
| 4652 | |
| 4653 | var peb_buf: [@sizeOf(PEB)]u8 align(@alignOf(PEB)) = undefined; |
| 4654 | const peb_out = try ReadProcessMemory(handle, info.PebBaseAddress, &peb_buf); |
| 4655 | const ppeb = @ptrCast(*const PEB, @alignCast(@alignOf(PEB), peb_out.ptr)); |
| 4656 | return ppeb.ImageBaseAddress; |
| 4657 | } |