- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2k
[WIN32SS:NTUSER] Implement desktop-switch notification by event #8393
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
base: master
Are you sure you want to change the base?
Conversation
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.
@tkreuzer @ThFabba @learn-more I would like to hear you about these questions I have.
| #if 0 | ||
| /* Create the switch event handle in the CSRSS context, | ||
| * so as to associate it with a good process owner */ | ||
| KAPC_STATE ApcState; | ||
| KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState); | ||
| InitializeObjectAttributes(&ObjectAttributes, | ||
| &Name, | ||
| OBJ_OPENIF | OBJ_CASE_INSENSITIVE, | ||
| BnoHandle, | ||
| &EventSd); | ||
| Status = ZwCreateEvent(&EventHandle, | ||
| EVENT_ALL_ACCESS, | ||
| &ObjectAttributes, | ||
| NotificationEvent, | ||
| FALSE); | ||
| if (!NT_SUCCESS(Status)) | 
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.
Here, I would like to have the advice of kernel programming experts, regarding the best way to create that named event, so that:
- win32k then retrieves the object itself,
- but we make it so that CSRSS becomes the process that "owns" this event by making it having a handle to the event opened. So that, when looking with ProcessMonitor for example, we see that it's CSRSS who has an opened handle to \BaseNamedObjects\WinSta0_DesktopSwitch, instead of any other process (like the caller's , or the System process).
I have made two possible solutions, the first one is this one, where I KeStackAttachProcess() to CSRSS prior to invoking ZwCreateEvent() BUT such that I get a user-mode handle (no OBJ_KERNEL_HANDLE), then retrieve the actual object out of the handle....
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.
So why doesn't csrss create this event in the first place, and then win32k just grabs a handle to it?
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.
So why doesn't csrss create this event in the first place, and then win32k just grabs a handle to it?
Csrss is just hosting some win32 usermode stuff.
The winsta0 Desktopswitch event is created only when the first winsta0 interactive windowstation is created, by an API call made usually by winlogon...
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.
One other thing that happens when the first window station is created is that the desktop thread and the raw input thread are created. This is triggered by winlogon and the two threads are created in the context of csrss. We could move the creation of the switch event in the desktop thread effectively creating the event from the context of csrss.
| InitializeObjectAttributes(&ObjectAttributes, | ||
| &Name, | ||
| OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, | ||
| BnoHandle, | ||
| &EventSd); | ||
| Status = ZwCreateEvent(&EventHandle, | ||
| EVENT_ALL_ACCESS, | ||
| &ObjectAttributes, | ||
| NotificationEvent, | ||
| FALSE); | 
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.
..... or, this second solution, where I create the event and get a kernel handle to it, then retrieve its underlying object, THEN attach to CSRSS in order to re-open the object such that I get a user-mode handle to it (2nd parameter of ObOpenObjectByPointer() being 0 instead of OBJ_KERNEL_HANDLE).
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.
Approving per code style.
…tos#8393) On desktop switching (triggered e.g. via `user32!SwitchDesktop()`), the per-session `\BaseNamedObjects\WinSta0_DesktopSwitch` event is pulsed for notifying any waiters that a desktop switch occurred. For Vista+ support, send also the `EVENT_SYSTEM_DESKTOPSWITCH` window event. References: - https://microsoft.public.win32.programmer.kernel.narkive.com/ZyolgdrA/event-or-callback-when-system-s-desktop-is-changed - https://sourceforge.net/p/classicshell/feature-requests/204/#bc3e
f771b67    to
    c435c1d      
    Compare
  
    | PTHREADINFO gptiDesktopThread = NULL; | ||
| HCURSOR gDesktopCursor = NULL; | ||
| PKEVENT gpDesktopThreadStartedEvent = NULL; | ||
| PKEVENT gpDesktopSwitchEvent = NULL; ///< WinSta0_DesktopSwitch event. | 
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.
Is there something depending on this name?
If not, then it might make sense to indicate that it is a legacy thing.
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.
I don't understand your question.
But yes, "WinSta0_DesktopSwitch" is the expected name of the event created, so that apps can open it to wait on i, and this still exists in windows, so I don't see why it's a "legacy thing".
(See the links in the pr description.)
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.
gpDesktopSwitchEvent is the name I was referring to.
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.
gpDesktopSwitchEventis the name I was referring to.
gpDesktopSwitchEvent is the object pointer variable name (like all the others above it), which is used in the code.
The comment next to it, indicates for the reader which exposed (in the NT object namespace) global named event this object pointer refers to; that is, "\BasedNamedObjects\WinSta0_DesktopSwitch".
| #if 0 | ||
| /* Create the switch event handle in the CSRSS context, | ||
| * so as to associate it with a good process owner */ | ||
| KAPC_STATE ApcState; | ||
| KeStackAttachProcess(&gpepCSRSS->Pcb, &ApcState); | ||
| InitializeObjectAttributes(&ObjectAttributes, | ||
| &Name, | ||
| OBJ_OPENIF | OBJ_CASE_INSENSITIVE, | ||
| BnoHandle, | ||
| &EventSd); | ||
| Status = ZwCreateEvent(&EventHandle, | ||
| EVENT_ALL_ACCESS, | ||
| &ObjectAttributes, | ||
| NotificationEvent, | ||
| FALSE); | ||
| if (!NT_SUCCESS(Status)) | 
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.
So why doesn't csrss create this event in the first place, and then win32k just grabs a handle to it?
| // FIXME! TODO: Add this new window station to a linked list | ||
|  | ||
| if (InputWindowStation == NULL) | ||
| if (InputWindowStation == WindowStation) // (!(WindowStation->Flags & WSS_NOIO)) | 
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 is this flag commented out behind it?
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.
Since currently we have two ways to decide whether a given windowstation is interactive (has the flag unset, and also, pointer is equal to the single global one), I was basically documenting this fact.
I could turn this into an assert.
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.
A comment like this is not useful, especially if you don't explain why it is there in the comment.
So either remove it, or clarify them.
Purpose & Proposed changes
On desktop switching (triggered e.g. via
user32!SwitchDesktop()), the per-session\BaseNamedObjects\WinSta0_DesktopSwitchevent is pulsed for notifying any waiters that a desktop switch occurred. For Vista+ support, send also theEVENT_SYSTEM_DESKTOPSWITCHwindow event.References:
Required for @katahiromz 's ctfmon (see PR #8392) and other 3rd-party software, including some AMD software tested by @DarkFire01.