reactos/win32ss/user/winsrv/usersrv/init.c

304 lines
8.9 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS User API Server DLL
* FILE: win32ss/user/winsrv/usersrv/init.c
* PURPOSE: Initialization
* PROGRAMMERS: Dmitry Philippov (shedon@mail.ru)
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#include "usersrv.h"
#include "api.h" // USERSRV Public server APIs definitions
#include "../consrv/api.h" // CONSRV Public server APIs definitions
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
HINSTANCE UserServerDllInstance = NULL;
/* Handles for Power and Media events. Used by both usersrv and win32k. */
HANDLE ghPowerRequestEvent;
HANDLE ghMediaRequestEvent;
/* Copy of CSR Port handle for win32k */
HANDLE CsrApiPort = NULL;
/* Memory */
HANDLE UserServerHeap = NULL; // Our own heap.
// Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
PCSR_API_ROUTINE UserServerApiDispatchTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
{
SrvExitWindowsEx,
SrvEndTask,
SrvLogon,
SrvRegisterServicesProcess, // Not present in Win7
SrvActivateDebugger,
SrvGetThreadConsoleDesktop, // Not present in Win7
SrvDeviceEvent,
SrvRegisterLogonProcess, // Not present in Win7
SrvCreateSystemThreads,
SrvRecordShutdownReason,
// SrvCancelShutdown, // Added in Vista
// SrvConsoleHandleOperation, // Added in Win7
// SrvGetSetShutdownBlockReason, // Added in Vista
};
BOOLEAN UserServerApiServerValidTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
{
FALSE, // SrvExitWindowsEx
FALSE, // SrvEndTask
FALSE, // SrvLogon
FALSE, // SrvRegisterServicesProcess
FALSE, // SrvActivateDebugger
TRUE, // SrvGetThreadConsoleDesktop
FALSE, // SrvDeviceEvent
FALSE, // SrvRegisterLogonProcess
FALSE, // SrvCreateSystemThreads
FALSE, // SrvRecordShutdownReason
// FALSE, // SrvCancelShutdown
// FALSE, // SrvConsoleHandleOperation
// FALSE, // SrvGetSetShutdownBlockReason
};
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
/*
* On Windows Server 2003, CSR Servers contain
* the API Names Table only in Debug Builds.
*/
#ifdef CSR_DBG
PCHAR UserServerApiNameTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
{
"SrvExitWindowsEx",
"SrvEndTask",
"SrvLogon",
"SrvRegisterServicesProcess",
"SrvActivateDebugger",
"SrvGetThreadConsoleDesktop",
"SrvDeviceEvent",
"SrvRegisterLogonProcess",
"SrvCreateSystemThreads",
"SrvRecordShutdownReason",
// "SrvCancelShutdown",
// "SrvConsoleHandleOperation",
// "SrvGetSetShutdownBlockReason",
};
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#endif
/* FUNCTIONS ******************************************************************/
BOOL CALLBACK
FindTopLevelWnd(
IN HWND hWnd,
IN LPARAM lParam)
{
if (GetWindow(hWnd, GW_OWNER) == NULL)
{
*(HWND*)lParam = hWnd;
return FALSE;
}
return TRUE;
}
// PUSER_SOUND_SENTRY. Used in basesrv.dll
BOOL NTAPI _UserSoundSentry(VOID)
{
// TODO: Do something.
return TRUE;
}
ULONG
NTAPI
CreateSystemThreads(PVOID pParam)
{
2018-03-04 15:07:41 +00:00
NtUserCallOneParam((DWORD_PTR)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
RtlExitUserThread(0);
return 0;
}
/* API_NUMBER: UserpCreateSystemThreads */
CSR_API(SrvCreateSystemThreads)
{
NTSTATUS Status = CsrExecServerThread(CreateSystemThreads, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("Cannot start system thread!\n");
}
return Status;
}
/* API_NUMBER: UserpActivateDebugger */
CSR_API(SrvActivateDebugger)
{
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
}
/* API_NUMBER: UserpGetThreadConsoleDesktop */
CSR_API(SrvGetThreadConsoleDesktop)
{
NTSTATUS Status;
PUSER_GET_THREAD_CONSOLE_DESKTOP GetThreadConsoleDesktopRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.GetThreadConsoleDesktopRequest;
Status = GetThreadConsoleDesktop(GetThreadConsoleDesktopRequest->ThreadId,
&GetThreadConsoleDesktopRequest->ConsoleDesktop);
if (!NT_SUCCESS(Status))
{
DPRINT1("GetThreadConsoleDesktop(%lu) failed with Status 0x%08x\n",
GetThreadConsoleDesktopRequest->ThreadId, Status);
}
/* Windows-compatibility: Always return success since User32 relies on this! */
return STATUS_SUCCESS;
}
/* API_NUMBER: UserpDeviceEvent */
CSR_API(SrvDeviceEvent)
{
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
}
/* API_NUMBER: UserpLogon */
CSR_API(SrvLogon)
{
PUSER_LOGON LogonRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.LogonRequest;
DPRINT1("We are logged %s\n", LogonRequest->IsLogon ? "on" : "off");
/* Impersonate the caller in order to retrieve settings in its context */
if (!CsrImpersonateClient(NULL))
return STATUS_UNSUCCESSFUL;
GetTimeouts(&ShutdownSettings);
/* We are done */
CsrRevertToSelf();
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
UserClientConnect(IN PCSR_PROCESS CsrProcess,
IN OUT PVOID ConnectionInfo,
IN OUT PULONG ConnectionInfoLength)
{
NTSTATUS Status;
// PUSERCONNECT
PUSERSRV_API_CONNECTINFO ConnectInfo = (PUSERSRV_API_CONNECTINFO)ConnectionInfo;
In absence of patchbot, let's test patch directly on... trunk!! Yeah!! Let's break trunk! (or not, we'll see...) [USER32][USERSRV][WIN32K] - Flag CSRSS threads as such. - Each time a win32 thread is "created" (or a win32k system call is done) a PsConvertToGuiThread call is done, that makes a Win32ThreadCallout which calls UserCreateThreadInfo. We should call back ClientThreadSetup to set client-side info. - Introduce a ClientThreadSetupHelper function to try to understand what happens when doing direct calls to ClientThreadSetup and via win32k callbacks. - Reenable CSR call in user32::DllMain but add shame hacks in Init(..) to force NtUserProcessConnect callbacks (yet they should not be done there): see the code comment associated for more details. - Temporarily disable ClientThreadSetupHelper call in ClientThreadSetup because it makes things fail, like console input thread failing and so on... - ... and in ClientThreadSetupHelper, some correct code is commented out because it currently breaks other things (like menu initialization etc...), and HACKS ARE ADDED!! (see especially the "if (gpsi)" one, that should not exist, but if removed we fail sometimes in MenuInit because gpsi becomes NULL for some reason, if some other code that makes redundant calls to NtUserProcessConnect, is uncommented). To sum up I tried to scaffold the thing as it should be, but with disabled code to not break everything. CORE-8949 #comment Revision 65799 committed the patch v1. svn path=/trunk/; revision=65799
2014-12-22 21:23:00 +00:00
DPRINT("UserClientConnect\n");
/* Check if we don't have an API port yet */
if (CsrApiPort == NULL)
{
/* Query the API port and save it globally */
CsrApiPort = CsrQueryApiPort();
/* Inform win32k about the API port */
Status = NtUserSetInformationThread(NtCurrentThread(),
UserThreadCsrApiPort,
&CsrApiPort,
sizeof(CsrApiPort));
if (!NT_SUCCESS(Status))
{
return Status;
}
}
/* Check connection info validity */
if ( ConnectionInfo == NULL ||
ConnectionInfoLength == NULL ||
*ConnectionInfoLength != sizeof(*ConnectInfo) )
{
DPRINT1("USERSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), expected %lu\n",
ConnectionInfo,
ConnectionInfoLength,
ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1,
sizeof(*ConnectInfo));
return STATUS_INVALID_PARAMETER;
}
/* Pass the request to win32k */
ConnectInfo->dwDispatchCount = 0; // gDispatchTableValues;
Status = NtUserProcessConnect(CsrProcess->ProcessHandle,
ConnectInfo,
*ConnectionInfoLength);
return Status;
}
CSR_SERVER_DLL_INIT(UserServerDllInitialization)
{
NTSTATUS Status;
/* Initialize the memory */
UserServerHeap = RtlGetProcessHeap();
/* Setup the DLL Object */
LoadedServerDll->ApiBase = USERSRV_FIRST_API_NUMBER;
LoadedServerDll->HighestApiSupported = UserpMaxApiNumber;
LoadedServerDll->DispatchTable = UserServerApiDispatchTable;
LoadedServerDll->ValidTable = UserServerApiServerValidTable;
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#ifdef CSR_DBG
LoadedServerDll->NameTable = UserServerApiNameTable;
[CSR] During my investigations for making working Win2k3 csrsrv.dll (or other CSR servers) into ROS (to compare our behaviour with our own csrsrv.dll and Win2k3 one), I hit a problem: if I test a checked-build version of csrsrv (or other CSR servers), everything was fine when they were loaded, but if I use a release-build version (i.e. without any debug information), I systematically hit a memory access violation which was traced back to the moment when a CSR server's CsrInitialization entry point was called. So I did the experiment, where I used our (debug-build) csrsrv with a free-build win2k3 CSR server dll (it was winsrv.dll, and I retested with basesrv.dll after). I hit the access violation. But if I took a debug-build version of winsrv.dll, everything was OK. I then added in our csrsrv' server.c file the following line (around line 212 of the current file version): DPRINT1("%s ; ServerDll->ValidTable = 0x%p ; ServerDll->NameTable = 0x%p ; ServerDll->SizeOfProcessData = %d ; ServerDll->ConnectCallback = 0x%p\n", DllString, ServerDll->ValidTable, ServerDll->NameTable, ServerDll->SizeOfProcessData, ServerDll->ConnectCallback); and I saw that, when using a debug-build win2k3 CSR server, everything was fine (in particular the ServerDll->SizeOfProcessData member contained a reasonable value, e.g. a size of 88 bytes), whereas if I used a free-build version, I got an off-by-one problem, with the ServerDll->ValidTable pointer valid but the ServerDll->NameTable member being equal to 88 (i.e. invalid pointer) and the ServerDll->SizeOfProcessData member being equal to a very large value, which looked like a pointer value. After more investigations, I saw that in debug-build CSR servers the list of API names were stored, whereas it was not the case in free-build versions. Therefore I concluded that the API names table was included *ONLY* in debug builds and not in release builds. Hence, to be able to test in ROS either debug-builds or release-builds versions of Windows CSR servers in ROS (and vice-versa), I introduced a #define called CSR_DBG, which is defined only if the DBG macro is != 0, and which is not defined otherwise. When the CSR_DBG flag is defined, API names tables are added in CSR servers and otherwise, they are not. Therefore, we are now able to test debug-build Windows CSR servers in ROS (the default possibility) or free-build versions of these CSR servers (but first, we have to build the other ones without the CSR_DBG flag, to avoid the off-by-one problem described above). svn path=/trunk/; revision=60560
2013-10-06 13:33:17 +00:00
#endif
LoadedServerDll->SizeOfProcessData = 0;
LoadedServerDll->ConnectCallback = UserClientConnect;
LoadedServerDll->DisconnectCallback = NULL;
LoadedServerDll->HardErrorCallback = UserServerHardError;
LoadedServerDll->ShutdownProcessCallback = UserClientShutdown;
UserServerDllInstance = LoadedServerDll->ServerHandle;
/* Create the power request event */
Status = NtCreateEvent(&ghPowerRequestEvent,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Power request event creation failed with Status 0x%08x\n", Status);
return Status;
}
/* Create the media request event */
Status = NtCreateEvent(&ghMediaRequestEvent,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Media request event creation failed with Status 0x%08x\n", Status);
return Status;
}
/* Set the process creation notify routine for BASE */
BaseSetProcessCreateNotify(NtUserNotifyProcessCreate);
/* Initialize the hard errors cache */
UserInitHardErrorsCache();
/* Initialize the kernel mode subsystem */
Status = NtUserInitialize(USER_VERSION,
ghPowerRequestEvent,
ghMediaRequestEvent);
if (!NT_SUCCESS(Status))
{
DPRINT1("NtUserInitialize failed with Status 0x%08x\n", Status);
return Status;
}
/* All done */
return STATUS_SUCCESS;
}
/* EOF */