1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Interface between Win32k and USERSRV
5 * FILE: win32ss/user/ntuser/csr.c
6 * PROGRAMMER: Hermes Belusca-Maito (hermes.belusca@sfr.fr), based on
7 * the original code by Ge van Geldorp (ge@gse.nl) and by
8 * the CSR code in NTDLL.
9 */
10
11 #include <win32k.h>
12
13 DBG_DEFAULT_CHANNEL(UserCsr);
14
15 PEPROCESS gpepCSRSS = NULL;
16 PVOID CsrApiPort = NULL;
17 DWORD gdwPendingSystemThreads = 0;
18
19 VOID
InitCsrProcess(VOID)20 InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
21 {
22 /* Save the EPROCESS of CSRSS */
23 gpepCSRSS = PsGetCurrentProcess();
24 // gpepCSRSS = CsrProcess;
25 ObReferenceObject(gpepCSRSS);
26 }
27
28 VOID
ResetCsrProcess(VOID)29 ResetCsrProcess(VOID)
30 {
31 if (gpepCSRSS)
32 ObDereferenceObject(gpepCSRSS);
33
34 gpepCSRSS = NULL;
35 }
36
37 NTSTATUS
InitCsrApiPort(IN HANDLE CsrPortHandle)38 InitCsrApiPort(IN HANDLE CsrPortHandle)
39 {
40 NTSTATUS Status;
41
42 Status = ObReferenceObjectByHandle(CsrPortHandle,
43 0,
44 /* * */LpcPortObjectType, // or NULL,
45 UserMode,
46 &CsrApiPort,
47 NULL);
48 if (!NT_SUCCESS(Status))
49 {
50 CsrApiPort = NULL;
51 ERR("Failed to set CSR API Port.\n");
52 }
53
54 return Status;
55 }
56
57 VOID
ResetCsrApiPort(VOID)58 ResetCsrApiPort(VOID)
59 {
60 if (CsrApiPort)
61 ObDereferenceObject(CsrApiPort);
62
63 CsrApiPort = NULL;
64 }
65
66 /*
67 * Function copied from ntdll/csr/connect.c::CsrClientCallServer
68 * and adapted for kernel-mode.
69 *
70 * NOTE: This is really a co_* function!
71 */
72 NTSTATUS
73 NTAPI
CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL,IN CSR_API_NUMBER ApiNumber,IN ULONG DataLength)74 CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
75 IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL,
76 IN CSR_API_NUMBER ApiNumber,
77 IN ULONG DataLength)
78 {
79 NTSTATUS Status;
80 #if 0
81 ULONG PointerCount;
82 PULONG_PTR OffsetPointer;
83 #endif
84
85 /* Do we have a connection to CSR yet? */
86 if (!CsrApiPort)
87 return STATUS_INVALID_PORT_HANDLE;
88
89 /* Fill out the Port Message Header */
90 ApiMessage->Header.u2.ZeroInit = 0;
91 ApiMessage->Header.u1.s1.TotalLength = FIELD_OFFSET(CSR_API_MESSAGE, Data) + DataLength;
92 ApiMessage->Header.u1.s1.DataLength = ApiMessage->Header.u1.s1.TotalLength -
93 sizeof(ApiMessage->Header);
94
95 /* Fill out the CSR Header */
96 ApiMessage->ApiNumber = ApiNumber;
97 ApiMessage->CsrCaptureData = NULL;
98
99 TRACE("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
100 ApiNumber,
101 ApiMessage->Header.u1.s1.DataLength,
102 ApiMessage->Header.u1.s1.TotalLength);
103
104 #if 0
105 /* Check if we got a Capture Buffer */
106 if (CaptureBuffer)
107 {
108 /*
109 * We have to convert from our local (client) view
110 * to the remote (server) view.
111 */
112 ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
113 ((ULONG_PTR)CaptureBuffer + CsrPortMemoryDelta);
114
115 /* Lock the buffer. */
116 CaptureBuffer->BufferEnd = NULL;
117
118 /*
119 * Each client pointer inside the CSR message is converted into
120 * a server pointer, and each pointer to these message pointers
121 * is converted into an offset.
122 */
123 PointerCount = CaptureBuffer->PointerCount;
124 OffsetPointer = CaptureBuffer->PointerOffsetsArray;
125 while (PointerCount--)
126 {
127 if (*OffsetPointer != 0)
128 {
129 *(PULONG_PTR)*OffsetPointer += CsrPortMemoryDelta;
130 *OffsetPointer -= (ULONG_PTR)ApiMessage;
131 }
132 ++OffsetPointer;
133 }
134 }
135 #endif
136
137 UserLeaveCo();
138
139 /* Send the LPC Message */
140
141 // The wait logic below is subject to change in the future. One can
142 // imagine adding an external parameter to CsrClientCallServer, or write
143 // two versions of CsrClientCallServer, synchronous and asynchronous.
144 if (PsGetCurrentProcess() == gpepCSRSS)
145 {
146 Status = LpcRequestPort(CsrApiPort,
147 &ApiMessage->Header);
148 }
149 else
150 {
151 Status = LpcRequestWaitReplyPort(CsrApiPort,
152 &ApiMessage->Header,
153 &ApiMessage->Header);
154 }
155
156 UserEnterCo();
157
158 #if 0
159 /* Check if we got a Capture Buffer */
160 if (CaptureBuffer)
161 {
162 /*
163 * We have to convert back from the remote (server) view
164 * to our local (client) view.
165 */
166 ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER)
167 ((ULONG_PTR)ApiMessage->CsrCaptureData - CsrPortMemoryDelta);
168
169 /*
170 * Convert back the offsets into pointers to CSR message
171 * pointers, and convert back these message server pointers
172 * into client pointers.
173 */
174 PointerCount = CaptureBuffer->PointerCount;
175 OffsetPointer = CaptureBuffer->PointerOffsetsArray;
176 while (PointerCount--)
177 {
178 if (*OffsetPointer != 0)
179 {
180 *OffsetPointer += (ULONG_PTR)ApiMessage;
181 *(PULONG_PTR)*OffsetPointer -= CsrPortMemoryDelta;
182 }
183 ++OffsetPointer;
184 }
185 }
186 #endif
187
188 /* Check for success */
189 if (!NT_SUCCESS(Status))
190 {
191 /* We failed. Overwrite the return value with the failure. */
192 ERR("LPC Failed: %lx\n", Status);
193 ApiMessage->Status = Status;
194 }
195
196 /* Return the CSR Result */
197 TRACE("Got back: 0x%lx\n", ApiMessage->Status);
198 return ApiMessage->Status;
199 }
200
201 /*
202 * UserSystemThreadProc
203 *
204 * Called form dedicated thread in CSRSS. RIT is started in context of this
205 * thread because it needs valid Win32 process with TEB initialized.
206 */
UserSystemThreadProc(BOOL bRemoteProcess)207 DWORD UserSystemThreadProc(BOOL bRemoteProcess)
208 {
209 DWORD Type;
210
211 if (!gdwPendingSystemThreads)
212 {
213 ERR("gdwPendingSystemThreads is 0!\n");
214 return 0;
215 }
216
217 /* Decide which thread this will be */
218 if (gdwPendingSystemThreads & ST_RIT)
219 Type = ST_RIT;
220 else if (gdwPendingSystemThreads & ST_DESKTOP_THREAD)
221 Type = ST_DESKTOP_THREAD;
222 else
223 Type = ST_GHOST_THREAD;
224
225 ASSERT(Type);
226
227 /* We will handle one of these threads right here so unmark it as pending */
228 gdwPendingSystemThreads &= ~Type;
229
230 UserLeave();
231
232 TRACE("UserSystemThreadProc: %d\n", Type);
233
234 switch (Type)
235 {
236 case ST_RIT: RawInputThreadMain(); break;
237 case ST_DESKTOP_THREAD: DesktopThreadMain(); break;
238 case ST_GHOST_THREAD: UserGhostThreadEntry(); break;
239 default: ERR("Wrong type: %x\n", Type);
240 }
241
242 UserEnterShared();
243
244 return 0;
245 }
246
UserCreateSystemThread(DWORD Type)247 BOOL UserCreateSystemThread(DWORD Type)
248 {
249 USER_API_MESSAGE ApiMessage;
250 PUSER_CREATE_SYSTEM_THREAD pCreateThreadRequest = &ApiMessage.Data.CreateSystemThreadRequest;
251
252 TRACE("UserCreateSystemThread: %d\n", Type);
253
254 ASSERT(UserIsEnteredExclusive());
255
256 if (gdwPendingSystemThreads & Type)
257 {
258 ERR("System thread 0x%x already pending for creation\n", Type);
259 return TRUE;
260 }
261
262 /* We can't pass a parameter to the new thread so mark what the new thread needs to do */
263 gdwPendingSystemThreads |= Type;
264
265 /* Ask winsrv to create a new system thread. This new thread will enter win32k again calling UserSystemThreadProc */
266 pCreateThreadRequest->bRemote = FALSE;
267 CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
268 NULL,
269 CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpCreateSystemThreads),
270 sizeof(USER_CREATE_SYSTEM_THREAD));
271 if (!NT_SUCCESS(ApiMessage.Status))
272 {
273 ERR("Csr call failed!\n");
274 return FALSE;
275 }
276
277 return TRUE;
278 }
279
280 /* EOF */
281