Git Product home page Git Product logo

Comments (17)

rodrigocfd avatar rodrigocfd commented on May 24, 2024 1

Yeah, I just did this. This kind of undocumented behavior is really hard to work with.

Thank you very much for your help.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024 1

@michidk I changed this function to return an iterator, so the loop work is done internally. If you're still interested, I'd be glad to hear if it works for you.

New docs with example can be found here.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

As far as I could investigate, the enumeration ends when EnumDisplayDevices returns zero and GetLastError returns ERROR_PROC_NOT_FOUND, therefore the foolproof implementation has to consider this. The check is necessary to rule out legitimate errors.

I changed the implementation to reflect this. Please let me know if this worked for you.

from winsafe.

michidk avatar michidk commented on May 24, 2024

Wow that was quick :D. I am not too familiar with winapi error handling stuff, but if I adjusted my code like mentioned in the example:

/// Returns a list of all displays.
pub fn discover_displays() -> Result<DisplaySet> {
    let mut result = Vec::<Display>::new();

    let mut dev_num: u32 = 0;
    let mut display_device = DISPLAY_DEVICE::default();

    loop {
        let has_more = EnumDisplayDevices(
            None,
            dev_num,
            &mut display_device,
            EDD::GET_DEVICE_INTERFACE_NAME,
        )?;

        if has_more {
            result.push(Display::from_winsafe(dev_num, &display_device)?);
            dev_num += 1;
        } else {
            break;
        }
    }

    Ok(DisplaySet { displays: result })
}

Then the fn returns early with the following Err: "[0x00cb 203] The system could not find the environment option that was entered.".

The following works fine:

        let has_more = EnumDisplayDevices(
		...
        ); // no `?`

        if has_more.is_ok() { // `is_ok()` instead
            result.push(Display::from_winsafe(dev_num, &display_device)?);
            dev_num += 1;
        } else {
            break;
        }

This might have to do with the fact that I have one display that is active: false?

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

Indeed, it seems that a display with active: false returns an error for that specific index, and since this is meaningful to you, you'll have to treat that error specifically, and turn the active into some sort of flag. Maybe something like this:

{
	use winsafe as w;

	let mut dev_num: u32 = 0;
	let mut display_device = w::DISPLAY_DEVICE::default();

	loop {
		let (is_good, is_active) = match w::EnumDisplayDevices(
			None,
			dev_num,
			&mut display_device,
			w::co::EDD::GET_DEVICE_INTERFACE_NAME,
		) {
			Ok(r) => (r, true), // active
			Err(e) => match e {
				w::co::ERROR::ENVVAR_NOT_FOUND => (true, false), // inactive
				_ => panic!("Actual error!"),
			}
		};

		if is_good {
			// result.push(Display::from_winsafe(dev_num, &display_device)?);
			println!("{}, active: {}", display_device.DeviceName(), is_active);
			dev_num += 1;
		} else {
			break;
		}
	}
}

from winsafe.

michidk avatar michidk commented on May 24, 2024

When I run your code, I get an infinite loop, because is_good is always true.

But it should stop after there is no display anymore right? I have three active displays and one inactive. This means it should iterate five times, and since the fifth display does not exist an error ("The system could not find the environment option that was entered.") will be thrown and the code should break. This is not the case with the code you just posted.

from winsafe.

michidk avatar michidk commented on May 24, 2024

I only have three displays attached to the four DisplayPort ports on my GPU (maybe the fourth one is also some kind of virtual display output device).
This is how the API calls look in APIMonitor:
image
While all other displays have the active flag there, my fourth "display" shows this flag:
image

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

This is very unsettling... please run the code below and post back the results:

{
	use winsafe as w;

	for n in 0..8 {
		let mut dide = w::DISPLAY_DEVICE::default();
		let ret = w::EnumDisplayDevices(
			None, n, &mut dide, w::co::EDD::GET_DEVICE_INTERFACE_NAME);
		match ret {
			Ok(b) => println!("{} Ok {}", n, b),
			Err(e) => println!("{} Err {}", n, e),
		}
	}
}

from winsafe.

michidk avatar michidk commented on May 24, 2024

Results in an infinite loop with the following output

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

It's just a for iterating from 0 to 7... it can't be an infinite loop.

Are you running this code inside something else?

from winsafe.

michidk avatar michidk commented on May 24, 2024

Agh sorry. Wanted to get back to you ASAP and got sloppy: I had another loop {} around this from code before. This code actually doesn't loop. Output is just:

0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.

5 Err [0x00cb 203] The system could not find the environment option that was entered.

6 Err [0x00cb 203] The system could not find the environment option that was entered.

7 Err [0x00cb 203] The system could not find the environment option that was entered.

The code snippet you posted earlier (before the last one) still leads to endless looping.

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

What about this example in the docs? Does it still loop?

from winsafe.

michidk avatar michidk commented on May 24, 2024

No, it does not loop on the latest commit. However, an error is thrown:

0: \\.\DISPLAY1 - NVIDIA GeForce GTX 1080
1: \\.\DISPLAY2 - NVIDIA GeForce GTX 1080
2: \\.\DISPLAY3 - NVIDIA GeForce GTX 1080
3: \\.\DISPLAY4 - NVIDIA GeForce GTX 1080
Error:
   0: [0x00cb 203] The system could not find the environment option that was entered.
   0:

Location:
   src\display.rs:462

The error occurs on the following line:
let is_good = EnumDisplayDevices(None, dev_num, &mut dide, co::EDD::NoValue)?;

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

This means that when the loop ends, GetLastError returns code 203, which should be the stop condition.

However... on my computer, it returns code 127 instead. That's odd.

I'm on Windows 10 x64, what's yours?

from winsafe.

michidk avatar michidk commented on May 24, 2024

Win 10 Pro x64

from winsafe.

rodrigocfd avatar rodrigocfd commented on May 24, 2024

OK, so I completely removed the internal error checking, and the zero is always considered the "done" state now.

Let me know if this works for you.

from winsafe.

michidk avatar michidk commented on May 24, 2024

Output now is:

0: \\.\DISPLAY1 - NVIDIA GeForce GTX 1080
1: \\.\DISPLAY2 - NVIDIA GeForce GTX 1080
2: \\.\DISPLAY3 - NVIDIA GeForce GTX 1080
3: \\.\DISPLAY4 - NVIDIA GeForce GTX 1080

So it works!

We could also handle just 127 as well as 203 as codes for Ok(false).

from winsafe.

Related Issues (20)

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.