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 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 29 ResetCsrProcess(VOID) 30 { 31 if (gpepCSRSS) 32 ObDereferenceObject(gpepCSRSS); 33 34 gpepCSRSS = NULL; 35 } 36 37 NTSTATUS 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 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 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 */ 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 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