Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get poco-w95.exe running #39

Closed
wants to merge 10 commits into from
Closed
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
6 changes: 6 additions & 0 deletions cli/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ impl win32::Host for EnvRef {
Ok(host_to_windows_path(&path))
}

fn set_current_dir(&self, path: &WindowsPath) -> Result<(), u32> {
let path = windows_to_host_path(path);
log::info!("set_current_dir {:?}", path);
std::env::set_current_dir(path).map_err(|e| io_error_to_win32(&e))
}

fn open(&self, path: &WindowsPath, options: FileOptions) -> Result<Box<dyn win32::File>, u32> {
let path = windows_to_host_path(path);
let result = std::fs::File::options()
Expand Down
4 changes: 4 additions & 0 deletions web/glue/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ impl win32::Host for JsHost {
todo!()
}

fn set_current_dir(&self, path: &WindowsPath) -> Result<(), u32> {
todo!("set_current_dir {path}")
}

fn create_dir(&self, path: &WindowsPath) -> Result<(), u32> {
todo!("create_dir {path}")
}
Expand Down
2 changes: 1 addition & 1 deletion win32/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DLL_SRC=advapi32.rs bass.rs ddraw/ dsound.rs gdi32/ kernel32/ ntdll.rs ole32.rs oleaut32.rs retrowin32_test.rs ucrtbase.rs vcruntime140.rs version.rs user32/ winmm/
DLL_SRC=advapi32.rs bass.rs ddraw/ dsound.rs gdi32/ kernel32/ ntdll.rs ole32.rs oleaut32.rs retrowin32_test.rs shell32.rs ucrtbase.rs vcruntime140.rs version.rs user32/ winmm/
DLLS=$(foreach dll,$(DLL_SRC),src/winapi/$(dll))
src/winapi/builtin.rs: Makefile derive/src/*.rs src/*.rs src/winapi/* src/winapi/*/*
cargo run -p win32-derive -- --dll-dir dll --builtins $@ $(DLLS)
Expand Down
Binary file modified win32/dll/advapi32.dll
Binary file not shown.
Binary file modified win32/dll/kernel32.dll
Binary file not shown.
Binary file added win32/dll/shell32.dll
Binary file not shown.
2 changes: 2 additions & 0 deletions win32/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ pub trait Host {

/// Retrieves the absolute (Windows-style) path of the current working directory.
fn current_dir(&self) -> Result<WindowsPathBuf, u32>;
/// Sets the absolute (Windows-style) path of the current working directory.
fn set_current_dir(&self, path: &WindowsPath) -> Result<(), u32>;
/// Open a file at the given (Windows-style) path.
fn open(&self, path: &WindowsPath, options: FileOptions) -> Result<Box<dyn File>, u32>;
/// Retrieve file or directory metadata at the given (Windows-style) path.
Expand Down
4 changes: 2 additions & 2 deletions win32/src/pe/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub fn find_resource(
section: &[u8],
query_type: ResourceName,
query_id: ResourceName,
) -> Option<Range<usize>> {
) -> Option<Range<u32>> {
// Resources are structured as generic nested directories, but in practice there
// are always exactly three levels with known semantics.
let mut dir = IMAGE_RESOURCE_DIRECTORY::entries(section);
Expand All @@ -130,5 +130,5 @@ pub fn find_resource(
ResourceValue::Data(data) => data,
_ => todo!(),
};
Some(data.OffsetToData as usize..(data.OffsetToData + data.Size) as usize)
Some(data.OffsetToData..(data.OffsetToData + data.Size))
}
11 changes: 1 addition & 10 deletions win32/src/str16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,7 @@ impl Str16 {
}

pub fn to_string(&self) -> String {
self.0
.iter()
.map(|&c| {
if c > 0xFF {
// TODO
panic!("unhandled non-ascii {:?}", char::from_u32(c as u32));
}
c as u8 as char
})
.collect()
String::from_utf16(&self.0).unwrap()
}
}

Expand Down
55 changes: 55 additions & 0 deletions win32/src/winapi/advapi32.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
#![allow(non_snake_case)]

use memory::ExtensionsMut;

use super::types::Str16;
use crate::machine::Machine;

const TRACE_CONTEXT: &'static str = "advapi32";

const REG_SZ: u32 = 0x00000001; // A string.

pub type HKEY = u32;

#[win32_derive::dllexport]
pub fn RegCreateKeyA(
_machine: &mut Machine,
hKey: HKEY,
lpSubKey: Option<&str>,
phkResult: Option<&mut u32>,
) -> u32 {
0
}

#[win32_derive::dllexport]
pub fn RegCreateKeyExW(
_machine: &mut Machine,
Expand All @@ -28,6 +42,47 @@ pub fn RegCloseKey(_machine: &mut Machine, hKey: HKEY) -> u32 {
0 // success
}

#[win32_derive::dllexport]
pub fn RegQueryValueExA(
machine: &mut Machine,
hKey: HKEY,
lpValueName: Option<&str>,
lpReserved: u32,
lpType: Option<&mut u32>,
lpData: u32,
lpcbData: Option<&mut u32>,
) -> u32 {
if matches!(lpValueName, Some("ProgramFilesDir")) {
// const PROGRAM_FILES: &str = "C:\\Program Files";
const PROGRAM_FILES: &str = "C:\\Users\\linus\\Program Files";

if let Some(lpType) = lpType {
*lpType = REG_SZ;
}

if lpData != 0 {
let in_out_len = lpcbData.unwrap();

if *in_out_len <= PROGRAM_FILES.len() as u32 {
return 234; // ERROR_MORE_DATA
}

*in_out_len = (PROGRAM_FILES.len() as u32) + 1;

let buf = machine.mem().sub32_mut(lpData, *in_out_len);

buf[..PROGRAM_FILES.len()].copy_from_slice(PROGRAM_FILES.as_bytes());
buf[PROGRAM_FILES.len()] = 0;
} else if let Some(lpcbData) = lpcbData {
*lpcbData = (PROGRAM_FILES.len() as u32) + 1;
}

return 0;
}

2 // ERROR_FILE_NOT_FOUND
}

#[win32_derive::dllexport]
pub fn RegQueryValueExW(
_machine: &mut Machine,
Expand Down
109 changes: 104 additions & 5 deletions win32/src/winapi/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ pub mod advapi32 {
let hKey = <HKEY>::from_stack(mem, esp + 4u32);
winapi::advapi32::RegCloseKey(machine, hKey).to_raw()
}
pub unsafe fn RegCreateKeyA(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, esp + 4u32);
let lpSubKey = <Option<&str>>::from_stack(mem, esp + 8u32);
let phkResult = <Option<&mut u32>>::from_stack(mem, esp + 12u32);
winapi::advapi32::RegCreateKeyA(machine, hKey, lpSubKey, phkResult).to_raw()
}
pub unsafe fn RegCreateKeyExW(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, esp + 4u32);
Expand All @@ -50,6 +57,25 @@ pub mod advapi32 {
)
.to_raw()
}
pub unsafe fn RegQueryValueExA(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, esp + 4u32);
let lpValueName = <Option<&str>>::from_stack(mem, esp + 8u32);
let lpReserved = <u32>::from_stack(mem, esp + 12u32);
let lpType = <Option<&mut u32>>::from_stack(mem, esp + 16u32);
let lpData = <u32>::from_stack(mem, esp + 20u32);
let lpcbData = <Option<&mut u32>>::from_stack(mem, esp + 24u32);
winapi::advapi32::RegQueryValueExA(
machine,
hKey,
lpValueName,
lpReserved,
lpType,
lpData,
lpcbData,
)
.to_raw()
}
pub unsafe fn RegQueryValueExW(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hKey = <HKEY>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -98,12 +124,24 @@ pub mod advapi32 {
stack_consumed: 4u32,
is_async: false,
};
pub const RegCreateKeyA: Shim = Shim {
name: "RegCreateKeyA",
func: impls::RegCreateKeyA,
stack_consumed: 12u32,
is_async: false,
};
pub const RegCreateKeyExW: Shim = Shim {
name: "RegCreateKeyExW",
func: impls::RegCreateKeyExW,
stack_consumed: 36u32,
is_async: false,
};
pub const RegQueryValueExA: Shim = Shim {
name: "RegQueryValueExA",
func: impls::RegQueryValueExA,
stack_consumed: 24u32,
is_async: false,
};
pub const RegQueryValueExW: Shim = Shim {
name: "RegQueryValueExW",
func: impls::RegQueryValueExW,
Expand All @@ -117,9 +155,11 @@ pub mod advapi32 {
is_async: false,
};
}
const SHIMS: [Shim; 4usize] = [
const SHIMS: [Shim; 6usize] = [
shims::RegCloseKey,
shims::RegCreateKeyA,
shims::RegCreateKeyExW,
shims::RegQueryValueExA,
shims::RegQueryValueExW,
shims::RegSetValueExW,
];
Expand Down Expand Up @@ -2765,8 +2805,8 @@ pub mod kernel32 {
}
pub unsafe fn LoadResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hModule = <u32>::from_stack(mem, esp + 4u32);
let hResInfo = <u32>::from_stack(mem, esp + 8u32);
let hModule = <HMODULE>::from_stack(mem, esp + 4u32);
let hResInfo = <HRSRC>::from_stack(mem, esp + 8u32);
winapi::kernel32::LoadResource(machine, hModule, hResInfo).to_raw()
}
pub unsafe fn LocalAlloc(machine: &mut Machine, esp: u32) -> u32 {
Expand All @@ -2782,7 +2822,7 @@ pub mod kernel32 {
}
pub unsafe fn LockResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hResData = <u32>::from_stack(mem, esp + 4u32);
let hResData = <HRSRC>::from_stack(mem, esp + 4u32);
winapi::kernel32::LockResource(machine, hResData).to_raw()
}
pub unsafe fn MulDiv(machine: &mut Machine, esp: u32) -> u32 {
Expand Down Expand Up @@ -2858,11 +2898,22 @@ pub mod kernel32 {
let _add = <u32>::from_stack(mem, esp + 8u32);
winapi::kernel32::SetConsoleCtrlHandler(machine, _handlerRoutine, _add).to_raw()
}
pub unsafe fn SetCurrentDirectoryA(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let lpPathName = <Option<&str>>::from_stack(mem, esp + 4u32);
winapi::kernel32::SetCurrentDirectoryA(machine, lpPathName).to_raw()
}
pub unsafe fn SetEndOfFile(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hFile = <HFILE>::from_stack(mem, esp + 4u32);
winapi::kernel32::SetEndOfFile(machine, hFile).to_raw()
}
pub unsafe fn SetEnvironmentVariableA(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let name = <Option<&str>>::from_stack(mem, esp + 4u32);
let value = <Option<&str>>::from_stack(mem, esp + 8u32);
winapi::kernel32::SetEnvironmentVariableA(machine, name, value).to_raw()
}
pub unsafe fn SetEvent(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hEvent = <HANDLE<()>>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -2949,6 +3000,12 @@ pub mod kernel32 {
winapi::kernel32::SetUnhandledExceptionFilter(machine, _lpTopLevelExceptionFilter)
.to_raw()
}
pub unsafe fn SizeofResource(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let hModule = <HMODULE>::from_stack(mem, esp + 4u32);
let hResInfo = <HRSRC>::from_stack(mem, esp + 8u32);
winapi::kernel32::SizeofResource(machine, hModule, hResInfo).to_raw()
}
pub unsafe fn Sleep(machine: &mut Machine, esp: u32) -> u32 {
let mem = machine.mem().detach();
let dwMilliseconds = <u32>::from_stack(mem, esp + 4u32);
Expand Down Expand Up @@ -3868,12 +3925,24 @@ pub mod kernel32 {
stack_consumed: 8u32,
is_async: false,
};
pub const SetCurrentDirectoryA: Shim = Shim {
name: "SetCurrentDirectoryA",
func: impls::SetCurrentDirectoryA,
stack_consumed: 4u32,
is_async: false,
};
pub const SetEndOfFile: Shim = Shim {
name: "SetEndOfFile",
func: impls::SetEndOfFile,
stack_consumed: 4u32,
is_async: false,
};
pub const SetEnvironmentVariableA: Shim = Shim {
name: "SetEnvironmentVariableA",
func: impls::SetEnvironmentVariableA,
stack_consumed: 8u32,
is_async: false,
};
pub const SetEvent: Shim = Shim {
name: "SetEvent",
func: impls::SetEvent,
Expand Down Expand Up @@ -3946,6 +4015,12 @@ pub mod kernel32 {
stack_consumed: 4u32,
is_async: false,
};
pub const SizeofResource: Shim = Shim {
name: "SizeofResource",
func: impls::SizeofResource,
stack_consumed: 8u32,
is_async: false,
};
pub const Sleep: Shim = Shim {
name: "Sleep",
func: impls::Sleep,
Expand Down Expand Up @@ -4085,7 +4160,7 @@ pub mod kernel32 {
is_async: true,
};
}
const SHIMS: [Shim; 148usize] = [
const SHIMS: [Shim; 151usize] = [
shims::AcquireSRWLockExclusive,
shims::AcquireSRWLockShared,
shims::AddVectoredExceptionHandler,
Expand Down Expand Up @@ -4198,7 +4273,9 @@ pub mod kernel32 {
shims::ReleaseSRWLockShared,
shims::RemoveDirectoryA,
shims::SetConsoleCtrlHandler,
shims::SetCurrentDirectoryA,
shims::SetEndOfFile,
shims::SetEnvironmentVariableA,
shims::SetEvent,
shims::SetFileAttributesA,
shims::SetFilePointer,
Expand All @@ -4211,6 +4288,7 @@ pub mod kernel32 {
shims::SetThreadPriority,
shims::SetThreadStackGuarantee,
shims::SetUnhandledExceptionFilter,
shims::SizeofResource,
shims::Sleep,
shims::SystemTimeToFileTime,
shims::TlsAlloc,
Expand Down Expand Up @@ -4404,6 +4482,27 @@ pub mod retrowin32_test {
raw: std::include_bytes!("../../dll/retrowin32_test.dll"),
};
}
pub mod shell32 {
use super::*;
mod impls {
use crate::{
machine::Machine,
winapi::{self, stack_args::*, types::*},
};
use memory::Extensions;
use winapi::shell32::*;
}
mod shims {
use super::impls;
use super::Shim;
}
const SHIMS: [Shim; 0usize] = [];
pub const DLL: BuiltinDLL = BuiltinDLL {
file_name: "shell32.dll",
shims: &SHIMS,
raw: std::include_bytes!("../../dll/shell32.dll"),
};
}
pub mod ucrtbase {
use super::*;
mod impls {
Expand Down
5 changes: 4 additions & 1 deletion win32/src/winapi/kernel32/dll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,11 @@ unsafe impl ::memory::Pod for STARTUPINFOA {}
pub fn GetStartupInfoA(_machine: &mut Machine, lpStartupInfo: Option<&mut STARTUPINFOA>) -> u32 {
// MSVC runtime library passes in uninitialized memory for lpStartupInfo, so don't trust info.cb.
let info = lpStartupInfo.unwrap();
let len = std::cmp::min(info.cb, std::mem::size_of::<STARTUPINFOA>() as u32);
let len = std::mem::size_of::<STARTUPINFOA>() as u32;
Copy link
Owner

Choose a reason for hiding this comment

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

By the way, I checked and I now believe that STARTUPINFOA has never changed in size, so my worries about callers passing in an undersized buffer or something like that are unfounded. And further I checked and at least win2k's kernel32.dll does exactly what you've done here, so I think this is correct.

unsafe { info.clear_memory(len) };

info.cb = len;

0
}

Expand Down
Loading