xref: /reactos/win32ss/user/winsrv/usersrv/init.c (revision 98e8827a)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS User API Server DLL
4  * FILE:            win32ss/user/winsrv/usersrv/init.c
5  * PURPOSE:         Initialization
6  * PROGRAMMERS:     Dmitry Philippov (shedon@mail.ru)
7  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include "usersrv.h"
13 #include "api.h"            // USERSRV Public server APIs definitions
14 #include "../consrv/api.h"  //  CONSRV Public server APIs definitions
15 
16 #define NDEBUG
17 #include <debug.h>
18 
19 /* GLOBALS ********************************************************************/
20 
21 HINSTANCE UserServerDllInstance = NULL;
22 
23 /* Handles for Power and Media events. Used by both usersrv and win32k. */
24 HANDLE ghPowerRequestEvent;
25 HANDLE ghMediaRequestEvent;
26 
27 /* Copy of CSR Port handle for win32k */
28 HANDLE CsrApiPort = NULL;
29 
30 /* Memory */
31 HANDLE UserServerHeap = NULL;   // Our own heap.
32 
33 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
34 PCSR_API_ROUTINE UserServerApiDispatchTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
35 {
36     SrvExitWindowsEx,
37     SrvEndTask,
38     SrvLogon,
39     SrvRegisterServicesProcess, // Not present in Win7
40     SrvActivateDebugger,
41     SrvGetThreadConsoleDesktop, // Not present in Win7
42     SrvDeviceEvent,
43     SrvRegisterLogonProcess,    // Not present in Win7
44     SrvCreateSystemThreads,
45     SrvRecordShutdownReason,
46     // SrvCancelShutdown,              // Added in Vista
47     // SrvConsoleHandleOperation,      // Added in Win7
48     // SrvGetSetShutdownBlockReason,   // Added in Vista
49 };
50 
51 BOOLEAN UserServerApiServerValidTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
52 {
53     FALSE,   // SrvExitWindowsEx
54     FALSE,   // SrvEndTask
55     FALSE,   // SrvLogon
56     FALSE,   // SrvRegisterServicesProcess
57     FALSE,   // SrvActivateDebugger
58     TRUE,    // SrvGetThreadConsoleDesktop
59     FALSE,   // SrvDeviceEvent
60     FALSE,   // SrvRegisterLogonProcess
61     FALSE,   // SrvCreateSystemThreads
62     FALSE,   // SrvRecordShutdownReason
63     // FALSE,   // SrvCancelShutdown
64     // FALSE,   // SrvConsoleHandleOperation
65     // FALSE,   // SrvGetSetShutdownBlockReason
66 };
67 
68 /*
69  * On Windows Server 2003, CSR Servers contain
70  * the API Names Table only in Debug Builds.
71  */
72 #ifdef CSR_DBG
73 PCHAR UserServerApiNameTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] =
74 {
75     "SrvExitWindowsEx",
76     "SrvEndTask",
77     "SrvLogon",
78     "SrvRegisterServicesProcess",
79     "SrvActivateDebugger",
80     "SrvGetThreadConsoleDesktop",
81     "SrvDeviceEvent",
82     "SrvRegisterLogonProcess",
83     "SrvCreateSystemThreads",
84     "SrvRecordShutdownReason",
85     // "SrvCancelShutdown",
86     // "SrvConsoleHandleOperation",
87     // "SrvGetSetShutdownBlockReason",
88 };
89 #endif
90 
91 /* FUNCTIONS ******************************************************************/
92 
93 BOOL CALLBACK
94 FindTopLevelWnd(
95     IN HWND hWnd,
96     IN LPARAM lParam)
97 {
98     if (GetWindow(hWnd, GW_OWNER) == NULL)
99     {
100         *(HWND*)lParam = hWnd;
101         return FALSE;
102     }
103     return TRUE;
104 }
105 
106 // PUSER_SOUND_SENTRY. Used in basesrv.dll
107 BOOL NTAPI _UserSoundSentry(VOID)
108 {
109     // TODO: Do something.
110     return TRUE;
111 }
112 
113 ULONG
114 NTAPI
115 CreateSystemThreads(PVOID pParam)
116 {
117     NtUserCallOneParam((DWORD_PTR)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
118     RtlExitUserThread(0);
119     return 0;
120 }
121 
122 /* API_NUMBER: UserpCreateSystemThreads */
123 CSR_API(SrvCreateSystemThreads)
124 {
125     NTSTATUS Status = CsrExecServerThread(CreateSystemThreads, 0);
126     if (!NT_SUCCESS(Status))
127     {
128         DPRINT1("Cannot start system thread!\n");
129     }
130 
131     return Status;
132 }
133 
134 /* API_NUMBER: UserpActivateDebugger */
135 CSR_API(SrvActivateDebugger)
136 {
137     DPRINT1("%s not yet implemented\n", __FUNCTION__);
138     return STATUS_NOT_IMPLEMENTED;
139 }
140 
141 /* API_NUMBER: UserpGetThreadConsoleDesktop */
142 CSR_API(SrvGetThreadConsoleDesktop)
143 {
144     NTSTATUS Status;
145     PUSER_GET_THREAD_CONSOLE_DESKTOP GetThreadConsoleDesktopRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.GetThreadConsoleDesktopRequest;
146 
147     Status = GetThreadConsoleDesktop(GetThreadConsoleDesktopRequest->ThreadId,
148                                      &GetThreadConsoleDesktopRequest->ConsoleDesktop);
149     if (!NT_SUCCESS(Status))
150     {
151         DPRINT1("GetThreadConsoleDesktop(%lu) failed with Status 0x%08x\n",
152                 GetThreadConsoleDesktopRequest->ThreadId, Status);
153     }
154 
155     /* Windows-compatibility: Always return success since User32 relies on this! */
156     return STATUS_SUCCESS;
157 }
158 
159 /* API_NUMBER: UserpDeviceEvent */
160 CSR_API(SrvDeviceEvent)
161 {
162     DPRINT1("%s not yet implemented\n", __FUNCTION__);
163     return STATUS_NOT_IMPLEMENTED;
164 }
165 
166 /* API_NUMBER: UserpLogon */
167 CSR_API(SrvLogon)
168 {
169     PUSER_LOGON LogonRequest = &((PUSER_API_MESSAGE)ApiMessage)->Data.LogonRequest;
170 
171     DPRINT1("We are logged %s\n", LogonRequest->IsLogon ? "on" : "off");
172 
173     /* Impersonate the caller in order to retrieve settings in its context */
174     if (!CsrImpersonateClient(NULL))
175         return STATUS_UNSUCCESSFUL;
176 
177     GetTimeouts(&ShutdownSettings);
178 
179     /* We are done */
180     CsrRevertToSelf();
181     return STATUS_SUCCESS;
182 }
183 
184 NTSTATUS
185 NTAPI
186 UserClientConnect(IN PCSR_PROCESS CsrProcess,
187                   IN OUT PVOID  ConnectionInfo,
188                   IN OUT PULONG ConnectionInfoLength)
189 {
190     NTSTATUS Status;
191     // PUSERCONNECT
192     PUSERSRV_API_CONNECTINFO ConnectInfo = (PUSERSRV_API_CONNECTINFO)ConnectionInfo;
193 
194     DPRINT("UserClientConnect\n");
195 
196     /* Check if we don't have an API port yet */
197     if (CsrApiPort == NULL)
198     {
199         /* Query the API port and save it globally */
200         CsrApiPort = CsrQueryApiPort();
201 
202         /* Inform win32k about the API port */
203         Status = NtUserSetInformationThread(NtCurrentThread(),
204                                             UserThreadCsrApiPort,
205                                             &CsrApiPort,
206                                             sizeof(CsrApiPort));
207         if (!NT_SUCCESS(Status))
208         {
209             return Status;
210         }
211     }
212 
213     /* Check connection info validity */
214     if ( ConnectionInfo       == NULL ||
215          ConnectionInfoLength == NULL ||
216         *ConnectionInfoLength != sizeof(*ConnectInfo) )
217     {
218         DPRINT1("USERSRV: Connection failed - ConnectionInfo = 0x%p ; ConnectionInfoLength = 0x%p (%lu), expected %lu\n",
219                 ConnectionInfo,
220                 ConnectionInfoLength,
221                 ConnectionInfoLength ? *ConnectionInfoLength : (ULONG)-1,
222                 sizeof(*ConnectInfo));
223 
224         return STATUS_INVALID_PARAMETER;
225     }
226 
227     /* Pass the request to win32k */
228     ConnectInfo->dwDispatchCount = 0; // gDispatchTableValues;
229     Status = NtUserProcessConnect(CsrProcess->ProcessHandle,
230                                   ConnectInfo,
231                                   *ConnectionInfoLength);
232 
233     return Status;
234 }
235 
236 CSR_SERVER_DLL_INIT(UserServerDllInitialization)
237 {
238     NTSTATUS Status;
239 
240     /* Initialize the memory */
241     UserServerHeap = RtlGetProcessHeap();
242 
243     /* Setup the DLL Object */
244     LoadedServerDll->ApiBase = USERSRV_FIRST_API_NUMBER;
245     LoadedServerDll->HighestApiSupported = UserpMaxApiNumber;
246     LoadedServerDll->DispatchTable = UserServerApiDispatchTable;
247     LoadedServerDll->ValidTable = UserServerApiServerValidTable;
248 #ifdef CSR_DBG
249     LoadedServerDll->NameTable = UserServerApiNameTable;
250 #endif
251     LoadedServerDll->SizeOfProcessData = 0;
252     LoadedServerDll->ConnectCallback = UserClientConnect;
253     LoadedServerDll->DisconnectCallback = NULL;
254     LoadedServerDll->HardErrorCallback = UserServerHardError;
255     LoadedServerDll->ShutdownProcessCallback = UserClientShutdown;
256 
257     UserServerDllInstance = LoadedServerDll->ServerHandle;
258 
259     /* Create the power request event */
260     Status = NtCreateEvent(&ghPowerRequestEvent,
261                            EVENT_ALL_ACCESS,
262                            NULL,
263                            SynchronizationEvent,
264                            FALSE);
265     if (!NT_SUCCESS(Status))
266     {
267         DPRINT1("Power request event creation failed with Status 0x%08x\n", Status);
268         return Status;
269     }
270 
271     /* Create the media request event */
272     Status = NtCreateEvent(&ghMediaRequestEvent,
273                            EVENT_ALL_ACCESS,
274                            NULL,
275                            SynchronizationEvent,
276                            FALSE);
277     if (!NT_SUCCESS(Status))
278     {
279         DPRINT1("Media request event creation failed with Status 0x%08x\n", Status);
280         return Status;
281     }
282 
283     /* Set the process creation notify routine for BASE */
284     BaseSetProcessCreateNotify(NtUserNotifyProcessCreate);
285 
286     /* Initialize the hard errors cache */
287     UserInitHardErrorsCache();
288 
289     /* Initialize the kernel mode subsystem */
290     Status = NtUserInitialize(USER_VERSION,
291                               ghPowerRequestEvent,
292                               ghMediaRequestEvent);
293     if (!NT_SUCCESS(Status))
294     {
295         DPRINT1("NtUserInitialize failed with Status 0x%08x\n", Status);
296         return Status;
297     }
298 
299     /* All done */
300     return STATUS_SUCCESS;
301 }
302 
303 /* EOF */
304