Skip to content

Commit 823dcb5

Browse files
committed
mutli session suipport
1 parent bb6690d commit 823dcb5

10 files changed

Lines changed: 949 additions & 109 deletions

File tree

base/system/smss/smss.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,74 @@ _main(IN INT argc,
514514
}
515515
SmpReleasePrivilege(State);
516516

517+
/*
518+
* Bring up a second session (MuSession 1). smss is the session leader
519+
* and is now sessionless again, so it can create another kernel session,
520+
* load that session's subsystems (its own csrss) and launch its initial
521+
* command (winlogon) - exactly what the SB API SmpStartCsr does for a
522+
* remote session-create request, just driven directly here.
523+
*
524+
* Gated behind HKLM\SYSTEM\CCS\Control\Session Manager:EnableSecondSession
525+
* (DWORD, default 0): the kernel session create, the per-session win32k
526+
* load (session-image reuse path) and the per-session object namespaces
527+
* all work, but session 1's csrss still trips deep per-session win32k GUI
528+
* issues, so it is opt-in until that is finished.
529+
*/
530+
{
531+
ULONG EnableSecondSession = 0;
532+
RTL_QUERY_REGISTRY_TABLE SecondSessionQueryTable[2];
533+
534+
RtlZeroMemory(SecondSessionQueryTable, sizeof(SecondSessionQueryTable));
535+
SecondSessionQueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
536+
SecondSessionQueryTable[0].Name = L"EnableSecondSession";
537+
SecondSessionQueryTable[0].EntryContext = &EnableSecondSession;
538+
SecondSessionQueryTable[0].DefaultType = REG_DWORD;
539+
SecondSessionQueryTable[0].DefaultData = &EnableSecondSession;
540+
SecondSessionQueryTable[0].DefaultLength = sizeof(EnableSecondSession);
541+
RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
542+
L"Session Manager",
543+
SecondSessionQueryTable,
544+
NULL,
545+
NULL);
546+
547+
if (EnableSecondSession)
548+
{
549+
ULONG Session1Id = 1;
550+
HANDLE Session1WinSubSysPid = NULL;
551+
HANDLE Session1Command = NULL;
552+
UNICODE_STRING Session1InitialCommand;
553+
554+
RtlInitEmptyUnicodeString(&Session1InitialCommand, NULL, 0);
555+
556+
DPRINT1("SMSS: Bringing up session %lu\n", Session1Id);
557+
Status = SmpLoadSubSystemsForMuSession(&Session1Id,
558+
&Session1WinSubSysPid,
559+
&Session1InitialCommand);
560+
if (!NT_SUCCESS(Status))
561+
{
562+
DPRINT1("SMSS: SmpLoadSubSystemsForMuSession(%lu) failed - 0x%x\n",
563+
Session1Id, Status);
564+
}
565+
else
566+
{
567+
Status = SmpExecuteInitialCommand(Session1Id,
568+
&Session1InitialCommand,
569+
&Session1Command,
570+
NULL);
571+
if (!NT_SUCCESS(Status))
572+
{
573+
DPRINT1("SMSS: session %lu initial command failed - 0x%x\n",
574+
Session1Id, Status);
575+
}
576+
else
577+
{
578+
DPRINT1("SMSS: session %lu is up and running\n", Session1Id);
579+
if (Session1Command) NtClose(Session1Command);
580+
}
581+
}
582+
} /* if (EnableSecondSession) */
583+
}
584+
517585
/* Wait on either CSRSS or Winlogon to die */
518586
Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles),
519587
Handles,

ntoskrnl/ex/sysinfo.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,11 +1972,22 @@ SSI_DEF(SystemExtendServiceTableInformation)
19721972
sizeof(Win32kName));
19731973
}
19741974

1975-
/* Load the image */
1975+
/*
1976+
* Load the image into SESSION space. win32k is a per-session driver: every
1977+
* session maps its own physical copy at the same session-wide virtual
1978+
* address, so win32k's .data (gpsi, the USER/GDI heaps and handle tables,
1979+
* ...) is naturally per-session, while the single shadow service table -
1980+
* registered once and pointing at that shared VA - resolves to the current
1981+
* session's copy via its page tables. The first session loads it fresh; a
1982+
* later session reuses the existing entry and gets its own copy (the
1983+
* session-image reuse path in MmLoadSystemImage). The caller is attached to
1984+
* the target session here (the session was just created), so this maps into
1985+
* the right session.
1986+
*/
19761987
Status = MmLoadSystemImage((PUNICODE_STRING)Buffer,
19771988
NULL,
19781989
NULL,
1979-
0,
1990+
1,
19801991
(PVOID)&ModuleObject,
19811992
&ImageBase);
19821993

@@ -2262,6 +2273,10 @@ NTSTATUS
22622273
NTAPI
22632274
MmSessionDelete(IN ULONG SessionId);
22642275

2276+
NTSTATUS
2277+
NTAPI
2278+
MmDetachCurrentSession(VOID);
2279+
22652280
/* Class 47 - Create a new session (TSE) */
22662281
SSI_DEF(SystemSessionCreate)
22672282
{
@@ -2287,10 +2302,9 @@ SSI_DEF(SystemSessionCreate)
22872302
return Status;
22882303
}
22892304

2290-
/* Class 48 - Delete an existing session (TSE) */
2305+
/* Class 48 - Detach the calling process from its session (TSE) */
22912306
SSI_DEF(SystemSessionDetach)
22922307
{
2293-
ULONG SessionId;
22942308
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
22952309

22962310
if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
@@ -2301,11 +2315,17 @@ SSI_DEF(SystemSessionDetach)
23012315
{
23022316
return STATUS_PRIVILEGE_NOT_HELD;
23032317
}
2304-
}
23052318

2306-
SessionId = *(PULONG)Buffer;
2319+
ProbeForReadUlong(Buffer);
2320+
}
23072321

2308-
return MmSessionDelete(SessionId);
2322+
/*
2323+
* The session id is accepted for ABI compatibility but the operation always
2324+
* detaches the calling process from its current session (matching the class
2325+
* name and Windows semantics), leaving it sessionless so it can create or
2326+
* join another session.
2327+
*/
2328+
return MmDetachCurrentSession();
23092329
}
23102330

23112331
/* Class 49 - UNKNOWN */

ntoskrnl/include/internal/mm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,10 @@ MmDetachSession(
17751775
_Inout_ PVOID SessionEntry,
17761776
_Out_ PKAPC_STATE ApcState);
17771777

1778+
NTSTATUS
1779+
NTAPI
1780+
MmDetachCurrentSession(VOID);
1781+
17781782
VOID
17791783
NTAPI
17801784
MmQuitNextSession(

ntoskrnl/mm/ARM3/miarm.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,20 @@ typedef struct _MM_SESSION_SPACE
521521
} MM_SESSION_SPACE, *PMM_SESSION_SPACE;
522522

523523
extern PMM_SESSION_SPACE MmSessionSpace;
524+
525+
//
526+
// Per-session loaded-image tracking entry. Linked into
527+
// MmSessionSpace->ImageList; one per distinct image mapped into the session,
528+
// with a reference count covering repeated loads of the same image within the
529+
// session (ReactOS uses a simple list where Win10 uses an AVL ImageTree).
530+
//
531+
typedef struct _MI_SESSION_IMAGE
532+
{
533+
LIST_ENTRY Link;
534+
PVOID ImageBase;
535+
PFN_COUNT PteCount;
536+
LONG ImageCount;
537+
} MI_SESSION_IMAGE, *PMI_SESSION_IMAGE;
524538
extern MMPTE HyperTemplatePte;
525539
extern MMPDE ValidKernelPde;
526540
extern MMPTE ValidKernelPte;
@@ -1882,6 +1896,71 @@ MiInitializeSessionIds(
18821896
VOID
18831897
);
18841898

1899+
PVOID
1900+
NTAPI
1901+
MiSessionWideReserveImageAddress(
1902+
_In_ PFN_COUNT PteCount
1903+
);
1904+
1905+
VOID
1906+
NTAPI
1907+
MiSessionWideFreeImageAddress(
1908+
_In_ PVOID ImageBase,
1909+
_In_ PFN_COUNT PteCount
1910+
);
1911+
1912+
NTSTATUS
1913+
NTAPI
1914+
MiSessionCommitPageTables(
1915+
_In_ PVOID StartVa,
1916+
_In_ PVOID EndVa
1917+
);
1918+
1919+
NTSTATUS
1920+
NTAPI
1921+
MiCommitSessionImagePages(
1922+
_In_ PVOID DriverBase,
1923+
_In_ PFN_COUNT PteCount
1924+
);
1925+
1926+
VOID
1927+
NTAPI
1928+
MiFreeSessionImage(
1929+
_In_ PVOID DriverBase,
1930+
_In_ PFN_COUNT PteCount
1931+
);
1932+
1933+
VOID
1934+
NTAPI
1935+
MiTestSessionImageLoad(
1936+
VOID
1937+
);
1938+
1939+
PMI_SESSION_IMAGE
1940+
NTAPI
1941+
MiSessionLookupImage(
1942+
_In_ PVOID ImageBase
1943+
);
1944+
1945+
NTSTATUS
1946+
NTAPI
1947+
MiSessionInsertImage(
1948+
_In_ PVOID ImageBase,
1949+
_In_ PFN_COUNT PteCount
1950+
);
1951+
1952+
VOID
1953+
NTAPI
1954+
MiSessionRemoveImage(
1955+
_In_ PVOID ImageBase
1956+
);
1957+
1958+
VOID
1959+
NTAPI
1960+
MiSessionImageTeardown(
1961+
VOID
1962+
);
1963+
18851964
CODE_SEG("INIT")
18861965
BOOLEAN
18871966
NTAPI

ntoskrnl/mm/ARM3/pagfault.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,13 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
328328
}
329329
else if (MI_IS_SESSION_ADDRESS(VirtualAddress))
330330
{
331-
/* ReactOS does not have an image list yet, so bail out to failure case */
332-
ASSERT(IsListEmpty(&MmSessionSpace->ImageList));
331+
/*
332+
* Session images use a copy-based model: their pages are committed as
333+
* valid PTEs and their PDEs are demand-faulted by MiCheckPdeForSessionSpace,
334+
* so a legitimate session-image access never reaches this prototype-PTE
335+
* lookup. Anything that lands here is an access to an uncommitted session
336+
* address, which falls through to the failure case below.
337+
*/
333338
}
334339

335340
/* Default case -- failure */

ntoskrnl/mm/ARM3/section.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,8 @@ MiUnmapViewOfSection(IN PEPROCESS Process,
920920
return Status;
921921
}
922922

923-
static
924923
NTSTATUS
924+
NTAPI
925925
MiSessionCommitPageTables(IN PVOID StartVa,
926926
IN PVOID EndVa)
927927
{

0 commit comments

Comments
 (0)