[WINLOGON][USER32]

Fix the explanations of how Windows/ReactOS should shut down (it's winlogon itself that calls NtShutdownSystem, not something else; that story about "SMSS API #1" concerns the SMSS API SmpSessionCompleteApi called by the helper function SmSessionComplete which is in turn called by CSRSS function CsrDereferenceNtSession, when all win32 processes are gone, as it should).
The webpage http://www.reactos.org/wiki/ShutdownProcess should be corrected for.

[USER32]
Whitespace fixes for winstation code.

svn path=/trunk/; revision=66275
This commit is contained in:
Hermès Bélusca-Maïto 2015-02-15 02:07:23 +00:00
parent 61ec2f8e01
commit 4c28eeae21
3 changed files with 215 additions and 236 deletions

View file

@ -898,7 +898,8 @@ HandleShutdown(
/* Destroy SAS window */ /* Destroy SAS window */
UninitializeSAS(Session); UninitializeSAS(Session);
FIXME("FIXME: Call SMSS API #1\n"); /* Now we can shut down NT */
ERR("Shutting down NT...\n");
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT) if (wlxAction == WLX_SAS_ACTION_SHUTDOWN_REBOOT)
{ {

View file

@ -17,10 +17,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
* *
* - App (usually explorer) calls ExitWindowsEx() * - App (usually explorer) calls ExitWindowsEx()
* - ExitWindowsEx() sends a message to CSRSS * - ExitWindowsEx() sends a message to CSRSS
* - CSRSS impersonates the caller and sends a message to a hidden WinLogon window * - CSRSS impersonates the caller and sends a message to a hidden Winlogon window
* - WinLogon checks if the caller has the required privileges * - Winlogon checks if the caller has the required privileges
* - WinLogon enters pending log-out state * - Winlogon enters pending log-out state
* - WinLogon impersonates the interactive user and calls ExitWindowsEx() again, * - Winlogon impersonates the interactive user and calls ExitWindowsEx() again,
* passing some special internal flags * passing some special internal flags
* - CSRSS loops over all processes of the interactive user (sorted by their * - CSRSS loops over all processes of the interactive user (sorted by their
* SetProcessShutdownParameters() level), sending WM_QUERYENDSESSION and * SetProcessShutdownParameters() level), sending WM_QUERYENDSESSION and
@ -39,28 +39,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
* If the handler doesn't respond in time the same activities as for GUI * If the handler doesn't respond in time the same activities as for GUI
* apps (i.e. display dialog box etc) take place. This also happens if * apps (i.e. display dialog box etc) take place. This also happens if
* the handler returns TRUE. * the handler returns TRUE.
* - This ends the processing for the first ExitWindowsEx() call from WinLogon. * - This ends the processing for the first ExitWindowsEx() call from Winlogon.
* Execution continues in WinLogon, which calls ExitWindowsEx() again to * Execution continues in Winlogon, which calls ExitWindowsEx() again to
* terminate COM processes in the interactive user's session. * terminate COM processes in the interactive user's session.
* - WinLogon stops impersonating the interactive user (whose processes are * - Winlogon stops impersonating the interactive user (whose processes are
* all dead by now). and enters log-out state * all dead by now). and enters log-out state
* - If the ExitWindowsEx() request was for a logoff, WinLogon sends a SAS * - If the ExitWindowsEx() request was for a logoff, Winlogon sends a SAS
* event (to display the "press ctrl+alt+del") to the GINA. WinLogon then * event (to display the "press ctrl+alt+del") to the GINA. Winlogon then
* waits for the GINA to send a SAS event to login. * waits for the GINA to send a SAS event to login.
* - If the ExitWindowsEx() request was for shutdown/restart, WinLogon calls * - If the ExitWindowsEx() request was for shutdown/restart, Winlogon calls
* ExitWindowsEx() again in the system process context. * ExitWindowsEx() again in the system process context.
* - CSRSS goes through the motions of sending WM_QUERYENDSESSION/WM_ENDSESSION * - CSRSS goes through the motions of sending WM_QUERYENDSESSION/WM_ENDSESSION
* to GUI processes running in the system process context but won't display * to GUI processes running in the system process context but won't display
* dialog boxes or kill threads/processes. Same for console processes, * dialog boxes or kill threads/processes. Same for console processes,
* using the CTRL_SHUTDOWN_EVENT. The Service Control Manager is one of * using the CTRL_SHUTDOWN_EVENT. The Service Control Manager is one of
* these console processes and has a special timeout value WaitToKillServiceTimeout. * these console processes and has a special timeout value WaitToKillServiceTimeout.
* - WinLogon issues a "InitiateSystemShutdown" request to the SM (SMSS API # 1) * - After CSRSS has finished its pass notifying processes that system is shutting down,
* - the SM propagates the shutdown request to every environment subsystem it * Winlogon finishes the shutdown process by calling the executive subsystem
* started since bootstrap time (still active ones, of course) * function NtShutdownSystem.
* - each environment subsystem, on shutdown request, releases every resource
* it aquired during its life (processes, memory etc), then dies
* - when every environment subsystem has gone to bed, the SM actually initiates
* the kernel and executive shutdown by calling NtShutdownSystem.
*/ */
typedef struct typedef struct

View file

@ -19,9 +19,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(winsta);
*/ */
HWINSTA WINAPI HWINSTA WINAPI
CreateWindowStationA(LPCSTR lpwinsta, CreateWindowStationA(LPCSTR lpwinsta,
DWORD dwReserved, DWORD dwReserved,
ACCESS_MASK dwDesiredAccess, ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpsa) LPSECURITY_ATTRIBUTES lpsa)
{ {
UNICODE_STRING WindowStationNameU; UNICODE_STRING WindowStationNameU;
HWINSTA hWinSta; HWINSTA hWinSta;
@ -53,55 +53,55 @@ CreateWindowStationA(LPCSTR lpwinsta,
*/ */
HWINSTA WINAPI HWINSTA WINAPI
CreateWindowStationW(LPCWSTR lpwinsta, CreateWindowStationW(LPCWSTR lpwinsta,
DWORD dwReserved, DWORD dwReserved,
ACCESS_MASK dwDesiredAccess, ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpsa) LPSECURITY_ATTRIBUTES lpsa)
{ {
UNICODE_STRING WindowStationName; UNICODE_STRING WindowStationName;
UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations"); UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hWindowStationsDir; HANDLE hWindowStationsDir;
NTSTATUS Status; NTSTATUS Status;
HWINSTA hwinsta; HWINSTA hwinsta;
/* Open WindowStations directory */ /* Open WindowStations directory */
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&WindowStationsDir, &WindowStationsDir,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
0, 0,
0); 0);
Status = NtOpenDirectoryObject(&hWindowStationsDir, Status = NtOpenDirectoryObject(&hWindowStationsDir,
DIRECTORY_CREATE_OBJECT, DIRECTORY_CREATE_OBJECT,
&ObjectAttributes); &ObjectAttributes);
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
ERR("Failed to open WindowStations directory\n"); ERR("Failed to open WindowStations directory\n");
return NULL; return NULL;
} }
RtlInitUnicodeString(&WindowStationName, lpwinsta); RtlInitUnicodeString(&WindowStationName, lpwinsta);
/* Create the window station object */ /* Create the window station object */
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&WindowStationName, &WindowStationName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
hWindowStationsDir, hWindowStationsDir,
0); 0);
/* Check if the handle should be inheritable */ /* Check if the handle should be inheritable */
if (lpsa && lpsa->bInheritHandle) if (lpsa && lpsa->bInheritHandle)
{ {
ObjectAttributes.Attributes |= OBJ_INHERIT; ObjectAttributes.Attributes |= OBJ_INHERIT;
} }
hwinsta = NtUserCreateWindowStation(&ObjectAttributes, hwinsta = NtUserCreateWindowStation(&ObjectAttributes,
dwDesiredAccess, dwDesiredAccess,
0, 0, 0, 0, 0); 0, 0, 0, 0, 0);
NtClose(hWindowStationsDir); NtClose(hWindowStationsDir);
return hwinsta; return hwinsta;
} }
/* /*
@ -110,87 +110,78 @@ CreateWindowStationW(LPCWSTR lpwinsta,
BOOL FASTCALL BOOL FASTCALL
EnumNamesW(HWINSTA WindowStation, EnumNamesW(HWINSTA WindowStation,
NAMEENUMPROCW EnumFunc, NAMEENUMPROCW EnumFunc,
LPARAM Context, LPARAM Context,
BOOL Desktops) BOOL Desktops)
{ {
char Buffer[256]; CHAR Buffer[256];
PVOID NameList; PVOID NameList;
PWCHAR Name; PWCHAR Name;
NTSTATUS Status; NTSTATUS Status;
ULONG RequiredSize; ULONG RequiredSize;
ULONG CurrentEntry, EntryCount; ULONG CurrentEntry, EntryCount;
BOOL Ret; BOOL Ret;
/* /* Check parameters */
* Check parameters if (WindowStation == NULL && Desktops)
*/ {
if (NULL == WindowStation && Desktops) WindowStation = GetProcessWindowStation();
{ }
WindowStation = GetProcessWindowStation();
}
/* /* Try with fixed-size buffer */
* Try with fixed-size buffer Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize);
*/ if (NT_SUCCESS(Status))
Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize); {
if (NT_SUCCESS(Status)) /* Fixed-size buffer is large enough */
{ NameList = (PWCHAR) Buffer;
/* Fixed-size buffer is large enough */ }
NameList = (PWCHAR) Buffer; else if (Status == STATUS_BUFFER_TOO_SMALL)
} {
else if (Status == STATUS_BUFFER_TOO_SMALL) /* Allocate a larger buffer */
{ NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
/* Allocate a larger buffer */ if (NameList == NULL)
NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize); return FALSE;
if (NULL == NameList)
{
return FALSE;
}
/* Try again */
Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL);
if (! NT_SUCCESS(Status))
{
HeapFree(GetProcessHeap(), 0, NameList);
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
}
else
{
/* Some unrecognized error occured */
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
/* /* Try again */
* Enum the names one by one Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL);
*/ if (!NT_SUCCESS(Status))
EntryCount = *((DWORD *) NameList); {
Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD)); HeapFree(GetProcessHeap(), 0, NameList);
Ret = TRUE; SetLastError(RtlNtStatusToDosError(Status));
for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry) return FALSE;
{ }
Ret = (*EnumFunc)(Name, Context); }
Name += wcslen(Name) + 1; else
} {
/* Some unrecognized error occured */
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
/* /* Enum the names one by one */
* Cleanup EntryCount = *((DWORD *) NameList);
*/ Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD));
if (NameList != Buffer) Ret = TRUE;
{ for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry)
HeapFree(GetProcessHeap(), 0, NameList); {
} Ret = (*EnumFunc)(Name, Context);
Name += wcslen(Name) + 1;
}
return Ret; /* Cleanup */
if (NameList != Buffer)
{
HeapFree(GetProcessHeap(), 0, NameList);
}
return Ret;
} }
/* For W->A conversion */ /* For W->A conversion */
typedef struct tagENUMNAMESASCIICONTEXT typedef struct tagENUMNAMESASCIICONTEXT
{ {
NAMEENUMPROCA UserEnumFunc; NAMEENUMPROCA UserEnumFunc;
LPARAM UserContext; LPARAM UserContext;
} ENUMNAMESASCIICONTEXT, *PENUMNAMESASCIICONTEXT; } ENUMNAMESASCIICONTEXT, *PENUMNAMESASCIICONTEXT;
/* /*
@ -200,65 +191,59 @@ typedef struct tagENUMNAMESASCIICONTEXT
BOOL CALLBACK BOOL CALLBACK
EnumNamesCallback(LPWSTR Name, LPARAM Param) EnumNamesCallback(LPWSTR Name, LPARAM Param)
{ {
PENUMNAMESASCIICONTEXT Context = (PENUMNAMESASCIICONTEXT) Param; PENUMNAMESASCIICONTEXT Context = (PENUMNAMESASCIICONTEXT) Param;
char FixedNameA[32]; CHAR FixedNameA[32];
LPSTR NameA; LPSTR NameA;
int Len; INT Len;
BOOL Ret; BOOL Ret;
/* /*
* Determine required size of Ascii string and see if we can use * Determine required size of Ascii string and see
* fixed buffer * if we can use fixed buffer.
*/ */
Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL); Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL);
if (Len <= 0) if (Len <= 0)
{ {
/* Some strange error occured */ /* Some strange error occured */
return FALSE; return FALSE;
} }
else if (Len <= sizeof(FixedNameA)) else if (Len <= sizeof(FixedNameA))
{ {
/* Fixed-size buffer is large enough */ /* Fixed-size buffer is large enough */
NameA = FixedNameA; NameA = FixedNameA;
} }
else else
{ {
/* Allocate a larger buffer */ /* Allocate a larger buffer */
NameA = HeapAlloc(GetProcessHeap(), 0, Len); NameA = HeapAlloc(GetProcessHeap(), 0, Len);
if (NULL == NameA) if (NULL == NameA)
{ {
SetLastError(ERROR_NOT_ENOUGH_MEMORY); SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE; return FALSE;
} }
} }
/* /* Do the Unicode ->Ascii conversion */
* Do the Unicode ->Ascii conversion if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL))
*/ {
if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL)) /* Something went wrong, clean up */
{ if (NameA != FixedNameA)
/* Something went wrong, clean up */ {
if (NameA != FixedNameA) HeapFree(GetProcessHeap(), 0, NameA);
{ }
HeapFree(GetProcessHeap(), 0, NameA); return FALSE;
} }
return FALSE;
}
/* /* Call user callback */
* Call user callback Ret = Context->UserEnumFunc(NameA, Context->UserContext);
*/
Ret = Context->UserEnumFunc(NameA, Context->UserContext);
/* /* Cleanup */
* Clean up if (NameA != FixedNameA)
*/ {
if (NameA != FixedNameA) HeapFree(GetProcessHeap(), 0, NameA);
{ }
HeapFree(GetProcessHeap(), 0, NameA);
}
return Ret; return Ret;
} }
/* /*
@ -267,15 +252,15 @@ EnumNamesCallback(LPWSTR Name, LPARAM Param)
BOOL FASTCALL BOOL FASTCALL
EnumNamesA(HWINSTA WindowStation, EnumNamesA(HWINSTA WindowStation,
NAMEENUMPROCA EnumFunc, NAMEENUMPROCA EnumFunc,
LPARAM Context, LPARAM Context,
BOOL Desktops) BOOL Desktops)
{ {
ENUMNAMESASCIICONTEXT PrivateContext; ENUMNAMESASCIICONTEXT PrivateContext;
PrivateContext.UserEnumFunc = EnumFunc; PrivateContext.UserEnumFunc = EnumFunc;
PrivateContext.UserContext = Context; PrivateContext.UserContext = Context;
return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops); return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops);
} }
/* /*
@ -283,9 +268,9 @@ EnumNamesA(HWINSTA WindowStation,
*/ */
BOOL WINAPI BOOL WINAPI
EnumWindowStationsA(WINSTAENUMPROCA EnumFunc, EnumWindowStationsA(WINSTAENUMPROCA EnumFunc,
LPARAM Context) LPARAM Context)
{ {
return EnumNamesA(NULL, EnumFunc, Context, FALSE); return EnumNamesA(NULL, EnumFunc, Context, FALSE);
} }
@ -294,9 +279,9 @@ EnumWindowStationsA(WINSTAENUMPROCA EnumFunc,
*/ */
BOOL WINAPI BOOL WINAPI
EnumWindowStationsW(WINSTAENUMPROCW EnumFunc, EnumWindowStationsW(WINSTAENUMPROCW EnumFunc,
LPARAM Context) LPARAM Context)
{ {
return EnumNamesW(NULL, EnumFunc, Context, FALSE); return EnumNamesW(NULL, EnumFunc, Context, FALSE);
} }
@ -305,8 +290,8 @@ EnumWindowStationsW(WINSTAENUMPROCW EnumFunc,
*/ */
HWINSTA WINAPI HWINSTA WINAPI
OpenWindowStationA(LPCSTR lpszWinSta, OpenWindowStationA(LPCSTR lpszWinSta,
BOOL fInherit, BOOL fInherit,
ACCESS_MASK dwDesiredAccess) ACCESS_MASK dwDesiredAccess)
{ {
UNICODE_STRING WindowStationNameU; UNICODE_STRING WindowStationNameU;
HWINSTA hWinSta; HWINSTA hWinSta;
@ -340,48 +325,48 @@ OpenWindowStationW(LPCWSTR lpszWinSta,
BOOL fInherit, BOOL fInherit,
ACCESS_MASK dwDesiredAccess) ACCESS_MASK dwDesiredAccess)
{ {
UNICODE_STRING WindowStationName; UNICODE_STRING WindowStationName;
UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations"); UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hWindowStationsDir; HANDLE hWindowStationsDir;
NTSTATUS Status; NTSTATUS Status;
HWINSTA hwinsta; HWINSTA hwinsta;
/* Open WindowStations directory */ /* Open WindowStations directory */
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&WindowStationsDir, &WindowStationsDir,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
0, 0,
0); 0);
Status = NtOpenDirectoryObject(&hWindowStationsDir, Status = NtOpenDirectoryObject(&hWindowStationsDir,
DIRECTORY_TRAVERSE, DIRECTORY_TRAVERSE,
&ObjectAttributes); &ObjectAttributes);
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
ERR("Failed to open WindowStations directory\n"); ERR("Failed to open WindowStations directory\n");
return NULL; return NULL;
} }
/* Open the window station object */ /* Open the window station object */
RtlInitUnicodeString(&WindowStationName, lpszWinSta); RtlInitUnicodeString(&WindowStationName, lpszWinSta);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
&WindowStationName, &WindowStationName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
hWindowStationsDir, hWindowStationsDir,
0); 0);
if( fInherit ) if(fInherit)
{ {
ObjectAttributes.Attributes |= OBJ_INHERIT; ObjectAttributes.Attributes |= OBJ_INHERIT;
} }
hwinsta = NtUserOpenWindowStation(&ObjectAttributes, dwDesiredAccess); hwinsta = NtUserOpenWindowStation(&ObjectAttributes, dwDesiredAccess);
NtClose(hWindowStationsDir); NtClose(hWindowStationsDir);
return hwinsta; return hwinsta;
} }
@ -390,15 +375,12 @@ OpenWindowStationW(LPCWSTR lpszWinSta,
*/ */
BOOL BOOL
WINAPI WINAPI
SetWindowStationUser( SetWindowStationUser(HWINSTA hWindowStation,
HWINSTA hWindowStation, PLUID pluid,
PLUID pluid, PSID psid,
PSID psid, DWORD size)
DWORD size
)
{ {
return NtUserSetWindowStationUser(hWindowStation, pluid, psid, size); return NtUserSetWindowStationUser(hWindowStation, pluid, psid, size);
} }
/* EOF */ /* EOF */