Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@HBelusca
Copy link
Contributor

@HBelusca HBelusca commented Sep 19, 2025

Purpose & Proposed changes

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:

Required for @katahiromz 's ctfmon (see PR #8392) and other 3rd-party software, including some AMD software tested by @DarkFire01.

@HBelusca HBelusca self-assigned this Sep 19, 2025
@HBelusca HBelusca added enhancement For PRs with an enhancement/new feature. help wanted Request for help. no squash merge Author has no full name in GitHub profile, either merge by rebase or manually Win32SS For Win32 subsystem (Win32k, GDI/USER DLLs, etc.) related components PRs. labels Sep 19, 2025
Copy link
Contributor Author

@HBelusca HBelusca left a 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.

Comment on lines +570 to +585
#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))
Copy link
Contributor Author

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....

Copy link
Member

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?

Copy link
Contributor Author

@HBelusca HBelusca Sep 25, 2025

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...

Copy link
Member

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.

Comment on lines +625 to +634
InitializeObjectAttributes(&ObjectAttributes,
&Name,
OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
BnoHandle,
&EventSd);
Status = ZwCreateEvent(&EventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
NotificationEvent,
FALSE);
Copy link
Contributor Author

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).

@HBelusca HBelusca requested a review from ThFabba September 19, 2025 20:53
Copy link
Member

@SigmaTel71 SigmaTel71 left a 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
@HBelusca HBelusca force-pushed the win32k_switchdesktop_event branch from f771b67 to c435c1d Compare September 22, 2025 11:17
PTHREADINFO gptiDesktopThread = NULL;
HCURSOR gDesktopCursor = NULL;
PKEVENT gpDesktopThreadStartedEvent = NULL;
PKEVENT gpDesktopSwitchEvent = NULL; ///< WinSta0_DesktopSwitch event.
Copy link
Member

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.

Copy link
Contributor Author

@HBelusca HBelusca Sep 25, 2025

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.)

Copy link
Member

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.

Copy link
Contributor Author

@HBelusca HBelusca Oct 15, 2025

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.

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".

Comment on lines +570 to +585
#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))
Copy link
Member

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))
Copy link
Member

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?

Copy link
Contributor Author

@HBelusca HBelusca Sep 25, 2025

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.

Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement For PRs with an enhancement/new feature. help wanted Request for help. no squash merge Author has no full name in GitHub profile, either merge by rebase or manually Win32SS For Win32 subsystem (Win32k, GDI/USER DLLs, etc.) related components PRs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants