Git Product home page Git Product logo

winsafe's People

Contributors

amithkk avatar anatawa12 avatar azam avatar caesay avatar cashtang avatar michidk avatar roblabla avatar rodrigocfd avatar sollyucko avatar tomzbench avatar y15un avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

winsafe's Issues

Adding a safe wrapper around ChangeDisplaySettingsExW

Currently, this crate only has a wrapper around ChangeDisplaySettingsW, which is limited to changing device settings for the "Default" or primary display. However this crate already provides EnumDisplaySettingsExW that allows you to retrieve the DEVMODE struct for any display

This issue proposes adding ChangeDisplaySettingsExW which takes in a parameter to specify the device name so that one can both read and write device settings for all displays

CreateWindowEx is unsound

lpParam needs to be a valid pointer in some cases:

If an application calls CreateWindow to create a MDI client window, lpParam should point to a CLIENTCREATESTRUCT structure. If an MDI client window calls CreateWindow to create an MDI child window, lpParam should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw

However, CreateWindowEx is not unsafe, performs no relevant parameter validation, and makes lparam a simple to misconstruct Option<isize>.

/// [`CreateWindowEx`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw)
/// static method.
fn CreateWindowEx(
ex_style: co::WS_EX,
class_name: AtomStr,
title: Option<&str>,
style: co::WS,
pos: POINT,
size: SIZE,
hwnd_parent: Option<HWND>,
hmenu: IdMenu,
hinstance: HINSTANCE,
lparam: Option<isize>) -> WinResult<HWND>

There's SetClipboardData but not GetClipboardData yet?

Also, how does one use SetClipboardData?

I tried this:

    fn events(&self) {
        self.btn_hello.on().bn_clicked({
            let self2 = self.wnd.clone(); // clone so it can be passed into the closure
            move || {
                let mut ptr = b"Hello World\0".to_vec().as_mut_ptr() as *mut u8;
                self2.hwnd().OpenClipboard();
                SetClipboardData(CF::TEXT, ptr);
                CloseClipboard();

(modified from https://github.com/rodrigocfd/winsafe-examples/blob/941627b5ea93d7e7e564c91478a88a1d64e2dcf4/01_button_click/src/my_window.rs#L38-L41)

But when I click the button, the program crashes with:

error: process didn't exit successfully: `target\debug\app.exe` (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)

Sending messages to unsupported controls

For example, the msctls_progress32 control does not seem to be supported yet. Is there a way to send custom messages to unsupported controls created in .resource files, using this function?

winsafe/src/handles/hwnd.rs

Lines 973 to 982 in 82bcca0

pub fn SendMessage<M: MsgSend>(self, uMsg: M) -> M::RetType {
let wmAny = uMsg.as_generic_wm();
uMsg.convert_ret(
unsafe {
user32::SendMessageW(
self.ptr, wmAny.msg_id.0, wmAny.wparam, wmAny.lparam,
)
},
)
}

In this specific case, I'd like to send PBM_SETSTEP messages.

HKEY::QueryValueEx and GetValue contain race conditions and lack length-versus-type checking

These two functions work in two stages: first they do the query with a null buffer to discover the type and length of the data, then they do the query a second time with an allocated buffer of the specified length. However, another process, or another thread of the same process, could have modified the value in the registry in between the two calls. Thus:

  • If the other process made the data larger, the buffer will be too small and the second call will fail. This is arguably correct behaviour, but it seems like it would be more useful if the library were to loop and enlarge the buffer further in this case.
  • If the other process made the data smaller, the new length returned by the second query is not used, rather the full buffer is decoded, meaning you get a return value containing the new data followed by some filler.
  • If the other process changed the type of the data, then the new bytes are decoded based on the old data type.

Furthermore, even in the absence of race conditions, there is no checking that the returned length makes sense for the given type. This is not guaranteed by the Windows API: it is totally possible to construct a REG_DWORD that is three or seven bytes long, or a REG_SZ whose length is odd or that does not end in a NUL. You can even do this in RegEdit by right-clicking a value and clicking Modify Binary. This lack of checking means that, for example, if the registry contains a three-byte REG_DWORD, then when constructing the return value, u32::from_ne_bytes(buf.try_into().unwrap()) will panic because buf is not four bytes long. This should be caught and returned as a proper error, since an application should never be forced to panic under the control of external data.

Can't construct TRACKMOUSEEVENT

Does winsafe support creating TRACKMOUSEEVENT?

I get an error related to private fields.

let mut mouse_event = winsafe::TRACKMOUSEEVENT {
  dwFlags: winsafe::co::TME::HOVER | winsafe::co::TME::LEAVE,
  hwndTrack: self.lbl.hwnd(),
  dwHoverTime: 0,
  ..Default::default()
//^^^^^^^^^^^^^^^^^^^^ field `cbSize` is private
};
winsafe::TrackMouseEvent(&mut mouse_event);

let label_events = self.lbl.on_subclass();
label_events.wm_mouse_hover({
  move |params| {
    println!("{},{}", params.coords.x, params.coords.y);
  }
});

WM_MENUSELECT

I can listen for menu list open events. But what about for when a specific menu item is clicked? I dont see WM_MENUSELECT in the documentation.

My menu is created in a resource file, if it matters.

screenshot

Load icon from file?

let name: u16 = // ?
let h_icon = HINSTANCE::NULL.LoadImageIcon(name, 16, 16, LR::LOADFROMFILE);

Why is name a u16? Shouldn't a filename string be accepted?

I would like to change the window icon at runtime from a file that isn't included in the resources.

GetDlgCtrlId fails if the child window’s ID is actually zero

The wrapper for GetDlgCtrlId tries to distinguish between zero-as-success and zero-as-failure by calling GetLastError. However, it does not call SetLastError(ERROR_SUCCESS) before calling GetDlgCtrlId, which means if the last error code was non-successful on entry and the value is zero, a spurious error will be returned. The documentation is vague as to whether the last error code is cleared on success or not by the underlying Windows API call, but I encountered this personally and it is not, so you should probably do it in the wrapper.

Incorrect message parameters for WM_CHAR and friends

In commit 8335fe2, you changed the pub_struct_msg_char macro to generate a char_code field of type co::VK rather than u16. That macros is used for lots of messages right now, but their wParams aren’t all the same!

  • WM_CHAR gives a character code.
  • WM_KEYDOWN gives a virtual-key code.
  • WM_KEYUP gives a virtual-key code.
  • WM_SYSCHAR gives a character code.
  • WM_SYSDEADCHAR gives a character code.
  • WM_SYSKEYDOWN gives a virtual-key code.
  • WM_SYSKEYUP gives a virtual-key code.

Only those that carry a virtual-key code should be of type VK. The ones that carry a character code are either UTF-16 code units if the window class was registered with RegisterClassW or RegisterClassExW, or code page characters if registered with RegisterClassA or RegisterClassExA. So they should go back to being of type u16 (don’t use char since some sources claim that a non-BMP character could be delivered by two consecutive WM_CHAR messages each containing a surrogate, and a Rust char cannot contain a surrogate, so each message on its own would fail to decode; only later after reassembling both messages do you actually have a complete character).

Circular reference via event handlers causes memory leak

I think there is a memory leak in the 02_combo_and_radios example, which might be best addressed in this repo rather than in the example. Remove the #[derive(Clone)] from MyWindow and implement that and Drop by hand, with instrumentation, to see it:

pub struct MyWindow {
	wnd:        gui::WindowMain,
	cmb_cities: gui::ComboBox,
	rad_seas:   gui::RadioGroup,
}

impl Clone for MyWindow {
	fn clone(&self) -> Self {
		println!("Clone");
		Self {
			wnd: self.wnd.clone(),
			cmb_cities: self.cmb_cities.clone(),
			rad_seas: self.rad_seas.clone(),
		}
	}
}

impl Drop for MyWindow {
	fn drop(&mut self) {
		println!("Drop");
	}
}

When you run the code you see “Clone” printed three times (so there are four instances of MyWindow, the one created directly in MyWindow::new and then the three clones captured in event handler closures), but “Drop” is only printed once! So three objects have been leaked. The problem, if I understand correctly, is that there is a circular reference:

  1. The MyWindow contains a gui::WindowMain.
  2. The WindowMain contains a RawDlg, in this case the RawDlg::Raw variant.
  3. The RawDlg::Raw contains a RawMain.
  4. The RawMain contains a Pin<Arc<Obj>>.
  5. The Obj contains a RawBase.
  6. The RawBase contains a Base.
  7. The Base contains a WindowEventsAll.
  8. The WindowEventsAll contains a FuncStore<(u16, co::NM), Box<dyn Fn(wm::Notify) -> AnyResult<Option<isize>>>.
  9. The FuncStore contains a Vec<Pair> with one element.
  10. The element of the Vec contains a Box.
  11. The Box contains a the closure passed to ComboBoxEvents::cbn_sel_change.
  12. The closure contains a MyWindow.

So the Pin<Arc<Obj>> in step 4 contains, via a very long chain, a reference to itself.

Application code could fix this if it was very careful: instead of cloning MyWindow, it could hold MyWindow behind an Rc and always downgrade the Rc to a Weak and capture the Weak as part of the closure, upgrading it on each call; thus step 12 would break the cycle (since the closure would only contain a Weak). However, this is unintuitive and it would be easy to get it wrong.

I noticed you are only allowed to register event handlers before the HWND has been created. I wonder, would it make any sense that, when the HWND is destroyed, you drop all the event handlers? After all, if the HWND has been destroyed, they aren’t needed any more (since no more events can be delivered to them), and dropping them would break the circular reference. Although I’m not sure how well that would work with dynamic creation and destruction of controls, since many event handlers conceptually belong to child windows (e.g. WM_COMMAND handlers for buttons) but are actually registered against the parent (since that’s where the WM_COMMAND is actually sent).

HDC::GetDIBits

Hi, I'm trying to get a screenshot using winsafe, but there's no GetDIBits function, can it be added?

With windows-rs it looks atrocious:

let mut bmi = BITMAPINFO {
    bmiHeader: BITMAPINFOHEADER {
        biSize: std::mem::size_of::<BITMAPINFOHEADER>() as u32,
        biWidth: bmp.bmWidth,
        biHeight: -bmp.bmHeight,
        biPlanes: 1,
        biBitCount: 32,
        biCompression: BI_RGB as u32,
        biSizeImage: 0,
        biXPelsPerMeter: 0,
        biYPelsPerMeter: 0,
        biClrUsed: 0,
        biClrImportant: 0,
    },
    bmiColors: [RGBQUAD {
        rgbBlue: 0,
        rgbGreen: 0,
        rgbRed: 0,
        rgbReserved: 0,
    }],
};

//let size: usize = (width * height) as usize * 4;
let size: usize = (((bmp.bmWidth * (bmi.bmiHeader.biBitCount as i32) + 31) / 32) * 4 * bmp.bmHeight) as usize;
let mut data: Vec<u8> = Vec::with_capacity(size);
unsafe { data.set_len(size) };

unsafe {
    GetDIBits(
        hdc_mem, hbmp, 0, height as u32, &mut data[0] as *mut u8 as *mut c_void,
        &mut bmi,
        DIB_RGB_COLORS,
    );
}

WM_MOUSEMOVE for controls?

I would like to handle MOUSEMOVE for a label, but it doesn't have such an event. I don't think labels support custom messages like here, right?

I can't use self.wnd.on().wm_mouse_move({ because it stops firing when the cursor moves over a control.

Null value for bind_ctx

Hey all

I'm trying to translate a piece of c++ code (https://stackoverflow.com/questions/59926644/listing-of-installed-apps-on-windows-10) to rust. In it the author uses the BindToHandler function. I found that method in this crate as well but the problem is that in the original c++ code they pass a nullptr for the bindcontext. Since the bind context parameter in the BindToHandler method is not an option I can't pass None like I did with SHCreateItemFromParsingName. What would be the equivalent here of passing a NULL value in c++?

kr

winsafe::MSG doesn't match layout of windows.h MSG on 32-bit

The lpPrivate field at the end here:

winsafe/src/user/structs.rs

Lines 433 to 443 in 6540aea

#[repr(C)]
#[derive(Clone)]
pub struct MSG {
pub hwnd: HWND,
pub message: co::WM,
pub wParam: usize,
pub lParam: isize,
pub time: u32,
pub pt: POINT,
lPrivate: u32,
}

Is only defined by windows.h if _MAC (macos / OS X) is defined:

typedef struct tagMSG {
    HWND        hwnd;
    UINT        message;
    WPARAM      wParam;
    LPARAM      lParam;
    DWORD       time;
    POINT       pt;
#ifdef _MAC
    DWORD       lPrivate;
#endif
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

On 64-bit, there's some implicit padding there anyways. That's a bit sketchy if MSG were ever to be combined with MaybeUninit, as lPrivate could end up being left uninitialized.

On 32-bit, this actually changes the struct size (winsafe::MSG is 32 bytes, windows.h MSG is 28 bytes.)

Perhaps use #[cfg(target_os = "macos")] ?

cargo fmt, maybe?

currently this repo indents with tabs, but the style guide recommends to use spaces (4, specifically).

this bugged me greatly because by default vscode with rust extension will do 'format document' automatically upon every save, and it tries to convert all the indenting tabs to spaces.

there are two options i'd like to recommend:

  1. switch to spaces: doing a cargo fmt run to get a sane-enough outcome now
    • warning: this will create a massive commit, but better do this now than later i guess?
  2. keep using tabs: have a rustfmt.toml added to the repo with hard_tabs set to true
    • this will at least prevent vscode trying to auto-reformat document on every save.

just my two cents!

Request: Wrapper for GetVolumeInformationW

I'd like to request a wrapper for GetVolumeInformation/GetVolumeInformationA/GetVolumeInformationW. Probably the last one, since that speaks Unicode.

(Use case: I need to do something cross-plaform, but don't have a modern Windows dev environment. So I want to cross-compile. Thanks.)

ListBox missing SetCurSel event

The event is missing from the list in the documentation:

https://rodrigocfd.github.io/winsafe/winsafe/msg/lb/index.html

But it's in the Microsoft documentation:

https://docs.microsoft.com/en-us/windows/win32/controls/lb-setsel

I think it should look something like this:

winsafe::msg::lb::SetCurSel { 
  select: bool, 
  index: u32
}

Without it, there's no guaranteed way to uniquely select an item by index. SelectString can be used to select the first item beginning with a certain string, but fails to select Hello if that item is preceded by Hello World!.

Correct me if I'm wrong ...

Way to instantiate an arbitrary control when using gui

It would be nice if there were a clean way to build most of a GUI using the safe, high-level gui module, but include one or two controls that are not supported by Winsafe (either Microsoft common controls that Winsafe doesn’t wrap yet, or perhaps third-party controls in a linked DLL). Here are the ways I could think of to achieve that, along with why they’re not ideal:

  • You can’t use WindowControl::new because it insists on registering the class, which is inappropriate for an already-registered class.
  • If you use CreateWindowEx with no control ID, you can’t use .on().wm_notify(…) to receive WM_NOTIFY messages relating to the control because you have no control ID, which is a mandatory parameter to the wm_notify method.
  • If you use CreateWindowEx with no control ID, you can’t use .on().wm(WM::NOTIFY, ...) and match the HWND in the NMHDR, because callbacks registered with .wm(WM::NOTIFY, …) don’t seem to get called at all (it seems like WM_NOTIFY must be special-cased and not handleable via general-purpose message handlers).
  • If you use CreateWindowEx with a control ID, it works, but the auto-generated control IDs that Winsafe uses under the hood for the gui module are not available for clients to allocate and the value range is undocumented AFAICT, so it’s impossible to choose a safe, non-colliding control ID purely from publicly documented information.

How to change label text color?

As you can see in the code below, parms.hwnd is always the handle to my label, because it's the only control on the window. But the text is still black, not red as intended. Is this a bug, just an unsupported feature, or am I doing something wrong?

I've tried to translate what I've read on stackoverflow into the corresponding winsafe version. The answers there say to return an HBRUSH, but the compiler says it must return an HDC, so I figured setting the brush of the HDC is equivalent.

self.wnd.on().wm_ctl_color_static({
  let self2 = self.clone();
  move |parms| {
    println!("{:?}", parms.hwnd == self2.lbl.hwnd()); // true
    let red = COLORREF::new(0xff, 0x00, 0x00);
    let brush = HBRUSH::CreateSolidBrush(red).unwrap();
    parms.hdc.SelectObjectBrush(brush);
    parms.hdc.SetTextColor(red).unwrap();
    parms.hdc.SetBkMode(winsafe::co::BKMODE::TRANSPARENT);
    parms.hdc
  }
});

[0.0.11] Example from readme fails with Ordinal not found error

Windows 11, rust, added winsafe with gui feature, copy-pasted code from readme, cargo.exe build, cargo.exe run

rustc 1.64.0-nightly (1c7b36d4d 2022-07-12)
binary: rustc
commit-hash: 1c7b36d4db582cb47513a6c7176baaec1c3346ab
commit-date: 2022-07-12
host: x86_64-pc-windows-msvc
release: 1.64.0-nightly
LLVM version: 14.0.6

image
Output of cargo.exe run:

> cargo.exe run
   Compiling winsafe v0.0.11
   Compiling test v0.1.0 (<path>)
    Finished dev [unoptimized + debuginfo] target(s) in 15.00s
     Running `target\debug\test.exe`
error: process didn't exit successfully: `target\debug\test.exe` (exit code: 0xc0000138, STATUS_ORDINAL_NOT_FOUND)

With latest master:

> cargo.exe run
    Updating git repository `https://github.com/rodrigocfd/winsafe`
   Compiling winsafe v0.0.11 (https://github.com/rodrigocfd/winsafe#7c14269e)
   Compiling test v0.1.0 (<path>)
    Finished dev [unoptimized + debuginfo] target(s) in 22.23s
     Running `target\debug\test.exe`
error: process didn't exit successfully: `target\debug\test.exe` (exit code: 0xc0000138, STATUS_ORDINAL_NOT_FOUND)

Add support for IEnumShellItems

hi

I'm trying to use the BindToHandler method to iterate over objects in a folder. According to the examples I have found I should use the EnumItems BHID for that. But that constant requires the IEnumShellItems interface which I don't believe is supported in this library. I have attemtped to use IShellItemArray instead like so let ish_arr = shi.BindToHandler::<IShellItemArray>(None, &BHID::EnumItems).unwrap(); but then I get a No such interface supported.

Is there an alternative to this or will this interface be supported in the near-future?

Thanks!

[Question] How do I send mouse and key events

Hey, thank you for working on this project, its great !.
I am playing around with winapi in general for learning, so what is the correct way to send mouse and key events to a window since I could use this in a work project for automation of an app at work , it is already in production but I used global key events so this would be better using direct msg .

I wonder if this should work, cuz it doss not seem to work for me no right click happens,
and the FindWindow function should not not have the class name as an Optional?
and is the xy cords relative to the window or the screen? Thank you :)
rs```
let hwnd = HWND::FindWindow("Notepad", "Untitled - Notepad")?;
hwnd.SetForegroundWindow();
hwnd.SetFocus();
let m = wm::RButtonDown {
vkey_code: co::VK::RBUTTON,
coords: POINT { x: 8, y: 8 },
};
hwnd.SendMessage(m);

File Open Dialog

How to show the file open dialog?

let mut foo: winsafe::IUnknown = winsafe::CoCreateInstance(
  &winsafe::shell::clsid::FileOpenDialog,
  None,
  winsafe::co::CLSCTX::INPROC_SERVER,
).unwrap();

This code runs without errors but doesn't show a file open dialog.

WebView2 control

I would like to keep using Rust instead of switching to C#, but I never did any win32 programming so winsafe is very helpful. I've looked into webview2-rs, but the public API is full of unsafe and I found the sample code too complicated compared to winsafe...

Could WebView2 be added to winsafe somehow? I understand WebView2 is very new relative to the classic controls, but I think it would be pretty amazing, if it's doable.

DispatchMessage, SendMessage, DefWindowProc, and PostThreadMessage are all unsound.

Sending window messages in general should be unsafe. DispatchMessage - among others - is not.

winsafe/src/user/funcs.rs

Lines 100 to 103 in 06b1c08

/// [`DispatchMessage`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessagew)
/// function.
#[cfg_attr(docsrs, doc(cfg(feature = "user")))]
pub fn DispatchMessage(msg: &MSG) -> isize {

While the underlying DispatchMessage does a lot of parameter checking - including forbidding most system messages that interpret wparam/lparam as pointers by returning ERROR_MESSAGE_SYNC_ONLY - it cannot do the same for WM_USER+n or WM_APP+n messages which might interpret wparam/lparam as pointers.

For example, Microsoft's own TOOLBARCLASSNAME ("ToolbarWindow32") expects wparam to be a pointer to an array for TB_ADDBUTTONSW (WM_USER+68). While the docs recommend using SendMessage, DispatchMessage also works, and can crash / access violation if fed an invalid pointer. Other messages could even mutate what's pointed to, causing random memory corruption instead of a nice and clean access violation.

This means that if any middleware, library, injected DLL, etc. might ever create a window containing a toolbar on one of your threads, you can use DispatchMessage to cause undefined behavior.


SendMessage and DefWindowProc have similar issues, although there are traits involved muddying things up. Additionally, SendMessage won't reject messages with ERROR_MESSAGE_SYNC_ONLY to my knowledge. The traits involved are "safe" - it appears you're able to implement them to use e.g. WM::SETTEXT without any unsafe, despite the possibility of passing an invalid pointer in wparam for the string text.

PostThreadMessage at least won't dispatch to a wndproc... but I promise you that third parties will inject threads into your process (game overlays, debuggers, ...), and will treat wparam/lparam as pointers for some WM_USER+N messages.

HWDP guard does not handle changed handles nor failures correctly

The RAII guard for an HDWP returned by BeginDeferWindowPos is implemented the same way as lots of other RAII guards. However, in the case of an HDWP, that is incorrect for two reasons:

  1. Per the return value documentation of DeferWindowPos, “The handle returned by this function may differ from the handle passed to the function. The new handle that this function returns should be passed during the next call to the DeferWindowPos or EndDeferWindowPos function.” In other words, the old handle must not be ended nor reused, and the new handle (which DeferWindowPos currently returns as an unguarded HDWP) must be ended. What should probably ideally happen is that the handle living in the guard is swapped out for the return value on each call, and maybe DeferWindowPos should return SysResult<()> instead of SysResult<HDWP>.
  2. Per the remarks documentation of that same function, “If a call to DeferWindowPos fails, the application should abandon the window-positioning operation and not call EndDeferWindowPos.” But as written, in case of failure, the RAII guard will still call EndDeferWindowPos.

RegOpenKeyEx doesn’t work

RegOpenKeyEx always returns a null HKEYon success. The problem is that a null HKEY is constructed, then hKey.as_ptr() is passed into the raw function, which means it will store the newly opened HKEY into wherever hKey pointed at, which is null, rather than into hKey itself. I changed the function to look like this and it now works, but I imagine raw types like c_void probably aren’t supposed to appear here; I just don’t really quite understand all the type aliases so it was the fastest and simplest fix I could come up with:

	fn RegOpenKeyEx(self, sub_key: &str,
		options: co::REG_OPTION, access_rights: co::KEY) -> SysResult<HKEY>
	{
		let mut hKey: *mut std::ffi::c_void = std::ptr::null_mut();

		match co::ERROR(
			unsafe {
				advapi::ffi::RegOpenKeyExW(
					self.as_ptr(),
					WString::from_str(sub_key).as_ptr(),
					options.0,
					access_rights.0,
					&mut hKey as _,
				)
			} as _,
		) {
			co::ERROR::SUCCESS => Ok(unsafe { HKEY::from_ptr(hKey) }),
			err => Err(err),
		}
	}

Feature request: MONITORINFOEX struct

It would be nice to have a GetMonitorInfo function on the HMONITOR struct that supports MONITORINFOEX as an input, or make the existing function support it.

SS_CENTER flag on Label not working

I created the resource file in Resource Hacker, and saved the label with the SS_CENTER flag:

resource hacker screenshot

But in the program it's displayed as left-aligned:

bug screenshot

Code:

myself.lbl.set_text(&myself.input_val.borrow()).unwrap();

WindowControlOpts::ctrl_id does not auto-generate an ID

Create a WindowControl without setting WindowControlOpts::ctrl_id to anything. The documentation says a control ID will be auto-generated; in actual fact, the window is created with a child ID of zero. It works for other controls (at least the ones I checked), just not WindowControl.

[user] EnumDisplayDevices result

The EnumDisplayDevices function returns a WinResult. I don't see where Ok(true) is ever set. It also seems like it is not required because we also return a result.

Also, the current example in the docs of that function is a bit weird. The function is supposed to be called until the first error because that means that we finished iterating over all displays:

if !is_finished {

will never be the case, because the ? will return the error.

set background color of a label

This is a great piece of work.
But how do you set the bk color of a label (or set the mode to transparent)?
An example would be very helpful. Thanks!

create gui with resedit ?

Hi,
when you say that "WinSafe works with both ordinary windows and resource dialogs", does it mean that it will be possible to use a tool like ResEdit to create the GUI visually (or parts of it..) with it's dialog editor and use the .rc file created ?

Reg{Create,Open}KeyTransacted should take transaction by reference

Lots of things that take a handle take it by reference, since the commit that made handles non-Copy and non-Clone—for example, SetParent takes an &HWND as the new parent, not an HWND. RegCreateKeyTransacted and RegOpenKeyTransacted currently take the HTRANSACTION by value; it probably makes sense for them to take it by reference instead, to avoid ugly calls to raw_copy in user code.

Copyable handles are probably unsound

The fact that you can close a handle and then keep using it (since e.g. RegCloseKey takes self by value, but HANDLE impls Copy so you can keep using the value afterwards anyway) seems unsound. Immediate reuse generally results in the invalid handle error being reported, but if you wait and reuse it later after other code has run, the handle value might match a newly opened handle. That new handle would definitely point at the wrong thing (e.g. a registry key handle opened for one key, when reused, would now modify a totally different key), and might even be the wrong type (e.g. a registry key handle might now refer to a file instead). This seems like it should probably be considered to violate memory safety.

Cannot infer type

I know this is probably more of a newbie rustacean issue, but I've tried match without any luck:

let color: winsafe::COLORREF = winsafe::COLORREF::new(0xff, 0x00, 0x00);
let brush: winsafe::HBRUSH = GdiHbrush::CreateSolidBrush(color).unwrap();
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type

I'm trying to set the main window's background color.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.