-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Parse more physical monitor size information #2310
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
Merged
matt335672
merged 1 commit into
neutrinolabs:devel
from
matt335672:physical_desktop_size
Aug 1, 2022
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| #include "ms-rdpbcgr.h" | ||
|
|
||
| #define MAX_BITMAP_BUF_SIZE (16 * 1024) /* 16K */ | ||
| #define TS_MONITOR_ATTRIBUTES_SIZE 20 /* [MS-RDPBCGR] 2.2.1.3.9 */ | ||
|
|
||
| /******************************************************************************/ | ||
| struct xrdp_session *EXPORT_CC | ||
|
|
@@ -1764,6 +1765,97 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data, | |
| return xrdp_rdp_send_session_info(rdp, data, data_bytes); | ||
| } | ||
|
|
||
| /*****************************************************************************/ | ||
| /* | ||
| Sanitise extended monitor attributes | ||
|
|
||
| The extended attributes are received from either | ||
| [MS-RDPEDISP] 2.2.2.2.1 (DISPLAYCONTROL_MONITOR_LAYOUT), or | ||
| [MS-RDPBCGR] 2.2.1.3.9.1 (TS_MONITOR_ATTRIBUTES) | ||
|
|
||
| @param monitor_layout struct containing extended attributes | ||
| */ | ||
| static void | ||
| sanitise_extended_monitor_attributes(struct monitor_info *monitor_layout) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this refactor, especially because it helps clean up and clarify what extended monitor attributes are! |
||
| { | ||
| /* if EITHER physical_width or physical_height are | ||
| * out of range, BOTH must be ignored. | ||
| */ | ||
| if (monitor_layout->physical_width > 10000 | ||
| || monitor_layout->physical_width < 10) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:" | ||
| " physical_width is not within valid range." | ||
| " Setting physical_width to 0mm," | ||
| " Setting physical_height to 0mm," | ||
| " physical_width was: %d", | ||
| monitor_layout->physical_width); | ||
| monitor_layout->physical_width = 0; | ||
| monitor_layout->physical_height = 0; | ||
| } | ||
|
|
||
| if (monitor_layout->physical_height > 10000 | ||
| || monitor_layout->physical_height < 10) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:" | ||
| " physical_height is not within valid range." | ||
| " Setting physical_width to 0mm," | ||
| " Setting physical_height to 0mm," | ||
| " physical_height was: %d", | ||
| monitor_layout->physical_height); | ||
| monitor_layout->physical_width = 0; | ||
| monitor_layout->physical_height = 0; | ||
| } | ||
|
|
||
| switch (monitor_layout->orientation) | ||
| { | ||
| case ORIENTATION_LANDSCAPE: | ||
| case ORIENTATION_PORTRAIT: | ||
| case ORIENTATION_LANDSCAPE_FLIPPED: | ||
| case ORIENTATION_PORTRAIT_FLIPPED: | ||
| break; | ||
| default: | ||
| LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:" | ||
| " Orientation is not one of %d, %d, %d, or %d." | ||
| " Value was %d and ignored and set to default value of LANDSCAPE.", | ||
| ORIENTATION_LANDSCAPE, | ||
| ORIENTATION_PORTRAIT, | ||
| ORIENTATION_LANDSCAPE_FLIPPED, | ||
| ORIENTATION_PORTRAIT_FLIPPED, | ||
| monitor_layout->orientation); | ||
| monitor_layout->orientation = ORIENTATION_LANDSCAPE; | ||
| } | ||
|
|
||
| int check_desktop_scale_factor | ||
| = monitor_layout->desktop_scale_factor < 100 | ||
| || monitor_layout->desktop_scale_factor > 500; | ||
| if (check_desktop_scale_factor) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:" | ||
| " desktop_scale_factor is not within valid range" | ||
| " of [100, 500]. Assuming 100. Value was: %d", | ||
| monitor_layout->desktop_scale_factor); | ||
| } | ||
|
|
||
| int check_device_scale_factor | ||
| = monitor_layout->device_scale_factor != 100 | ||
| && monitor_layout->device_scale_factor != 140 | ||
| && monitor_layout->device_scale_factor != 180; | ||
| if (check_device_scale_factor) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "sanitise_extended_monitor_attributes:" | ||
| " device_scale_factor a valid value (One of 100, 140, 180)." | ||
| " Assuming 100. Value was: %d", | ||
| monitor_layout->device_scale_factor); | ||
| } | ||
|
|
||
| if (check_desktop_scale_factor || check_device_scale_factor) | ||
| { | ||
| monitor_layout->desktop_scale_factor = 100; | ||
| monitor_layout->device_scale_factor = 100; | ||
| } | ||
| } | ||
|
|
||
| /*****************************************************************************/ | ||
| /* | ||
| Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message. | ||
|
|
@@ -1907,87 +1999,11 @@ libxrdp_process_monitor_stream(struct stream *s, | |
|
|
||
| in_uint32_le(s, monitor_layout->physical_width); | ||
| in_uint32_le(s, monitor_layout->physical_height); | ||
|
|
||
| /* Per spec (2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT), | ||
| * if EITHER physical_width or physical_height are | ||
| * out of range, BOTH must be ignored. | ||
| */ | ||
| if (monitor_layout->physical_width > 10000 | ||
| || monitor_layout->physical_width < 10) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:" | ||
| " physical_width is not within valid range." | ||
| " Setting physical_width to 0mm," | ||
| " Setting physical_height to 0mm," | ||
| " physical_width was: %d", | ||
| monitor_layout->physical_width); | ||
| monitor_layout->physical_width = 0; | ||
| monitor_layout->physical_height = 0; | ||
| } | ||
|
|
||
| if (monitor_layout->physical_height > 10000 | ||
| || monitor_layout->physical_height < 10) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:" | ||
| " physical_height is not within valid range." | ||
| " Setting physical_width to 0mm," | ||
| " Setting physical_height to 0mm," | ||
| " physical_height was: %d", | ||
| monitor_layout->physical_height); | ||
| monitor_layout->physical_width = 0; | ||
| monitor_layout->physical_height = 0; | ||
| } | ||
|
|
||
| in_uint32_le(s, monitor_layout->orientation); | ||
| switch (monitor_layout->orientation) | ||
| { | ||
| case ORIENTATION_LANDSCAPE: | ||
| case ORIENTATION_PORTRAIT: | ||
| case ORIENTATION_LANDSCAPE_FLIPPED: | ||
| case ORIENTATION_PORTRAIT_FLIPPED: | ||
| break; | ||
| default: | ||
| LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:" | ||
| " Orientation is not one of %d, %d, %d, or %d." | ||
| " Value was %d and ignored and set to default value of LANDSCAPE.", | ||
| ORIENTATION_LANDSCAPE, | ||
| ORIENTATION_PORTRAIT, | ||
| ORIENTATION_LANDSCAPE_FLIPPED, | ||
| ORIENTATION_PORTRAIT_FLIPPED, | ||
| monitor_layout->orientation); | ||
| monitor_layout->orientation = ORIENTATION_LANDSCAPE; | ||
| } | ||
|
|
||
| in_uint32_le(s, monitor_layout->desktop_scale_factor); | ||
| int check_desktop_scale_factor | ||
| = monitor_layout->desktop_scale_factor < 100 | ||
| || monitor_layout->desktop_scale_factor > 500; | ||
| if (check_desktop_scale_factor) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:" | ||
| " desktop_scale_factor is not within valid range" | ||
| " of [100, 500]. Assuming 100. Value was: %d", | ||
| monitor_layout->desktop_scale_factor); | ||
| } | ||
|
|
||
| in_uint32_le(s, monitor_layout->device_scale_factor); | ||
| int check_device_scale_factor | ||
| = monitor_layout->device_scale_factor != 100 | ||
| && monitor_layout->device_scale_factor != 140 | ||
| && monitor_layout->device_scale_factor != 180; | ||
| if (check_device_scale_factor) | ||
| { | ||
| LOG(LOG_LEVEL_WARNING, "libxrdp_process_monitor_stream:" | ||
| " device_scale_factor a valid value (One of 100, 140, 180)." | ||
| " Assuming 100. Value was: %d", | ||
| monitor_layout->device_scale_factor); | ||
| } | ||
|
|
||
| if (check_desktop_scale_factor || check_device_scale_factor) | ||
| { | ||
| monitor_layout->desktop_scale_factor = 100; | ||
| monitor_layout->device_scale_factor = 100; | ||
| } | ||
| sanitise_extended_monitor_attributes(monitor_layout); | ||
|
|
||
| /* | ||
| * 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT | ||
|
|
@@ -2137,5 +2153,108 @@ libxrdp_process_monitor_stream(struct stream *s, | |
| monitor_layout->bottom = | ||
| monitor_layout->bottom - all_monitors_encompassing_bounds.top; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| /*****************************************************************************/ | ||
| int | ||
| libxrdp_process_monitor_ex_stream(struct stream *s, | ||
| struct display_size_description *description) | ||
| { | ||
| uint32_t num_monitor; | ||
| uint32_t monitor_index; | ||
| uint32_t attribute_size; | ||
| struct monitor_info *monitor_layout; | ||
|
|
||
| LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_process_monitor_ex_stream:"); | ||
| if (description == NULL) | ||
| { | ||
| LOG_DEVEL(LOG_LEVEL_ERROR, "libxrdp_process_monitor_ex_stream: " | ||
| "description was null. " | ||
| " Valid pointer to allocated description expected."); | ||
| return SEC_PROCESS_MONITORS_ERR; | ||
| } | ||
|
|
||
| if (!s_check_rem_and_log(s, 4, | ||
| "libxrdp_process_monitor_ex_stream:" | ||
| " Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR_EX")) | ||
| { | ||
| return SEC_PROCESS_MONITORS_ERR; | ||
| } | ||
|
|
||
| in_uint32_le(s, attribute_size); | ||
| if (attribute_size != TS_MONITOR_ATTRIBUTES_SIZE) | ||
| { | ||
| LOG(LOG_LEVEL_ERROR, | ||
| "libxrdp_process_monitor_ex_stream: [MS-RDPBCGR] Protocol" | ||
| " error: TS_UD_CS_MONITOR_EX monitorAttributeSize" | ||
| " MUST be %d, received: %d", | ||
| TS_MONITOR_ATTRIBUTES_SIZE, attribute_size); | ||
| return SEC_PROCESS_MONITORS_ERR; | ||
| } | ||
|
|
||
| in_uint32_le(s, num_monitor); | ||
| LOG(LOG_LEVEL_DEBUG, "libxrdp_process_monitor_ex_stream:" | ||
| " The number of monitors received is: %d", | ||
| num_monitor); | ||
|
|
||
| if (num_monitor != description->monitorCount) | ||
| { | ||
| LOG(LOG_LEVEL_ERROR, | ||
| "libxrdp_process_monitor_ex_stream: [MS-RDPBCGR] Protocol" | ||
| " error: TS_UD_CS_MONITOR monitorCount" | ||
| " MUST be %d, received: %d", | ||
| description->monitorCount, num_monitor); | ||
| return SEC_PROCESS_MONITORS_ERR; | ||
| } | ||
|
|
||
| for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index) | ||
| { | ||
| if (!s_check_rem_and_log(s, attribute_size, | ||
| "libxrdp_process_monitor_ex_stream:" | ||
| " Parsing TS_UD_CS_MONITOR_EX")) | ||
| { | ||
| return SEC_PROCESS_MONITORS_ERR; | ||
| } | ||
|
|
||
| monitor_layout = description->minfo + monitor_index; | ||
|
|
||
| in_uint32_le(s, monitor_layout->physical_width); | ||
| in_uint32_le(s, monitor_layout->physical_height); | ||
| in_uint32_le(s, monitor_layout->orientation); | ||
| in_uint32_le(s, monitor_layout->desktop_scale_factor); | ||
| in_uint32_le(s, monitor_layout->device_scale_factor); | ||
|
|
||
| sanitise_extended_monitor_attributes(monitor_layout); | ||
|
|
||
| LOG_DEVEL(LOG_LEVEL_INFO, "libxrdp_process_monitor_ex_stream:" | ||
| " Received [MS-RDPBCGR] 2.2.1.3.9.1 " | ||
| " TS_MONITOR_ATTRIBUTES" | ||
| " Index: %d, PhysicalWidth %d, PhysicalHeight %d," | ||
| " Orientation %d, DesktopScaleFactor %d," | ||
| " DeviceScaleFactor %d", | ||
| monitor_index, | ||
| monitor_layout->physical_width, | ||
| monitor_layout->physical_height, | ||
| monitor_layout->orientation, | ||
| monitor_layout->desktop_scale_factor, | ||
| monitor_layout->device_scale_factor); | ||
| } | ||
|
|
||
| /* Update non negative monitor info values */ | ||
| const struct monitor_info *src = description->minfo; | ||
| struct monitor_info *dst = description->minfo_wm; | ||
| for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index) | ||
| { | ||
| dst->physical_width = src->physical_width; | ||
| dst->physical_height = src->physical_height; | ||
| dst->orientation = src->orientation; | ||
| dst->desktop_scale_factor = src->desktop_scale_factor; | ||
| dst->device_scale_factor = src->device_scale_factor; | ||
| ++src; | ||
| ++dst; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not put
session_physical_width(and height) intodisplay_size_description? It contains the information for all the monitors in addition to summary information such as the size of the full session.Also, this doesn't seem to have logic that would be at parity with
session_height/width-- Those are for computing the height/width of the ENTIRE session. Is there a similar computation for the physical width/height of the ENTIRE session when it's provided for all monitors?I think also, how do we deal with DPI if multiple monitors are provided that each have a different scale factor? Pick the highest DPI? Lowest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funnily enough I started down that route. Eventually however it occurred to me that it didn't make much sense.
The physical size of the desktop is easy to understand for a single monitor, and actually has a use, which is to calculate the DPI for the monitor (in the absence of any other information). For multiple monitors however, which may not even be touching in any way, the overall physical size is not something that can be defined. For example, what would you do in a situation like this with a gap between the monitors?
So eventually I removed the overall physical size from the
display_size_description, and just left the values from the CORE message further down the structure as a fallback, in case extended monitor information isn't available. These could be renamed maybe, if it's not clear what is going on.Dealing with the DPI on the login screen is easy - the login screen only appears on the primary monitor, so that's the only monitor we need to worry about.